EmbDev.net

Forum: FPGA, VHDL & Verilog IIR FILTER PROBLEM


Author: Chris Cutilb (programmer001)
Posted on:

Rate this post
0 useful
not useful
Hi!
I have a problem with IIR filter. On the output I have a input sin 
signal but the filter doesn't suppress the signal. It behaviour is that 
as rewrite
input signal to output. I think that the problem is in the subtraction 
operation or types. Fcut=2MHz. Code below:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
use IEEE.NUMERIC_STD.ALL;

entity dsp is
    Port ( clk : in  STD_LOGIC := '0';
           clk_adc : out  STD_LOGIC := '0';
     clk_dac : out  STD_LOGIC := '0';
           adc_data : in  STD_LOGIC_VECTOR(9 downto 0) := (others => 
'0');
           dac_data : out  STD_LOGIC_VECTOR(9 downto 0) := (others => 
'0')
       );
end dsp;

architecture Behavioral of dsp is


constant coeff_a0: integer := 128; --coefficients
constant coeff_a1: integer := 256;
constant coeff_a2: integer := 128;

constant coeff_b0: integer := -293;
constant coeff_b1: integer := 106;


constant offset: STD_LOGIC_VECTOR(9 downto 0) := "1000000000";

signal adc_buffer: signed(9 downto 0) := (others => '0');
signal dac_buffer: STD_LOGIC_VECTOR(9 downto 0) := (others => '0');

signal mult_a0: signed(19 downto 0):= (others => '0'); --mult registers
signal mult_a1: signed(19 downto 0):= (others => '0');
signal mult_a2: signed(19 downto 0):= (others => '0');


signal mult_b0: signed(19 downto 0):= (others => '0');
signal mult_b1: signed(19 downto 0):= (others => '0');

signal tmult_a0: signed(9 downto 0):= (others => '0'); --truncate 
registers
signal tmult_a1: signed(9 downto 0):= (others => '0');
signal tmult_a2: signed(9 downto 0):= (others => '0');


signal tmult_b0: signed(9 downto 0):= (others => '0');
signal tmult_b1: signed(9 downto 0):= (others => '0');

signal add_all: signed(9 downto 0):= (others => '0');

signal pipe_a0: signed(9 downto 0) := (others => '0'); --delay registers
signal pipe_a1: signed(9 downto 0) := (others => '0');
signal pipe_a2: signed(9 downto 0) := (others => '0');


signal pipe_b0: signed(9 downto 0) := (others => '0');
signal pipe_b1: signed(9 downto 0) := (others => '0');


begin

P0: process(clk)
begin

  if falling_edge(clk) then

  adc_buffer <= signed(adc_data); -- adc give data in U2 code

  pipe_a0 <= adc_buffer;
  pipe_a1 <= pipe_a0;
  pipe_a2 <= pipe_a1;

  pipe_b0 <= signed(add_all);
  pipe_b1 <= pipe_b0;

  dac_data <= dac_buffer(9 downto 0); -- write to dac

  end if;

end process;

  mult_a0 <= pipe_a0*to_signed(coeff_a0,10); -- multiplication
  mult_a1 <= pipe_a1*to_signed(coeff_a1,10);
  mult_a2 <= pipe_a2*to_signed(coeff_a2,10);

  mult_b0 <= pipe_b0*to_signed(coeff_b0,10);
  mult_b1 <= pipe_b1*to_signed(coeff_b1,10);

  tmult_a0 <= mult_a0(19 downto 10); -- truncate to 10 bits
  tmult_a1 <= mult_a1(19 downto 10);
  tmult_a2 <= mult_a2(19 downto 10);

  tmult_b0 <= mult_b0(19 downto 10);
  tmult_b1 <= mult_b1(19 downto 10);

  --sum (add and substract)
  add_all <= tmult_a0 + tmult_a1 + tmult_a2 - tmult_b0 - tmult_b1;


  dac_buffer <= STD_LOGIC_VECTOR(add_all) + offset; -- to offset binary 
