I am trying run zynq book tutorials lab 4 and c part in vivado hls (hls included vitis in new version) but when I right click in the step of adding directive as described in the book, the add directive window does not open. I tried this separately in 2015.1, 2018.3 and 2021.2 versions of vivado, the result is the same in all of them.The step I'm having trouble with is as follows.Tutorial Book Link is here. Although I researched the problem a lot on the internet, there was not much result, but someone who encountered this problem in xilinx's forum explained in this link He mentioned that this is a bug and that the same operation can be added to the c file with the #pragma command line.Since I am new to these issues, I would appreciate if you could help me how to add the directive by using the #pragma command mentioned in the step (m) in the tutorial.
The c code mentioned is as follows.
void nco (ap_fixed<16,2> *sine_sample, ap_ufixed<16,12> step_size){
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
}
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:
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:
page 102 to 107 of Vivado HLS Optimization Methodology Guide for your better understanding.
From page 438 on wards of Vivado Design Suite User Guide High-Level Synthesis about set_directive_interface for your better understanding.
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:
page 120 to 121 of Vivado HLS Optimization Methodology Guide for your better understanding about pragma HLS resource.
On page 452 and page 453 of Vivado Design Suite User Guide High-Level Synthesis about set_directive_interface for your better understanding.
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
}