static
qualifier. This not only
ensures that Vitis HLS
implements the array with a memory in the RTL; it also allows
the default initialization behavior of the static types to be
used. In the following code, an array is initialized with a set of values. Each time the
function is executed, array coeff
is assigned
these values. After synthesis, each time the design executes the
RAM that implements coeff
is loaded with these
values. For a single-port RAM this would take eight clock
cycles. For an array of 1024, it would of course take 1024 clock
cycles, during which time no operations depending on
coeff
could occur.
int coeff[8] = {-2, 8, -4, 10, 14, 10, -4, 8, -2};
The following code uses the static
qualifier to
define array coeff
. The array
is initialized with the specified values at start of execution.
Each time the function is executed, array coeff
remembers its values
from the previous execution. A static array behaves in C/C++
code as a memory does in RTL.
static int coeff[8] = {-2, 8, -4, 10, 14, 10, -4, 8, -2};
In addition, if the variable has the static
qualifier, Vitis HLS
initializes the variable in the RTL design and in the FPGA
bitstream. This removes the need for multiple clock cycles to
initialize the memory and ensures that initializing large
memories is not an operational overhead. Refer to the initialization_and_reset example available
on GitHub for examples.
The RTL configuration command config_rtl -reset
can
specify if static variables return to their initial state after
a reset is applied. This is not the default. When reset
state
or all
are used, it
forces all arrays implemented as block RAM to be returned to
their initialized state after reset. This can result in two very
undesirable conditions in the RTL design:
- Unlike a power-up initialization (or power-on reset), an explicit reset requires the RTL design to iterate through each address in the block RAM to set the value: this can take many clock cycles if N is large, and requires more area resources to implement the reset.
- A reset is added to every array in the design.
To prevent adding reset logic onto every such block RAM, and incurring
the cycle overhead to reset all elements in the RAM, specify the
default control
reset mode and use the RESET
pragma or directive to identify individual static or global
variables to be reset.
Alternatively, you can use the state
reset mode, and use
the RESET directive off
option to select which
individual static or global variables to not reset.
Finally, depending on the hardware device or platform of your choice (UltraScale+ or Versal, etc), there can be differences in how BRAMs and URAMs are initialized and/or reset. In general, Vitis HLS supports two types of reset: one is when the device is powered on (and also termed as power-up initialization or power-on reset), and the second is when a hardware RESET signal is asserted during device execution. The following shows the differences in behavior for the different memory resources:
- Initialization Behavior: Applies to all BRAMs on all platforms and only to Versal URAMs. This is the behavior during power-on initialization (or power-on reset).
- Maintaining an “initial value array” and “run time array” if the array is read/written. This applies to both BRAMs and URAMs and this corresponds to the hardware “RESET” signal during device execution.