AXI timer capture mode

I am trying to develop a simple counter triggered by some events. The design is the following:

Where the custom IP timer_hls has the following code:


#include "ap_axi_sdata.h"
#include "hls_stream.h"
#include <ap_fixed.h>

typedef ap_fixed<32, 1> ap_fixed_input_type;
typedef ap_fixed<32, 1> ap_fixed_output_type;


typedef hls::axis<ap_fixed_input_type,0,0,0> pkt_t;

typedef hls::axis<ap_fixed_output_type,0,0,0> pkt_t_out;

void timer_hls(
		hls::stream< pkt_t > &din,
		hls::stream< pkt_t_out > &dout,
		ap_uint<1> & interrupt) {
	#pragma HLS INTERFACE ap_ctrl_none port=return
	#pragma HLS INTERFACE axis port=din
	#pragma HLS INTERFACE axis port=dout
	#pragma HLS INTERFACE ap_none register port=interrupt

	pkt_t pkt;
	pkt_t_out pkt_out;
	static int counter=0;



	ap_fixed_input_type input_ap_fixed = 0;
	ap_fixed_output_type output_ap_fixed = 0;



	din.read(pkt);
	input_ap_fixed = pkt.data;


	pkt_out.last = pkt.last;
	pkt_out.keep = pkt.keep;
	pkt_out.strb = pkt.strb;
	pkt_out.data = input_ap_fixed;

	dout.write(pkt_out);

	counter ++;

	if(counter>1024){
		counter = 0;
		interrupt = 1;
	}


}

These IP will count the input packets until a given number, then they generate an interrupt which is captured by the Vivado AXI timer IP. I will use these 2 IP + Vivado Timer to exactly measure the latency/computation time of another IP, which will be inserted between the two timer_hls IPs.

In my PYNQ code I set up everything and the design works fine: the input is correctly handled with a DMA, sent into the two timer_hls IPs and then saved back into memory.

However the Vivado Timer IP never gets interrupted via capture pins and I am not able to save the clock counter.

The Vivado AXI timer IP seems to work fine, if I write:

timer = overlay.axi_timer_0

time_0 = timer.read(0x08)
time_0

time_1 = timer.read(0x18)
time_1

I can see that it is counting correctly. However if i write:

timer.write(0x00, 1097) #setting the registers of AXI timer

And I read back:

print(timer.read(0x00))

I get 0b10011001001 → the interrupt of the counter (bit number 8) is always zero, this means that my capture pin never captures anything.

What am I missing?

2 Likes

Hi @mattiasu96,

From your description it seems that everything is setup properly.
Have you verified that the interrupt pin is asserted?

Mario

In the end it was a problem with the “format” of my interrupt pin, it was interpreted as an ap_fixed and not as an interrupt

Hi all,

I am intrigued by this design as I am looking to do something very similar, using 2 custom HLS IP to essentially read two points of a stopwatch to time processes taking place between them.

However, I intend on creating a fully PL based timer, where my custom HLS block at position a will sent an interrupt to captureTrig0 and read the resulting value in the load register upon TUSER=1 (sof in AXI Stream). It will add this value to a metadata line of a video frame. Then the other custom HLS block at position B will do the same sending an interrupt to captureTrig1 and storing this clock value from AXI-timer.

My custom block at position B (end of pipeline) will then send to the PS via axi-lite the start time and stop time so I can calculate the time elapsed with lowest latency.

I do this because I fear that by using the AXI-Timer API - sending commands from PS to read the Load register twice, will add time to the timer which doesn’t represent what I am really trying to time - the actual time taken by data to move from A to B?

Also, how easy is it to read the load register of the Axi Timer and store this as a variable in a custom HLS block without communication from the PS?

Any help is appreciated as I cannot see any examples of fully PS based timers online yet.

Cheers,
Cameron