03-26-2018 06:03 AM
Bidirectional streams are not supported in vivado HLS. However we would like to have it in our design. We have following situation.
We have a stream in_out_stream. It reads data from 2 blocks init and producer_consumer block. Init block initialises the system by putting initial data into the stream. the producer_consumer block reads the data and writes the data to the in_out_stream as per some logic. We created one stream in_out_stream and tried in_out_stream.read() and in_out_stream.write(). During synthesis we get message saying that the stream cannot be bidirectional. So we are thinking of the following scheme. In this scheme, there will be one stream in_out_stream. It will be directly connected to the producer consumer block which will read from the stream. However, when it has to write to the stream, it will send the data to another block which will multiplex the data between init and the producer_consumer block. ctrl_flag will be the control to the multiplexor. Output of multiplexor will be connected to in_out_stream. Is this a good implementation? Is there any other way around?
Basically we want to read struct from the in_out_stream. The in_out_stream is a stream of free pointer. We consume it if suitable. Also, when we produce a free pointer, it is written to the in_out_stream. In a way, the in_out_stream holds a list of free pointers. We could add free pointers or consume free pointers there.
In the beginning, all the free pointers are added to the stream by the init block.
How do we implement this?
03-27-2018 03:25 AM
Hmm, interesting problem. So what you want is essentially a FIFO where you can "prime" it externally (eg. from the Zynq CPU) but after that the block handles everything by itself?
One option I can see is to have a dual-port RAM, with one port connected to the block internals and the other to the CPU. CPU initializes the RAM and starts the block; the HLS block can then use the RAM either as a FIFO or a stack (either is easy), adding or removing pointers as required. You can achieve this easily using a array defined with the s_axilite interface.
Another way would be to have the FIFO/stack completely inside the block (as an array), with a stream provided from an external source for initialization. When the block starts, it reads some number of elements from the stream to populate its FIFO/stack and then everything else happens internally. This has the advantage that the block can use both ports (when you use an AXI Lite interface, one port is permanently connected to that interface so there's only one port for the block to use).
You can definitely have a block producing and consuming its own streams, but this seems like an awkward way to achieve what you want.