Specifying Arrays as PIPOs or FIFOs - 2023.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
Release Date
2023.2 English

All arrays are implemented by default as ping-pong to enable random access. These buffers can also be re-sized if needed. For example, in some circumstances, such as when a task is being bypassed, performance degradation is possible. To mitigate this effect on performance, you can give more slack to the producer and consumer by increasing the size of these buffers by using the STREAM pragma or directive as shown below.

void top ( ... ) {
#pragma HLS dataflow
  int A[1024];
#pragma HLS stream type=pipo variable=A depth=3
  producer(A, B, …);  // producer writes A and B
  middle(B, C, ...);  // middle reads B and writes C
  consumer(A, C, …);  // consumer reads A and C

Arrays on the interface are defined as m_axi or ap_memory by default. However, arrays can be specified as streaming if the INTERFACE pragma or directive defines the array as ap_fifo or axis.

Inside the design, an array must be specified as streaming using the STREAM pragma or directive if a FIFO is desired for the implementation.

Tip: When the STREAM directive is applied to an array, the resulting FIFO implemented in the hardware contains as many elements as the array. However, the depth option can be used to specify the size of the FIFO as described in syn.directive.stream.

The STREAM pragma or directive can also be used to override the default implementation specified by the syn.dataflow.fifo_depth configuration command for any arrays in a DATAFLOW region, as described in Dataflow Configuration. In general, the use of the STREAM pragma or directive for a given array is preferable to the global option.

  • If the syn.dataflow.default_channel is set as pingpong, any array can still be implemented as a FIFO by applying the STREAM directive to the array.

    Tip: To use a FIFO implementation, the array must be accessed in sequential order (and not in random access order).
  • If the syn.dataflow.default_channel is set to FIFO, any array can still be implemented as a ping-pong implementation by applying the type=pipo to the STREAM pragma or directive for the array.
Important: To preserve sequential accesses, and thus the correctness of streaming, it might be necessary to prevent compiler optimizations (dead code elimination particularly) by using the volatile qualifier.

When an array in a DATAFLOW region is specified as streaming and implemented as a FIFO, the FIFO is typically not required to hold the same number of elements as the original array. The tasks in a DATAFLOW region consume each data sample as soon as it becomes available. The depth of the FIFO can be specified using the syn.dataflow.fifo_depth option or the STREAM pragma or directive with the depth option. This can be used to set the size of the FIFO to ensure the flow of data never stalls.

If the type=pipo option is selected, the depth option sets the depth (number of blocks) of the PIPO.