Some thoughts on AXI pipe handshake protocol and timing closure - Page 1
Forum section: electronics / general

author: OwO
author_rank: Super Contributor
timestamp: July 06, 2019, 09:59:16 am
content: If you have ever worked with AXI interfaces you will know that the basic building block in an AXI Interface is the pipe, which consists of 3 signalsdata,ready, andvalid. An AXI streaming interface is usually simply a single pipe, and an AXI memory mapped interface combines several address and data pipes to transfer read/write commands and responses.The basic protocol of an AXI pipe is simple. When the source has data to send, it assertsvalidand setsdata. A transfer occurs when the sink also assertsready. The protocol advancement condition is thus (readyandvalid).I have been implementing AXI based peripherals and stream processors for some time now and have the following observation. In a larger design where a pipe passes through many modules or stream processors, it is usually desirable to register thereadysignal at many points along the stream in order to meet timing. Each stream processor may have their own logic to decide when to accept data, but it must always pause data flow if the downstreamreadysignal is 0, which naturally means thereadysignal can't be delayed. If thereadysignal is delayed, the stream processor will continue on for one more cycle after the sink de-assertsready, which means data will be lost.The way around this is a shallow FIFO, also called a "register slice" or "skid buffer". The FIFO is often 2 or 4 entries deep and allows buffering of incoming data when downstream is stalled but we are already committed to receiving data from upstream (because we still have ourreadysignal asserted.)The end result is every time you want to register a ready signal, you must have a skid buffer. This means in a larger pipeline you will have many skid buffers spread throughout the design. Each skid buffer also introduces extra cycles of data delay because the way the FIFO is implemented is usually with registers and a MUX, and another register is desirable after the MUX to improve timing.That's when I realized that a pattern often emerges when I'm e.g. implementing my own skid buffer or AXI stream arbiter. Often what I end up doing is converting an AXI pipe into a different kind of pipe, with signalsdata,strobe, andready, withstrobeserving a similar function asvalid. This interface I will call OXI from now on, and has the following properties:The bus advancement condition is no longerreadyandvalid, but simplystrobe. In other words wheneverstrobeis asserted the sink must accept a word of data and isn't allowed to reject it by de-assertingready.readycontrols data flow in the future. Assertingreadyfor one cycle will allow one word through some point in the future.readymust be asserted by a sink without waiting forstrobe, unlike in AXI which is the other way around.An OXI source has an attribute "overdelivery", which is the maximum flow control delay (fromreadytodata/strobe).An OXI sink has an attribute "overacceptance", which is the maximum number of words it can continue to accept after it deassertsready.A source can be connected to a sink only if the sink's "overacceptance" is >= the source's "overdelivery".Registers can be inserted in thereadyordata/strobepath at will without requiring any skid buffer. However each register you insert will increase the "overdelivery" of the source by 1.The end result is you can get away with one bigger FIFO/skid buffer at the very end of the pipeline (the ultimate sink) rather than many small FIFOs scattered throughout. The FIFO deasserts itsreadysignal when it is M words short of full, hence it has "overacceptance" of M. It then becomes possible to add pipeline registers to both thedata/strobeandreadypath at any point of the pipeline as needed.The advantages of this protocol are less resource usage (especially in FPGAs where ram is more area efficient than many small FIFOs implemented with registers and MUXs), and less total latency (because every skid buffer needs some extra pipeline registers). It isn't meant to replace AXI but rather supplement it. It's very trivial to convert an AXI source to an OXI source (one AND gate and optional registering), and easy to adapt an OXI source to an AXI sink (a FIFO is one way). I might, for example, convert an AXI stream to OXI, put it through a long pipeline, and convert to AXI again by adding the FIFO required for overacceptance.Has a protocol like this been devised before and is there a good argument for immediate-handshake protocols like the way it is done in AXI? It seems to me that it's far easier to get timing closure with a "delay acceptable" protocol like what I just described while introducing minimal latency, so what is the reason the industry has gone with an immediate handshake approach?

author: OwO
author_rank: Super Contributor
timestamp: July 06, 2019, 01:19:19 pm
content: Here is an overview diagram of my AXI skid buffer implementation that shows the implicit conversion to an OXI-like protocol internally before the FIFO.

author: rstofer
author_rank: Super Contributor
timestamp: July 06, 2019, 03:08:21 pm
content: I really like that 1 element FIFO. Very clever!I don't use the AXI stuff simply because I am usually building my own cores but this scheme is worth remembering.

author: NorthGuy
author_rank: Super Contributor
timestamp: July 06, 2019, 10:33:19 pm
content: Why not to put the data you receive from AXI into a regular FIFO, and then draw them from the other end passing it to the other AXI as needed. This will make the two AXIs completely independent, you may even clock them with different clocks at different frequencies.7-series have shallow and wide IN_FIFO and OUT_FIFO which you can use for this purpose.