3.5.1.20.4 hls::FIFO Argument

SmartHLS provides a Streaming Library which includes a FIFO template class for inferring the AXI4-stream like, ready-valid-data (RVD) interface. When a hls::FIFO type argument is used by the top-level function, a corresponding RVD interface is always generated.

The RVD interface is useful to transfer data from an upstream producer to a downstream consumer. The upstream sends the data along with a valid signal to indicate the data validity, while the downstream controls a ready signal to indicate its readiness to consume the data. A data is only transferred when both valid and ready signals are high at a positive clock edge.

As shown in the above timing diagram, three sets of data are transferred at the second, fourth, and sixth positive clock edges. No data transfer occurs at the third positive clock edge because the upstream does not assert the valid signal. The data "D2" is also not transferred at the fifth positive clock edge because the downstream back-pressures the upstream by lowering the ready signal.

The hls::FIFO template class is declared as

template<class T, bool pack = false> class FIFO;

The template argument T defines the data type, which can be a scalar data type or a struct of multiple scalar types. The template argument pack defines whether the scalar elements inside the struct should be packed into a single data port. When pack is false, each scalar element has its own data port, and all scalar elements in the struct share the same pair of ready and valid ports. A hls::FIFO argument must be either write-only or read-only. The data and valid ports always have the same direction (output if write-only, input if read-only), while the ready port has the opposite direction. The following table shows the interface ports of the hls::FIFO argument depending on the template parameters.

Template ParameterPort Name
T is a scalar data type (pack is ignored)<ARG_NAME><ARG_NAME>_valid<ARG_NAME>_ready

T is a struct of scalars, e.g.,

struct MyAxiStream { ap_uint<32> data; ap_uint<8> keep; ap_uint<1> last; };

pack = false<ARG_NAME>_data<ARG_NAME>_keep<ARG_NAME>_last<ARG_NAME>_valid<ARG_NAME>_ready
pack = true<ARG_NAME> // 41-bit wide.<ARG_NAME>_valid<ARG_NAME>_ready

In the struct type example above, the ap_uint template class is from C++ Arbitrary Precision Data Types Library, which allows you to define custom bit-width integers.

If you are familiar with the AXI4-stream interface, you may already notice that the struct example (non-pack case) yields an AXI4-stream interface. Indeed, this is how to infer AXI4-stream interface using hls::FIFO library.