cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
mahkoe
Observer
Observer
844 Views
Registered: ‎02-08-2019

Free running counter in parallel with other logic

Jump to solution

In my design, I need to have a free-running counter which ticks every clock cycle. 

 

However, I also need to output this value via an AXI stream protocol every "once in a while". (To be more specific, my design receives commands over an input AXI stream, then depending on the command, will output the current count value on the output AXI stream).

 

I've looked at a few other posts on the forums, and the only solution I could find was to make sure my design has an II of 1. But even if I do that, the count value only increments between AXI Stream writes. Here is some simplified code that exhibits the problem:

#include <hls_stream.h>
#include <ap_int.h>

void tick(ap_uint<64>& count) {
#pragma HLS PIPELINE II=1
	count++;
}

void write_time(hls::stream<ap_uint<64> > &out, ap_uint<64> count) {
	out << count;
}

void ptp(
		hls::stream<ap_uint<64> > &in,
		hls::stream<ap_uint<64> > &out,
		int *mem
) {
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE axis register both port=out
#pragma HLS INTERFACE axis register both port=in

	static ap_uint<64> count;
	tick(count);
	write_time(out, count);
}

And here is a screenshot of the simulation:

hlscounter.png

 

 

0 Kudos
1 Solution

Accepted Solutions
u4223374
Advisor
Advisor
784 Views
Registered: ‎04-26-2015

This is a fine example of "not a job for HLS". HLS mimics the behaviour of a single-threaded C program. It will perform parallel processing for performance gains, but the behaviour it's aiming for is single-threaded. It follows directly that trying to implement a multi-threaded program is going to go poorly. It's never going to simulate accurately, and could well change behaviour in each new version of HLS.

 

I would suggest instead having an external timer (just a 64-bit counter), connected to a port on the HLS block that has been declared volatile. This tells HLS that it must perform every read/write as specified - no internal buffering is allowed. It'll still be impossible to simulate, but at least it should work consistently in hardware.

View solution in original post

4 Replies
nmoeller
Xilinx Employee
Xilinx Employee
825 Views
Registered: ‎09-05-2018

@mahkoe,

I think you need an if statement around the output. The code, the way it is written, is incrementing count and then writing it. The IP can't write out, so it doesn't do anything until it's allowed to write again. You want the code to increment count unconditionally, then output the value when you need it.

Nicholas Moellers

Xilinx Worldwide Technical Support
0 Kudos
mahkoe
Observer
Observer
816 Views
Registered: ‎02-08-2019

Hello,

I am not sure how this solves the problem. Even if I were to gate the outputting statement in an if block, I would still have a problem with the AXI write blocking.

0 Kudos
u4223374
Advisor
Advisor
785 Views
Registered: ‎04-26-2015

This is a fine example of "not a job for HLS". HLS mimics the behaviour of a single-threaded C program. It will perform parallel processing for performance gains, but the behaviour it's aiming for is single-threaded. It follows directly that trying to implement a multi-threaded program is going to go poorly. It's never going to simulate accurately, and could well change behaviour in each new version of HLS.

 

I would suggest instead having an external timer (just a 64-bit counter), connected to a port on the HLS block that has been declared volatile. This tells HLS that it must perform every read/write as specified - no internal buffering is allowed. It'll still be impossible to simulate, but at least it should work consistently in hardware.

View solution in original post

mahkoe
Observer
Observer
773 Views
Registered: ‎02-08-2019
In the end I did separate the counter (as though it were a separate "thread") into a different HLS core. This solved my problem, and it appear to be the "correct" way to do things.
0 Kudos