Yes, it happens at times that Vivado (now Vitis) HLS GUI does not show the directive. However, it's a blessing in disguise since it compels you to manually add the pragmas in your code and as a result you may actually understand the pragmas and their effect on the generated RTL. From the example above it seems you will be using INTERFACE
and RESOURCE
pragmas.
As a HLS enthusiast, I would like to briefly start with the basic understanding and syntax of both pragmas and then you can check my solution to your question in the end.
pragma HLS interface :
The INTERFACE
pragma specifies how RTL ports are created from the function definition during interface synthesis .
The ports in the RTL implementation are derived from:
- Any function-level protocol that is specified.
- Function arguments.
- Global variables accessed by the top-level function and defined outside its scope.
Below is the syntax of the INTERFACE
pragma:
Syntax:
#pragma HLS interface <mode> port=<name> bundle=<string> \
register register_mode=<mode> depth=<int> offset=<string> \
clock=<string> name=<string> \
num_read_outstanding=<int> num_write_outstanding=<int> \
max_read_burst_length=<int> max_write_burst_length=<int>
In order to explicitly understand each parameter in the syntax please do read the details in following references:
pragma HLS resource:
Specify that a specific library resource (core) is used to implement a variable (array, arithmetic operation or function argument) in the RTL. If the RESOURCE
pragma is not specified, Vivado HLS determines the resource to use.
#pragma HLS resource variable=<variable> core=<core>\
latency=<int>
In order to explicitly understand each parameter in the syntax please do read the details in following references:
Your solution:
Updated: Now I again post this solution after running the code myself on my Vivado HLS and hence more clarification:
void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size) {
#pragma HLS RESOURCE variable=sine_sample core=AXI4LiteS
#pragma HLS RESOURCE variable=step_size core=AXI4LiteS
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS RESOURCE variable=return core=AXI4LiteS
// Define the pcore interface and group into AXI4 slave "slv0"
/* Value to hold the current address value of the sine LUT
* 12-bit unsigned fixed-point, all integer bits.
* Overflow is set to "wrap around" by default. */
ap_ufixed<12,12> address;
temp+=step_size; // Accumulator. Values will wrap around on overflow.
address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.
*sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current address
}
On some Vivado HLS versions the above solution may give warning like following:
WARNING: [HLS 200-41] Resource core 'AXI4LiteS' on port '&sine_sample' is deprecated. Please use the interface directive to specify the AXI interface.
Hence, we use INTERFACE
directive for all variables as following that will give no warnings:
void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size) {
#pragma HLS INTERFACE s_axilite port=sine_sample
#pragma HLS INTERFACE s_axilite port=step_size
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE ap_ctrl_none port=return
// Define the pcore interface and group into AXI4 slave "slv0"
/* Value to hold the current address value of the sine LUT
* 12-bit unsigned fixed-point, all integer bits.
* Overflow is set to "wrap around" by default. */
ap_ufixed<12,12> address;
temp+=step_size; // Accumulator. Values will wrap around on overflow.
address = ap_ufixed<12,12>(temp); // Cast address to a 12-bit integer value.
*sine_sample = sine_lut[(int)address]; // Assign sign sample from LUT based on current address
}