Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
9 years ago

digital filter

hello everybody.

i am beginning with vhdl an i try to implement a digita filter on cyclone 2

This is the code i havebut i d ont understand why it doesnt work

thk for help

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.numeric_std.all;

entity filter is

--generic ( FILTERLAENGE :natural:=6;

-- FILTERKOEFF :array (natural range 0 to FILTERLAENGE - 1) of signed( 7 downto 0) :=(-1,-1,-1,-1,-1,-1)

-- );

port (

clk : IN STD_LOGIC;

reset : IN STD_LOGIC;

filterGO : IN STD_LOGIC;

filterEingang : IN STD_LOGIC_VECTOR (15 downto 0);

filterAusgang : OUT STD_LOGIC_VECTOR (15 downto 0)

);

end;

architecture beh of filter is

constant FILTERLAENGE: natural := 6;

type t_memory is array (natural range 0 to FILTERLAENGE - 1) of signed(15 downto 0);

type t_Koeff is array (natural range 0 to FILTERLAENGE - 1) of signed( 7 downto 0);

constant FILTERKOEFF: t_Koeff := (to_signed(1, 8), to_signed(1, 8), to_signed(1, 8),

to_signed(1, 8), to_signed(1, 8), to_signed(1, 8));

signal Speicher: t_memory;

begin

process(clk, reset)

variable filterMult: signed(23 downto 0) := (others => '0');

variable filterSumme: signed(24 downto 0) := (others => '0');

begin

if (reset = '0') then

filterAusgang <= (others => '0');

Speicher <= (others => (others => '0'));

elsif (rising_edge(clk)) then

if (filterGO = '1') then

-- held samples from "filterEingang" stored in Speicher

for I in 0 to FILTERLAENGE - 2

loop

Speicher(I) <= Speicher(I + 1);

end loop;

Speicher(FILTERLAENGE - 1) <= signed(filterEingang);

-- filter operation y(n) = b0*x(n) + b1*x(n - 1) + ... + bn*x(0)

filterSumme := (others => '0');

for I in 0 to FILTERLAENGE - 1

loop

filterMult := FILTERKOEFF(I)*Speicher(FILTERLAENGE - (I + 1));

filterSumme:= filterSumme + resize(filterMult, 25);

end loop;

-- current filter result in "filterSumme" has 25 bits width

-- needed y(n) has to be a 16 bits data

filterAusgang <= std_logic_vector(resize(filterSumme, 16));

end if;

end if;

end process;

end beh;

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    you are using multiply accumulate architecture. that is ok but you need to:

    1) reset sum after adding full set of mult results

    2) do not advance input until such result is finished and sum reset
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thank very much for answering

    my englisch is not so good.

    please can u write the 2 lines forme?

    and whats about the coefficients

    when i calculate then for example with mathlab should i convert then in binäre or something else?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    thank very much for answering

    my englisch is not so good.

    please can u write the 2 lines forme?

    and whats about the coefficients

    when i calculate then for example with mathlab should i convert then in binäre or something else?

    --- Quote End ---

    I think it is easier for you to change architecture to parallel multiply/add and so you don't need to worry about the accumulator reset and can advance input steam steadily.

    You can use integer for coeffs and convert them to signed as you have done.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    my problem is when i calculate the coeff the are not interger

    this is one example of the coef

    [0.000280,

    0.003809,

    0.010263,

    0.013750,

    0.010263,

    0.003809,

    0.000280]
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    my problem is when i calculate the coeff the are not interger

    this is one example of the coef

    [0.000280,

    0.003809,

    0.010263,

    0.013750,

    0.010263,

    0.003809,

    0.000280]

    --- Quote End ---

    scale up enough for integer resolution e.g. round(0.00028*2^20) = 294

    Then at final sum discard (20 LSBs or so, not critical but affects gain)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    you can scale coeffs as required e.g.

    hs=round(127*h/max(h)) or

    hs=round(256*h/sum(h)) %this keeps unity gain if you discard 8 lsbs at final output