convertion

  clk_adc <= clk;
  clk_dac <= clk;


end Behavioral;

Author: Pongo (Guest)
Posted on:

Rate this post
0 useful
not useful
Chris C. wrote:
> if falling_edge(clk) then
THIS IS NONSENSE. THERE IS NO FALLING CLOCK SENSITIVE FF IN AN FPGA.

> clk_adc <= clk;
> clk_dac <= clk;

THIS IS BAD! CLOCKS CANNOT BE ROUTET OUT.

also TRUNCATION IS TO EARLY.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Chris C. wrote:
> use IEEE.STD_LOGIC_unsigned.ALL;
> use IEEE.NUMERIC_STD.ALL;
Use the first one or use the second one. But never ever use both of them 
together.
Best is to use the numeric_std and its conversions and casts.
See how simple that is:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std
Try Google translator, it's German...

Author: Duke Scarring (Guest)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Beside all the other mentioned problems:
What is your main clock frequency?

I've added a testbench to the see the filter effect.
For me it looks like your cutoff frequency is to high.

Duke

Author: Chris Cutilb (programmer001)
Posted on:

Rate this post
0 useful
not useful
My clock frequency -> 100MHz

In code below coefficient are for 4MHz cut-off frequency but I dont know 
if they are correct. In new code is is easy to change coefficients.
I need coefficients only to test my filter. I would be gratefull if 
somebody generate coefficient (10 bit) to low-pass with cut-off beetwenn 
1-10MHz.
I dont know what to do with overflow bits. If I have 23-bit ad_all 
signal the output amplitude is 4 times lower than when I have 19-bit 
ad_all signal.
It probably means that the overflow bits doesn't occur. In my opinion 
the sum of 5 signed 19-bit signals should be stored in 23-bit signal.
Secondly is that if I operate on signed values I should be carefull with 
math operations signs (+/-). If I add negative values as a constant 
signed, in operation of sum of the signals I must use only "+" sign.
I ignored all overflow bits.
It is possible that I have only wrong coefficient. On hardware filter 
works but not correct.

My new, some improved code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity dsp is
    Port ( clk : in  STD_LOGIC := '0';
     clk_adc : out  STD_LOGIC := '0';
     clk_dac : out  STD_LOGIC := '0';
           adc_data : in  STD_LOGIC_VECTOR(9 downto 0) := (others => 
'0');
           dac_data : out  STD_LOGIC_VECTOR(9 downto 0) := (others => 
'0')
       );
end dsp;

architecture Behavioral of dsp is

constant coeff_a0: integer := 133; --coefficients
constant coeff_a1: integer := 262;
constant coeff_a2: integer := 133;

constant coeff_b0: integer := -164;
constant coeff_b1: integer := 70;

constant offset: signed(9 downto 0) :=  "0111111111"; -- +511 in U2

signal adc_buffer: signed(9 downto 0) := (others => '0');
signal dac_buffer: signed(9 downto 0) := (others => '0');

signal mult_a0: signed(19 downto 0):= (others => '0'); --mult registers
signal mult_a1: signed(19 downto 0):= (others => '0');
signal mult_a2: signed(19 downto 0):= (others => '0');


signal mult_b0: signed(19 downto 0):= (others => '0');
signal mult_b1: signed(19 downto 0):= (others => '0');

signal add_all: signed(19 downto 0):= (others => '0');

signal pipe_a0: signed(9 downto 0) := (others => '0'); --delay registers
signal pipe_a1: signed(9 downto 0) := (others => '0');
signal pipe_a2: signed(9 downto 0) := (others => '0');


signal pipe_b0: signed(9 downto 0) := (others => '0');
signal pipe_b1: signed(9 downto 0) := (others => '0');

begin

