vivadovivado-hls

How to create a trigger signal in vivado HLS


I want to add a binary trigger signal for measurements to my vivado HLS IP. The code looks as follows:

void subfunction1(const int a[10], const int b[10], int out[10]){
  for(int i=0;i<10;i++){
    out[i] = a[i] + b[i];
  }
}

void subfunction2(const int a[10], const int b[10], int out[10]){
  for(int i=0;i<10;i++){
    out[i] = a[i] + b[i];
  }
}


void function(const int a[10], const int b[10], int out[10], bool *trigger){
  subfunction1(a, b, out);
  *trigger = true;
  subfunction2(out, b, out);
  *trigger = false
}

uint8_t top_level_fun(const int a[10], const int b[10], int out[10], bool *trigger){
#pragma HLS INTERFACE ap_memory port = a
#pragma HLS INTERFACE ap_memory port = b
#pragma HLS INTERFACE ap_memory port = out
#pragma HLS INTERFACE ap_fifo register port = trigger

#pragma HLS RESOURCE variable=a     core=ROM_1P_BRAM
#pragma HLS RESOURCE variable=b     core=ROM_1P_BRAM
#pragma HLS RESOURCE variable=out   core=RAM_1P_BROM

  function(a,b,out,trigger);
  return 0x01; // success
}

I want the trigger variable to be 0 normally and 1 during the execution of subfunction2. When I compile/co-simulate the code and view the results in the full wave viewer I see that the value of trigger never changes. How can I control the value of trigger during the execution of my code so that I can see this on the top level of my IP.


Solution

  • You need to make your trigger variable volatile:

    void function([...], volatile bool *trigger)
    uint8_t top_level_fun([...], volatile bool *trigger)
    

    Otherwise the compiler will optimize away previous calls as it thinks they are unnecessary.

    Please note the section on multi-access pointers in UG902 / UG1399:

    Designs that use pointers in the argument list of the top-level function (on the interface) need special consideration when multiple accesses are performed using pointers. Multiple accesses occur when a pointer is read from or written to multiple times in the same function.

    Using pointers which are accessed multiple times can introduce unexpected behavior after synthesis. In the following "bad" example pointer d_i is read four times and pointer d_o is written to twice: the pointers perform multiple accesses.

    #include "pointer_stream_bad.h"
    
    void pointer_stream_bad ( dout_t *d_o,  din_t *d_i) {
     din_t acc = 0;
    
     acc += *d_i;
     acc += *d_i;
     *d_o = acc;
     acc += *d_i;
     acc += *d_i;
     *d_o = acc;
    }
    

    After synthesis this code will result in an RTL design which reads the input port once and writes to the output port once. As with any standard C/C++ compiler, Vitis HLS will optimize away the redundant pointer accesses.