Am working on a little project to make a convolution core, and i have been surprised by the fact hls_video.h and hls_opencv.h have been deprecated, making the tutorials i was following much less useful.
So now i am trying to implement the Conv2D with LineBuffer that is in the examples of Vivado HLS. ( and also in this link )
Can anyone guide me a little i want to pass an image from to the program on the testbench, How can i do it without the openCV libraries ?
After i export the generated design to Vivado i get an “ap_ctrl” port but Vivado doesn’t let me connect GPIO nor anything to it,
How can i control the core ?
If i put a Constant with “1” would that mean that the core would be always on ?
When i try to validate the design Vivado tells me it lacks a “Tlast” which i understood was important for AXI_Stream, Where can i get this signal from ?
is it one of these DST_TVALID or DST_TREADY on the 11x11 filter core that i should wire to AXI2mm_tlast ?
one last question is , supposing i got ta bitstream and then ran it on the PYNQ ,
how would i be able to pass ta test image to it ?
at which address should i send it with python ?
I suspect it should be an address on the DMA that i should configure on the adress bar on vivado , but i am still a bit confused and the AXI documentation i s super vast and i got lost on there mayt times.
Hi,
Unfortunately there are a few issues with that example for what you are trying to do.
I’d suggest you use an AXI lite interface for the control port. This is a memory mapped interface, so you can then control your IP (start/stop, status) by reading/writing registers in the IP that are generated as part of the AXI lite interface.
You can do this by adding this inside your function: #pragma HLS INTERFACE s_axilite port=return
You can then start your IP by writing the value 0x81 to register zero of the IP.
You can also “bundle” the height/width parameters into this AXI lite interface. They will get their own register that you can use to configure these values
(For reference, the ap_ctrl port is a bundle of 4 wires. You should be able to expand it and connect GPIO to each individual wire - but I’m suggesting you switch this to an AXI lite interface)
To send an image you allocate some memory and do a DMA transfer to the IP. The DMA reads from memory and streams (through the AXI stream interface) to the IP. You use the DMA to read from the output stream of the IP and it writes back to memory.
Thank you a lot for this very detailed answer !
If i understand correctly once i redesign everything, my python JupyterNotebook should talk to :
1-The AXI lite (by writing 0x81 which i guess is (10000001)b)
2-The DMA (by sending the image)
I will find the addresses i should write to in the hwh generated by Vivado HLS ?
Thanks again for your time and very complete answer !
Apologies, I should have explained that part further.
When you generate the IP with an AXI lite interface, a control register is generated at offset 0.
An example C driver will also be generated. In your HLS “solution” directory, you should be able to find the driver here:
\impl\ip\drivers\your_ip_name\src
If you check this file, you should be able to find the info below.
your_ip_name_hw.h
// control
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved
This is a convention, but by default all HLS IP will have the control register mapped here if you use the pragma I mentioned in the previous reply. #pragma HLS INTERFACE s_axilite port=return
0x81 is setting ap_start, and also auto_restart. (auto restart is optional, you can write a 0x1 every time you want your IP to run instead).
You can also read this register to check the status of the IP (bits 1,2,3)
In the same header you should find details for any other registers in your design. For example, the offset for the heigh and width registers if you choose to include them.
Hello !
I still have some more questions regarding the TLAST, if am not too being too much trouble.
I have been looking at the posts you directed me to, and am indeed suffering from their same problem.
I understood that the workaround has been to add this condition that implements a ‘1’ at the end of the output array from the operation ( dst[size].last ).
and i am not able to do it this simply as on the examples you pointed me to, as you expected the hls:stream type doesn’t store an array to let me append a ‘1’ to it.
I cannot therefore keep the code in the example in Vivado HLS, are there no simple fix to refactor the code to make it generate the TLAST ?
I have been thinking of making the T type in the prototypes of the Conv Example similar to the AXIS_T in the resize tutorial examples you sent me and then add that condition.
but i am a bit confused since the vertical and horizontal Convolutions seem to be unrolled in different for loops.
You can’t use the hls:stream type for this. You can see the workaround to use a custom struct and have a “last”.
In the code you copied, this is the axis_t type which is this (in header file):
I’ve tried that workaround on another project, using the functions from the HelloWorld repo, however I am getting the following error using Vitis 2020.2,
type 'hls::stream<DATATYPE, 2>' (aka 'stream<ap_uint<8>, 2>') does not provide a subscript operator
Do you know what could be causing that?
Also, in the new Composable pipeline repo, the author stops using that pre-defined conversion functions and starts using xf::cv::AXIvideo2xfMat. Does that mean that Vitis libraries streaming functions are working know?
Another question, what would be the benefits of using an AXI streaming + DMA besides using AXI memory mapped, for example, when implementing Vitis vision library functions? What would be the differences, pros and cons about the two options?