cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Participant
Participant
9,338 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
Highlighted
Explorer
Explorer
9,327 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
Highlighted
Participant
Participant
9,303 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
Highlighted
Participant
Participant
9,296 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
Highlighted
Xilinx Employee
Xilinx Employee
9,286 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
Highlighted
Participant
Participant
9,270 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
Highlighted
Xilinx Employee
Xilinx Employee
9,267 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