P0: process(clk)
begin

  if falling_edge(clk) then

  adc_buffer <= signed(adc_data); -- adc give data in U2 code

  pipe_a0 <= adc_buffer;
  pipe_a1 <= pipe_a0;
  pipe_a2 <= pipe_a1;

  pipe_b0 <= add_all(19 downto 10); --truncated sum
  pipe_b1 <= pipe_b0;

  dac_data <= STD_LOGIC_VECTOR(dac_buffer(9 downto 0)); -- write to dac 
(ignore MSB - offset bin conversion)



  mult_a0 <= pipe_a0*to_signed(coeff_a0,10);  -- signed * signed return 
20 bit signed
  mult_a1 <= pipe_a1*to_signed(coeff_a1,10);
  mult_a2 <= pipe_a2*to_signed(coeff_a2,10);

  mult_b0 <= pipe_b0*to_signed(coeff_b0,10);
  mult_b1 <= pipe_b1*to_signed(coeff_b1,10);

  --sum of signed results
  add_all <= mult_a0 + mult_a1 + mult_a2 + mult_b0 + mult_b1; --signed + 
signed + ...

  dac_buffer <= add_all(19 downto 10) + offset; -- to offset binary 
convertion (add 511) signed + signed
    end if;

end process;                               -- dac buffer is 11 bit long

  clk_adc <= clk;
  clk_dac <= clk;


end Behavioral;

: Edited by User
Author: Andreas (Guest)
Posted on:

Rate this post
0 useful
not useful
Chris C. wrote:
> In code below coefficient are for 4MHz cut-off frequency but I dont know
> if they are correct.

Did you have a matlab? There is a toolbox available for calculating 
filter coeffiecients in fixed data formats. Also do this toolbox a 
stability analyis of your IIR filter.

Best Regards,

Author: Duke Scarring (Guest)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Chris C. wrote:
> It is possible that I have only wrong coefficient. On hardware filter
> works but not correct.
Your coefficents are correct but your code doesn't work.

If I use your coefficients with the implementation biquad, form 1 as 
described on this website [1], I got the expected results.

Can you describe graphically the structure of your IIR filter?

Duke

[1] http://www.iowahills.com/4IIRFilterPage.html

Author: Chris Cutilb (programmer001)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Duke,
I would implement the same IIR structure as in picture.

Author: Duke Scarring (Guest)
Posted on:
Attached files:

Rate this post
0 useful
not useful
The names in code doesn't match with the schematic, but anyway:

1.  move the multiplications out of your register stage (if *_edge ... 
end if)
2.  mind the polarity signs on the big 'adder'
3.  don't move the adder out of the register stage

Another hint (again): Use falling_edge only if you have a good reason.

Duke

Author: Thomas Reinemann (Company: abaxor engineering) (abaxor)
Posted on:

Rate this post
0 useful
not useful
Duke Scarring wrote:
> 1.  move the multiplications out of your register stage (if *_edge ...
> end if)
> 2.  .... the big 'adder'

This will led to a lot of logic levels in this case
- 4 adders
- plus 1 multiplier

I would expect timing problems with the code posted by Chris.

Generally it is difficult to run an IIR-Filter with sampling frequency = 
clock frequency. Since the feed back loop has only one clock budget but 
you need at least two operations, add and multiply. Within a second 
order stage (as shown in the iir.jpg picture) there has to be performed 
three sequential operations, 2 additions and 1 multiplication. Either 
you get many logic levels (in terms of DSP blocks) or to many pipeline 
stages.

What is the reason for your IIR-Filter?

Tom

Author: Chris Cutilb (programmer001)
Posted on:

Rate this post
0 useful
not useful
Tom,
I make this filter as a project on high school.
It is very possible that you're right. I spend many hours with trying to 
resolve problem with this filter. I obtain results which magnitude 
characteristic was above 10dB upper than expected which I compue in FDA 
Tool in MATLAB. Interestng is that I implemented FIR filter with the 
same way and it works very good. I saw the VHDL code where IIR filter 
was divided to machine state (as you described the number of operations 
in one clock cycle). Maybe it is a solution of my problem but I need 
100MSPS. I think that the problem is in the second part of my filter, it 
works but 10dB above.

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig