UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Participant cogansco
Participant
9,191 Views
Registered: ‎07-28-2015

Problem with simple CIC filter in C / HLS

I'm just learning HLS, though I know C and VHDL for quite a while.  I'm trying to implement a simple boxcar average filter, essentially just running sum of the previous N points.   This involves keeping an accumulator (acc1) updated each clock cycle by adding the latest value and subtracting the value from N clocks previously.  The fifo1 stores the history of N din values.

 

I can't seem to get it working.  The clostest I've gotten so far is the code below, which always returns the input value + 1. (I added a +1 just to make sure the output wasn't exactly the same as the input).  In ISim simulation of the vhdl generated, I noticed that acc1 is always zero, which would explain why always dout = din + 1.

 

In C, by making the static assignment to acc1, it should initialize to zero ONLY on first run -- this should be translated into a power-up initialization.  But it appears to be reset to zero each time through the loop.  I also tried pulling acc1 out and making it a global variable.  In this case, I got the message:

 

[RTGEN-101] Register 'acc1' is power-on initialization.

 

That's great, but in simulation the result is same as before.  What am I doing wrong?

 

#include "ap_cint.h"

#define CIC1_LEN 13

// CIC Filter - Running boxcar average
void cic35x13x(int24 * din, int32 * dout)
{
#pragma HLS INTERFACE ap_fifo port=din
#pragma HLS INTERFACE ap_fifo port=dout

	static int32 fifo1[CIC1_LEN] = {0};
	static int32 acc1 = 0;
	int24 din_val;
	int i;

#pragma HLS PIPELINE II=1

		din_val = *(din);
		acc1 = acc1 + din_val - fifo1[0];
		for (i=0; i>CIC1_LEN-1; i++) {
			fifo1[i] = fifo1[i+1];
		}
		fifo1[CIC1_LEN-1] = din_val;

		// output the accumulator
		*(dout) = acc1+1;
}

By the way, here is my instantiation of the module in vhdl testbench:

  cic35x13x_inst: cic35x13x 
  PORT MAP(
    ap_clk      => clk,
    ap_rst      => reset,
    ap_start    => '1',
    ap_done     => open,
    ap_idle     => open,
    ap_ready    => open,
    din_dout    => dataIn,
    din_empty_n => '0',
    din_read    => open,
    dout_din    => dataOut,
    dout_full_n => '1',
    dout_write  => open
  );
Tags (4)
0 Kudos
6 Replies
Explorer
Explorer
9,180 Views
Registered: ‎07-13-2015

Re: Problem with simple CIC filter in C / HLS

I think you've got the sign in your loop backwards.

 

for (i=0; i>CIC1_LEN-1; i++) {

should be

for (i=0; i<CIC1_LEN-1; i++) {

Apart from that, the code looks okay to me.

0 Kudos
Participant cogansco
Participant
9,156 Views
Registered: ‎07-28-2015

Re: Problem with simple CIC filter in C / HLS

Thanks Evan, that was one problem.  I had reversed the order of the for loop at one point, but forgot to change the comparison back.  Also it turns out I have to send 1 to din_empty_n:

 din_empty_n => '1',

 

Now VHDL simulation works, but I don't believe the timing.

 

Modelsim shows no latency, which I doubt is possible to synthesize.  Can it really take 24-bit input, add to one 32-bit number and subtract a different 32-bit number in less than 1 clock cycle?  Oh yeah and a +1 at the end.  HLS synthesis says it can do these 3 additions in one clock of 9.99-2.50 ns.  Latency = 0 and Interval = 1.  See attached picture.

hls.png

 

There is no way this meets timing when doing real synthesis.  Very frustrating to have such a simple project not work for me.

 

 

0 Kudos
Participant cogansco
Participant
9,149 Views
Registered: ‎07-28-2015

Re: Problem with simple CIC filter in C / HLS

I'm getting closer .. this time I added an infinite loop within the function, and the pipeline directive applies to this instead.  Gives me slightly better results -- some of the signals are delayed now, but the dout is still happening immediately.  It is strange because in the C code, the last command in the loop is:

*(dout++) = acc1+1;

 

However, in simulation, you can clearly see acc1 has a few clocks delay from the input, but the dout is somehow a few clocks ahead of acc1.  Also, the signal name HLS created for dout was dout_din.  And din became din_dout.  How confusing is that?

hls2.png

 

 

Below is latest code:

 

#include "ap_cint.h"

#define CIC1_LEN 13

// CIC Filter - Running boxcar average
void cic35x13x(volatile int24 * din, volatile int32 * dout)
{
#pragma HLS INTERFACE ap_fifo port=din
#pragma HLS INTERFACE ap_fifo port=dout

	static int32 fifo1[CIC1_LEN] = {0};
	static int32 acc1 = 0;
	int24 din_val;
	int i;

#pragma HLS PIPELINE II=1
	while (1)
	{
		din_val = *(din++);
		acc1 = acc1 + din_val - fifo1[0];
		for (i=0; i<CIC1_LEN-1; i++) {
			fifo1[i] = fifo1[i+1];
		}
		fifo1[CIC1_LEN-1] = din_val;

		// output the accumulator
		*(dout++) = acc1+1;
	}
}
0 Kudos
Xilinx Employee
Xilinx Employee
9,139 Views
Registered: ‎08-17-2011

Re: Problem with simple CIC filter in C / HLS

hi @cogansco

 

first , check UG902 and also perform c simulation and cosimulation , that is the recommanded flow.

 

next a VHLS fifo interface as output, will connect to a FIFO IP that has those ports : DIN, FULL_N, WRITE and so those are the suffix used by VHLS. since you named your output port dout the the following names are generted : dout_DIN, dout_FULL_N, dout_WRITE ; similar story on the input side fifo interface that connects to a FIFO output with names DOUT, EMPTY_N READ

 

and yes, you can perfectly do combinatorial stuff using registered variables that are in a datapath pipeline. something like that :

wire tmp = new_data + accum_reg - old_data;

assign output_port = tmp + 1;

always @ clk accum_reg <= tmp

 

it looks that the timing in your waveform is wrong; the first data 20 is not captured by the design. it's happening before the din_read from the VHLS block - ie the IP didn't issue the read.

 that's why you have those conflicting questions;

i repeat my advice; do write a C TB , make it self checking and perform c sim then c/rtl cosim . dump the waveform and look at it..

 

i hope this helps.

- Hervé

SIGNATURE:
* New Dedicated Vivado HLS forums* http://forums.xilinx.com/t5/High-Level-Synthesis-HLS/bd-p/hls
* Readme/Guidance* http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

* Please mark the Answer as "Accept as solution" if information provided is helpful.
* Give Kudos to a post which you think is helpful and reply oriented.
0 Kudos
Participant cogansco
Participant
9,123 Views
Registered: ‎07-28-2015

Re: Problem with simple CIC filter in C / HLS

I sure wish I could do a simulation, but unfortunately "ap_cint.h" spits out an error, I cannot include this and simulate.  Which means I can't simulate any arbitrary precision C-code.  Unless you know a work around?

0 Kudos
Xilinx Employee
Xilinx Employee
9,120 Views
Registered: ‎08-17-2011

Re: Problem with simple CIC filter in C / HLS

ap_cint can't be used to run the debugger in c simulation - check UG902

you can use c++ class ap_(u)int<N> for the same ; also check UG902.

this means your design will be C++ not C but you can still write the same code; you just need to change the typedef for your data types.

- Hervé

SIGNATURE:
* New Dedicated Vivado HLS forums* http://forums.xilinx.com/t5/High-Level-Synthesis-HLS/bd-p/hls
* Readme/Guidance* http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

* Please mark the Answer as "Accept as solution" if information provided is helpful.
* Give Kudos to a post which you think is helpful and reply oriented.
0 Kudos