Basic Concepts and Code Examples
XAPP1209 (v1.0.1) August 8, 2014 www.xilinx.com 5
• Because it is a template class, the width of this array must also be specified. In this
case, 64 bits are used, matching the width of the data members of the input and
output interfaces of the top module.
• Are declared as static variables. A static variable maintains its value over multiple function
calls. The top-level module (and thus all its submodules) is called once in every clock cycle
when executed as a sequential C/C++ program, so any variables that must maintain their
values from the one cycle to the next intact, must be declared as static.
As mentioned, a stream interface can be implemented as a FIFO queue or as a memory, which
means that it can also have a specific depth to act as a buffer for data traffic. The depth of the
FIFO queue can be set for each stream using the stream pragma, as shown in lines 10 and 11
of Code Example 1 - Creating a Simple System in Vivado HLS. For typical feed-forward
designs, buffering might not be required. Omitting the pragma causes Vivado HLS to
automatically use a FIFO with a depth of one, which allows Vivado HLS to efficiently implement
small FIFOs using flip-flops, and thus save block RAMs and LUTs.
Creating Pipelined Designs
The last pragma to discuss is perhaps the most important one. The dataflow pragma in line
2 of Code Example 1 - Creating a Simple System in Vivado HLS instructs Vivado HLS to
attempt to schedule the execution of all the sub-functions in this function in parallel. It is
important to note that the effect of the dataflow pragma does not propagate down the
hierarchy of the design. Thus, if a lower level function contains sub-functions whose execution
has to be scheduled in parallel, then the dataflow pragma must be specified in that function
separately. The parameter interval defines the Initiation Interval (II) for this module. II
defines the throughput of the design by telling Vivado HLS how often this module has to be able
to process a new input data word. This does not preclude the module being internally pipelined
and having a latency greater than 1. An II=2 means that the module has 2 cycles to
complete the processing of a data word before having to read in a new one. This can allow
Vivado HLS to simplify the resulting RTL for a module. That being said, in a typical protocol
processing application the design has to be able to process one data word in each clock cycle,
thus from now on an II=1 is used.
Note:
The parameter interval is a deprecated feature and is subject to change.
Finally, you call the functions themselves. In Vivado HLS this also corresponds with the
instantiations of the modules. The parameters that are passed to each module essentially
define the module communication port. In this case, you create a chain of the three modules by
connecting the input to the first module, then the first module to the second over stream
modOne2modTwo, and so on.
Implementing a State Machine with Vivado HLS
Protocol processing is inherently stateful. You are required to read in successive packet words
arriving onto a bus over many clock cycles and decide on further operations according to some
field of the packet. The common way to handle this type of processing is by using a state
machine, which iterates over the packet and performs the necessary processing. Code
Example 3 - Finite State Machine using Vivado HLS shows a simple state machine, which
either drops or forwards a packet, depending on an input from a previous stage.
The function receives three arguments: the input packet data over the inData stream, a
one-bit flag that shows if a packet is valid or not over the validBuffer stream, and the output
packet data stream, called outData.
Note:
Parameters in the Vivado HLS functions are passed by reference. This is necessary when using
Vivado HLS streams, which are complex classes. Simpler data types like the ap_uint can also be
passed by value.
The pipeline pragma in line 2 of Code Example 3 - Finite State Machine using Vivado HLS
instructs Vivado HLS to pipeline this function to achieve an initiation interval of 1 (II = 1),