【问题标题】:FSM model of FIR filterFIR滤波器的FSM模型
【发布时间】:2014-04-15 02:11:00
【问题描述】:

我想做一个 FIR 的 FSM 模型,为此我需要在 FSM 实现中编写 FIR 计算代码行。

这是 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;

现在下面是我尝试的 FSM 实现,但没有得到与输入相同的示例,有人可以告诉我代码中可能存在什么问题吗?

---------------- FIR 滤波器的 FSM 实现 -------------------------------- ---

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;

我无法收到与第一个代码相同的输出。 FSM 代码为第一个输出提供了正确的输出,但从第二个输出示例中它给出了错误的结果。有人能告诉我我做错了什么吗?

【问题讨论】:

  • 您需要了解信号和变量之间的区别,尤其是在时钟进程中。
  • 好。现在想想 for 循环中信号分配对 j 和 k 的影响...
  • 没有理由期望减少 LUT 的使用,因为循环被有效地展开以在单个循环中运行。如果您可以容忍花费更多的周期来产生结果,您可以通过每个周期执行一次乘法/加法来减少硬件使用。要做到这一点,接下来要学习的是……状态机。或者 ;你的FPGA有硬件乘法器吗?可能会有一些东西阻止合成工具使用它们......
  • 是的,所以当需要时间来生成样本时,我在看到模拟后在 FSM 中添加了一个条件,即 64 个周期什么都不做,等待输入,因为较慢的时钟在在此期间的 16 个周期,快速时钟运行 64 个周期的比率为 4。然后从 64 到 76 FSM 运行并生成输出,然后当 FSM_monitor 为 76 时,我也通过单个进程将其再次设为零你是指一个进程谁的敏感度列表只有一个变量?

标签: filter filtering vhdl digital-filter


【解决方案1】:

此答案适用于问题的初始版本,但现在问题已更改。 使 add_out3 成为变量而不是信号。

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

在for循环中进行了上述更改它工作正常。 所以我问题中的代码也是 FIR 的正确代码,运行顺利。 了解到在使用信号或变量时需要非常小心。所有信号同时获得一个新值,即在时钟周期结束时,而在变量中,值会根据进程中的分配进行更新。尝试一步步运行模拟,发现问题所在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    相关资源
    最近更新 更多