filterfilteringvhdldigital-filter

FSM model of FIR filter


I want to make a FSM model of FIR, for that I need to write FIR calculation code line in FSM implementation.

Here is the actual and correct code for FIR

entity fir_4tap is
  port(   Clk : in std_logic; --clock signal
          Clk_fast : in std_logic;
          --  Xin : in signed(7 downto 0); --input signal
          bit_in : in std_logic;
          bit_out : out std_logic;
          Yout : out signed(15 downto 0)  --filter output
  );
end fir_4tap;

architecture Behavioral of fir_4tap is
  signal add_out3 : signed(15 downto 0) := (others => '0');
  signal index : unsigned(2 downto 0) := (others =>'0');
  signal counter : unsigned(3 downto 0) := (others => '0');
  signal p : unsigned(1 downto 0) := (others => '0');
  signal k : unsigned(1 downto 0) := (others => '0');
  signal j : unsigned(1 downto 0) := (others => '0');
  type array_signed is array(8 downto 0) of signed(7 downto 0);
  signal z : array_signed := (others => "00000000");
  type array_signed1 is array(3 downto 0) of signed(7 downto 0);
  signal H : array_signed1 := (others => "00000000");
  signal Xin : array_signed1 := (others => "00000000");
begin
  z(0) <= to_signed(-3,8);
  z(1) <= to_signed(1,8); 
  z(2) <= to_signed(0,8);
  z(3) <= to_signed(-2,8);
  z(4) <= to_signed(-1,8); 
  z(5) <= to_signed(4,8); 
  z(6) <= to_signed(-5,8);
  z(7) <= to_signed(6,8); 
  z(8) <= to_signed(0,8);
  H(0) <= to_signed(-2,8);
  H(1) <= to_signed(-1,8);
  H(2) <= to_signed(3,8);
  H(3) <= to_signed(4,8);

  process (clk) 
  begin
    if (rising_edge(Clk)) then 
      index <= index +1;
      if (index = "111") then 
        Xin(to_integer(p)) <= z(to_integer(counter));                                              k <= p;
        p <= p + 1;
        ***-- This part of the code has problem, I want to write the line which is summing --up for add_out3 in a for loop.***
        add_out3 <= (others => '0');
        add_out3 <=  Xin(to_integer(k))*H(to_integer(j)) + Xin(to_integer(k-1))*H(to_integer(j+1)) + Xin(to_integer(k-2))*H(to_integer(j+2)) + Xin(to_integer(k-3))*H(to_integer(j+3));
        Yout <= add_out3;
      end if;
    end if;
  end process;
end Behavioral;

Now Below is the FSM implementation try by me but not getting the same out sample as input can somebody tell me what could be the problem in the code?

----------------FSM implementation of the FIR filter ----------------------

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


entity test is
port(   Clk : in std_logic; --clock signal
          Clk_fast : in std_logic;
          bit_in : in std_logic;
          bit_out : out std_logic;
        Yout : out signed(15 downto 0)  --filter output
        );


end test;

architecture Behavioral of test is
signal data_buffer : signed(7 downto 0) := (others => '0');
signal index : unsigned(2 downto 0) := (others =>'0');


signal counter : unsigned(3 downto 0) := (others => '0');

type array_signed is array(8 downto 0) of signed(7 downto 0);
signal z : array_signed := (others => "00000000");

type array_signed1 is array(3 downto 0) of signed(7 downto 0);
signal H : array_signed1 := (others => "00000000");

signal input : signed(7 downto 0) := (others => '0');

type MULT_TYPE is array(3 downto 0) of signed(15 downto 0);
signal MULT_array : MULT_TYPE := (others => "0000000000000000");

type ADD_TYPE is array(3 downto 0) of signed(15 downto 0);
signal ADD_array : ADD_TYPE := (others => "0000000000000000");

constant ZERO : signed(15 downto 0) := (others => '0');

type state_type is (s0,s1,s2,s3);  --type of state machine.
signal current_s : state_type := s0;  --current and next state declaration.
signal next_s : state_type := s0; 

signal reset : std_logic := '0';
signal go : std_logic := '0';
signal change_state : std_logic := '0' ;
signal counter_FSM_monitor : unsigned( 6 downto 0) := "0000000"; 

begin

z(0) <= to_signed(-3,8);
z(1) <= to_signed(1,8); 
z(2) <= to_signed(0,8);
z(3) <= to_signed(-2,8);
z(4) <= to_signed(-1,8); 
z(5) <= to_signed(4,8); 
z(6) <= to_signed(-5,8);
z(7) <= to_signed(6,8); 
z(8) <= to_signed(0,8);

H(0) <= to_signed(-2,8);
H(1) <= to_signed(-1,8);
H(2) <= to_signed(3,8);
H(3) <= to_signed(4,8);




process (Clk) is
begin
if falling_edge(Clk) then 

data_buffer(to_integer(index)) <= bit_in;
index <= index +1;
if (index = "111") then 
input <= z(to_integer(counter));

counter <= counter + 1;
if(counter = "1000") then 
counter <= "0000";
end if; 
end if;
end if;
end process;


process (clk_fast)
begin

if (falling_edge(clk_fast)) then

counter_FSM_monitor <= counter_FSM_monitor + 1;

if( to_integer(counter_FSM_monitor) = 76) then 
counter_FSM_monitor <= "0000000";
end if;

case change_state is 

when '1' => 
current_s <= next_s;   --state change.                 

when '0' => --current_s <= s0;                 
when others =>
end case;
end if;
end process;

Process(current_s,input)
begin 
if ( to_integer(counter_FSM_monitor) < 64 ) then 
-- waiting for the Input
elsif (to_integer(counter_FSM_monitor) >= 64 and to_integer(counter_FSM_monitor) < 76) then 


---------------------------------------------- FSM ----------------------------------------


case current_s is 

when s0 => 
mult_array(0) <= input*H(3);
ADD_array(0) <= ZERO + mult_array(0);
next_s <= s1;
change_state <= '1';

when s1 => 
mult_array(1) <= input*H(2);
ADD_array(1) <= mult_array(1) + ADD_array(0);
next_s <= s2;
change_state <= '1';

when s2 => 
mult_array(2) <= input*H(1);
ADD_array(2) <= mult_array(2) + ADD_array(1);
next_s <= s3;
change_state <= '1';

when s3 => 
mult_array(3) <= input*H(0);
ADD_array(3) <= mult_array(3) + ADD_array(2);
Yout <= ADD_array(3);
next_s <= s0;
change_state <= '1';

when others => 
next_s <= s0;-- never comes here
change_state <= '1';
end case;
---------------------------------------------- FSM ----------------------------------------
end if;
end process;
end Behavioral;

How ever I am not able to receive the same output which I received by the first code. FSM code gives the correct output for the first out but from the second out sample it gives wrong result.Can somebody tell me what I am doing wrong ?


Solution

  • This answer is for the initial version of the question but Now question has been changed. Made add_out3 a variable instead of a signal.

    for i in 0 to 3 loop 
    add_out3 := add_out3 + Xin(k-i)*H(i); 
    end loop;
    

    Did the above changes in the for loop It works fine. So the code in my question is a correct code for FIR also, works smoothly. Learnt that one needs to be very careful while using signal or variables. All the signals get a new value at the same time i.e at the end of clock period, while in variables values gets updated as assigned within a process. Tried to run the simulation step by step and figured out the problem.