Finite state machine FSM model of FIR filter in VHDL for FPGA

digital filterfirfpgastate-machinesvhdl

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;

I am not able to receive the same output which I received by the first code with FSM model. 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 ?

Best Answer

Your second "FSM" code has many problems, primarily in the last process — process (current_s, input). Just a few examples to start with:

  • This is an asynchronous process, so you must list all of the signals used inside of it in the sensitivity list. Failing to do this means that the simulation will not match the behavior of the actual hardware.
  • Since not every output is assigned on every possible path through the code, you're creating an enormous number of implicit latches, which will probably simulate OK but give you lots of problems in synthesis.

In addition, this is a poorly-asked question:

  • You didn't document the relationship between Clk and clk_fast.
  • You didn't format (e.g., indent) the code to make it easy for others to follow.
  • You didn't comment the code so that we could figure out what your intent was.

Anyway, in general, an FSM is not the recommended approach for this sort of problem. What you really need to do is set up a pipeline to do the FIR arithmetic. This would allow you to eliminate the fast clock altogether, along with the complicated FSM logic. The module will produce the same output as the original module, except that it will be delayed by the number of stages in your pipeline.