This document contains technical documentation for the
This module provides a First In First Out (FIFO) mechanism where the data is buffered in DDR memory via AXI. It provides a simple interface, like a traditional FIFO, but can have a much greater depth (i.e. hold more data) than a FIFO that is limited by on-chip Block RAM.
In FPGA design, a FIFO is a very common component that is used to implement data flow control. It achieves a situation where data can be written at a certain rate, or in a certain pattern, but read out independently at a completely different rate or pattern. On-chip FIFOs are often implemented using Block RAM (for a depth in the 1000’s) or LUTRAM (for a depth in the 10’s). If the data read and write patterns demand a greater data buffer than that, an off-chip DDR memory can be used to buffer data, utilizing an AXI FIFO module like this.
Below is a simple block diagram of the module.
Note that the
job_partitioner, which splits bursts into smaller chunks, is only needed if
Otherwise, no burst splitting is necessary, since the whole packet length can fit in one burst.
This module uses AXI read and write ports of the same width as the native data port.
The module can not sustain full throughput on the
input interface over time.
For each AXI burst there is a two clock cycle stall on the data flow.
This means that, if continuously fed with data, the data FIFO will build up, which will eventually cause
input_ready to be lowered.
With this in mind, the depth of the data FIFO must be chosen carefully.
It must be able to hold a packet of maximum length, but could also have spare space to handle a build up of data.
Spare space should be dimensioned based on the behavior of
input stream, so that back-to-back packets can be handled as necessary.
output side there is no limitation in throughput.
Handshake data interface
This module uses handshaking for data qualification on the
Using AXI4-Stream-like handshake interfaces (
valid to qualify data transactions)
is very common in FPGA designs.
It enables a backpressure situation where the slave, i.e. the receiver of data, can indicate when it
is ready to receive the data.
Below are some rules governing how these handshake signals interact. They are adapted from the AMBA 4 AXI4-Stream Protocol Specification, ARM IHI 0051A (ID030610).
A transactions occurs on the positive edge of the clock when both
validare high. The graph below shows some typical transactions.
readysignal may fall without a transaction having occurred:
validsignal may NOT fall without a transaction having occurred:
validis asserted, the associated data may NOT be changed unless a transaction has occurred.
This applies to any auxillary signals associated with the bus as well, e.g. a
Note also that this restriction on data not changing only applies when
validis asserted. When it is not, the data may be changed freely.
In order to avoid deadlock situations, the master may NOT wait for the slave to assert
valid. The slave however may wait for
This entity provides a FIFO structure where data is buffered in memory via AXI.
Set buffer addresses
See off_chip_ring_buffer_manager.vhd for information on how to correctly set the buffer base addresses.
In order to keep complexity and resource utilization down, it uses a simple AXI mechanism that implies a limitation:
buffer_start_address must be a multiple of
However, in order to achieve the best memory performance, it is beneficial if
buffer_start_address is multiple of
4096. This will minimize the rate of
This entity does not contain a data FIFO on the
It is up to the user what type of buffering they need (synchronous or asynchronous, on the
output side or on the
R side, …).
With that in mind, the
AR transactions that this entity performs are not necessarily well
behaved in an AXI sense:
It is possible that more
R transactions are queued up than what the
R slave can receive.
If this is the case, it would result in degradation of memory performance.
Given this risk, it is recommended to have an
R FIFO in conjunction with
axi_read_throttle instance in your AXI subsystem.
address_width = 28
data_width = 64
max_packet_length_bytes = 1526
axi_max_burst_length_beats = 256
read_job_fifo_depth = 8
write_data_fifo_depth = 1024
Package with utility functions used in the rest of the module.
This entity provides a simplified/specialized application for handling segments in a ring buffer,
These two must be handled by mechanisms outside of this entity.
It instantiates the general
ring_buffer_manager, but with a local handling of
As soon as
enable is asserted, this entity will start serving addresses on
request_segment interface. To avoid faulty operation, the user must make sure that:
The buffer addresses must be correctly set before starting any operation.
Once set, the buffer addresses must not be changed.
Also, there is no internal error checking for how many addresses are outstanding:
Do not use the
release interface to release more addresses than you have
address_width = 28
segment_length_bytes = 2048