.. rst-class:: break_before AXI-Stream ========== Hardware Interface ------------------ The AXI-Stream interface is very simple in nature. There are only three signals, namely ``tdata``, ``tvalid`` and ``tready``. The signals ``tdata`` and ``tvalid`` are driven by the master (the data source) whereas ``tready`` is driven by the slave (data sink). .. image:: ../img/axi-stream-blocks.drawio.png :alt: AXI-Stream Configuration :align: center | The data on ``tdata`` is considered valid when both ``tvalid`` and ``tready`` are asserted high. .. warning:: Depending on the direction you want to send data, the role of master and slave change. Sending from PS to PL, the PS is the master. When sending from PL to PS, the instance providing the stream in the PL is the master. .. only:: builder_html Below, you can see a timing diagram of several AXI-Stream transactions. .. wavedrom:: { "signal": [ {"name": "clk", "wave": "p............"}, [ 'Master', {"name": "tdata", "wave": "x=.===..===x.", node: '.A', "data": ["0x43D0001", "0x43D0002", "0x43D0003", "0x43D0004", "0x43D0005", "0x43D0006", "0x43D0007"]}, {"name": "tvalid", "wave": "01.01..01...."}, ], {}, [ 'Slave', {"name": "tready", "wave": "1..0.1......."}, {"name": "stream", "wave": ".x=...=..===x", node: '..B', "data": ["0x43D0001", "0x43D0004", "0x43D0005", "0x43D0006", "0x43D0007"]} ] ], edge: [ 'A~>B' ], "config": { "hscale": 2 } } | There are a few things to keep in mind when designing AXI-Stream compatible blocks: - Once ``tvalid`` is asserted, it must not be de-asserted before ``tready`` has been asserted. - Once ``tvalid`` is asserted, ``tdata`` must not be changed until ``tready`` has been asserted. - Once ``tready`` is asserted, it must not be de-asserted before ``tvalid`` has been asserted Combining multiple AXI-Streams ------------------------------ It may occur that your design has multiple data sources that you would like to stream to the host. In that case, you can implement multiple AXI-Stream masters and then combine them to a single AXI-Stream. Worry not! The combination of multiple AXI-Streams is provided as a Xilinx IP. The IP that you need to select is called `AXI4-Stream Interconnect RTL`. This is a block that not only supports the simple AXI-Stream interface described above, but also allows for routing the streams to different destinations and allows for arbitration between many sources of AXI-Streams. AXI4-Stream Interconnect IP ~~~~~~~~~~~~~~~~~~~~~~~~~~~ You have the following options to set. - Set the `Number of slave interfaces` to your number of AXI-Stream masters (sources) - Select `Use TDATA signal` You want this because otherwise there is no data line. - Set `Interconnect switch TDATA width` to 4. You'd like to transfer 32 bits per transfer. This is a limitation of XiBIF. - Deselect `TSTRB`, `Use TKEEP signal`, `Use TLAST signal`, `Use TID signal`, `Use TDEST signal`, `Use TUSER signal` and `Use ACLKEN signal`. These signals provide more advanced options for routing AXI-Streams. - Set the `Arbiter Type` to `Round-Robin`. By default, it makes the most sense to let each stream send data after the other. Now select the `Slave Interface` tab. - Set all `Data Width` fields to 4. - If your slaves send data simultaneously, you will want to set the `FIFO Mode` to `Normal`. This allows multiple slaves to apply data at the same time and the AXI Interconnect IP to store the data until the slave is selected to send data. Move to the `Master Interface` tab. - Set the `Data Width` field to 4. .. note:: The same principles apply to the PS to PL stream connection. Distinguishing between Streams ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As things tend to be, allowing multiple AXI-Streams to be combined comes with an associated cost. Namely, you need to mark your data at the hardware level to be able to distinguish the data packets at the software level on the host. Most of the time, this can be achieved by including a `header` in the data that is sent. As a consequence, the 32 bits per packet can no longer be used for pure data. Some bits need to be reserved for the header. .. note:: If you can `guarantee` that data always arrives in a certain order, you may not need to have a header. The hardware acts predictably, so if you know the pattern of the data being written, you can decode it on the host according to that pattern. Most of the time, though, this is much too complicated since not the full 32 bits of data would be needed anyway.