cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MicroZed Chronicles: HLS Delays, Triggers and Pulses

Xilinx Employee
Xilinx Employee
1 3 1,055

Editor’s Note: This content is republished from the MicroZed Chronicles, with permission from the author and Hackster.io.

 

High Level Synthesis is great for implementing algorithms. However, there are times as we develop our HLS IP that we need to think about how it interfaces with the rest of the system beyond the AXI Interfaces which are our main interfaces.

This can be challenging in HLS as it often means we need to be able to wait on external signals, or to be able to wait for several clock cycles etc. implementing these can be challenging in HLS.

In this blog we are going to look at how we can implement structure in out HLS algorithms which

  • Wait for an input signal as a trigger
  • Wait for a defined number of clock cycles
  • Generate an output trigger signal

Let’s start with waiting for an input trigger from an external IP block, this could be a external frame sync in a image processing application.

The first thing we need to do is define an input using the arbitrary precision unsigned integer type, as we want a single bit, we can use

ap_unit<1> trig_in

We declare this in the parameter list for our HLS function, we can also then declare a HLS pragma which enables the input to be implemented as a ap_none.

#pragma HLS INTERFACE ap_none port=trig_in

This now provides us a single bit input into our C function, the next thing we need to do is pause the HLS IP block until we see the trigger.

The simplest way to do this within Vivado HLS is to use a function defined with ap_utils.h that is the ap_wait_until(X) function. This will cause the HLS IP to pause until the variable is true, true in this case means any none zero value.

ap_wait_until(trig_in);

When we simulate this in our C simulation, we need to ensure the trigger variable is set to a non-zero value otherwise the simulation will pause.

To ensure the implementation of the ap_wait_until() function is correct within our HLS code we can look at the analysis view.

In the analysis view we should see an operation called _lnXX(wait), right clicking and selecting goto source should cross probe to the ap_wait_until() function call.

342_Fig1.png

Now we know how to wait for an external trigger in our HLS code, how can we implement a delay for a specific number of clock cycles.

Typically writing our own delay function will not be efficient or implement the delay as we intend. As such the best way to implement a several clock cycle delay is to use the ap_wait_n(X) function.

This function is also defined with the ap_utils.h library, this function will delay at least X number of clock cycles. However, resumption of processing might take a few more clock cycles depending upon the implementation.

The delay can be changed on the fly, and if desired can be controlled using a AXI Lite Interface for example

void test (int delay)

#pragma HLS INTERFACE s_axilite port=delay

ap_wait_n(delay); //delay for a number of clock cycles provided over AXI bus

One useful application of the ap_wait_n(X) function is to adjust the frame rate to the exact frame rate you desire if creating a custom test pattern generator for video applications. In C simulation this delay will be ignored, however you will notice it in Co-Simulation when inspecting the waveform.

Similar to as we did with the ap_wait_until() we are able to observe the delay in the analysis view, in this case we will see a new loop which implements the counter to check for the correct delay. 

342_Fig2.png

The final aspect I want to examine is the creation of output signal, which changes state as the HLS IP core runs. This is important as the Vivado HLS compiler like many C compilers assumes the function will be single threaded. This means much like in a VHDL process only the final value of the variable is returned, to be able to generate intermediate outputs we need a little thought.

The first thing we need to do as for the trigger in is to create a single bit variable using the arbitrary precision types.

ap_uint<1> *trig_out

We declare this in our function parameter list however, as we want the signal to be an output and it is a scalar output, we must declare it is a pointer in accordance with figure 41 in user guide 902. 

342_Fig3.png

To ensure the intermediate values are output from the HLS IP function if we define the signal as being volatile. When the HLS compiler runs the intermediate operations will be performed and not optimized out. 

342_Fig4.png

Hopefully now you understand a little more about some of the more specialist features and functions that you deploy in your HLS solutions to make it easier to integrate into your overall solution.

 

See My FPGA / SoC Projects: Adam Taylor on Hackster.io

Get the Code: ATaylorCEngFIET (Adam Taylor)

Access the MicroZed Chronicles Archives with over 300 articles on the FPGA / Zynq / Zynq MpSoC updated weekly at MicroZed Chronicles.

 

3 Comments
Explorer
Explorer

Hello @xtech-blogs ,

we are experimenting with Vitis HLS 2020.1.1 in Vivado flow mode and we have some issues with the following function:

void foo(volatile ap_uint<32> *reg, volatile ap_uint<1> *raw_line)
{
#pragma HLS interface ap_none port=raw_line
#pragma HLS interface s_axilite port=reg bundle=ctrl
#pragma HLS interface s_axilite port=return bundle=ctrl

        ap_uint<32> local_reg = *reg;

        if (local_reg.test(0)) {
                *raw_line = 1;
                ap_wait_n(50);
                local_reg.clear(0);
        }

        *reg = local_reg;
        *raw_line = 0;
}

In Vitis HLS 2020.1.1 the generated HDL code keeps raw_line to 0 independently from the value of reg bit 0.

In Vivado HLS 2020.1.1 the generated HDL code correctly pilots raw_line to 1 when the bit 0 of reg is 1 but then it keeps raw_line to 1.

What should be the correct way to code this use case? What are we doing wrong?

Thank you, best regards.

Xilinx Employee
Xilinx Employee

Hi @dsakjl,

Thank you for reading the blog. The author of this blog is happy to talk you through this offline. Please send an email to him (adam@Adiuvoengineering.com).

The following technical support options are also available to Xilinx customers:

  • Technical information is available online 24 hours a day from the Support website
  • Technical Support staff are available to respond to your questions in the Community Forums

 

Explorer
Explorer

Hi @xtech-blogs ,

I already posted a question on Community Forums without success.

https://forums.xilinx.com/t5/High-Level-Synthesis-HLS/Vitis-Vivado-HLS-OUTPUT-PULSE-WITH-AP-NONE/td-p/1171461

Thank you, best regards.