0

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 ?

user3217310
  • 144
  • 1
  • 17
  • 1
    You need to understand the differences between signals and variables, especially in a clocked process. –  Mar 11 '14 at 12:58
  • I simulated (in testbench) the code which has sum expression It works fine and gives correct result, but when I replace the sum expression with the for loop it gives incorrect result. I checked the simulation using step by step also, all the steps for the for loop are in correct order only the output comes wrong?? I did not understand what you meant there by difference between the signals and variable. – user3217310 Mar 11 '14 at 13:06
  • 1
    [How does signal assignment work in a process?](http://stackoverflow.com/questions/5060635/how-does-signal-assignment-work-in-a-process) – fru1tbat Mar 11 '14 at 13:39
  • So the answer of you post says that the signals ( in my case signal array values) gets updated in the next cycle, but variable gets updated instantly ? So can i make an array of variable ? – user3217310 Mar 11 '14 at 13:53
  • I just replaced my 'add_out3' by a variable instead of a signal [variable sum_out3 : signed(15 downto 0) := (others => '0');] Then did the for loop but it is still showing incorrect outputs in Yout. – user3217310 Mar 11 '14 at 14:08
  • 1
    Good. Now think about the effects of signal assignment on j and k within the for loop... –  Mar 11 '14 at 14:12
  • @Brian Drummond : Hey even after using loops the number of LUTs are not decreased So how can I decrease the number of LUTs in my design.It has only around 7000 LUTs and I am using around 21000 LUTs. please give me some guidance. – user3217310 Mar 11 '14 at 18:20
  • 1
    There's no reason to expect reduced LUT usage since the loop is effectively unrolled to run in a single cycle. If you can tolerate taking more cycles to produce a result, you can reduce the hardware use by performing one mult/add per cycle. To accomplish that, the next thing to learn is ... state machines. Alternatively ; does your FPGA have hardware multipliers? There may be something stopping the synth tools from using them... –  Mar 11 '14 at 19:43
  • @BrianDrummond I wrote a FSM code for the above but it has some issues not for the first time calculation it gives correct output but after that output is not correct. – user3217310 Mar 21 '14 at 06:09
  • Remember that when a new sample arrives, it will take several cycles to generate its output; during that time you can expect incorrect output. Also : I find the "single process" form of FSM much easier to get right than this two process form (the sensitivity list may be incorrect, for a start) –  Mar 21 '14 at 12:25
  • 1
    yes so when it is taking time to generate a sample, I added a condition in FSM after seeing the simulation that for 64 cycles just do nothing and wait for the input as the slower clock generate an output in 16 cycles during that period the fast clock runs for 64 cycles ratio is 4. and after that from 64 to 76 FSM runs and generate an output and then when the FSM_monitor is 76 I make it zero again also by single process do you mean a process whose sensitivity list has only one variable ? – user3217310 Mar 21 '14 at 12:55

1 Answers1

1

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.

user3217310
  • 144
  • 1
  • 17