vhdl fsm counter condition

时间:2015-11-11 12:16:41

标签: vhdl counter fsm

所以,在我上一个学校项目中,我必须用VHDL实现一种计算各种值集的复杂平均值的算法。

我们必须使用带外部计数器的FSM来管理存储器的地址和管理状态变化。所以,当我完成一个集合时,我想从状态3移动到状态4,状态4移动到状态5,状态5移动到init。这是使用一个名为OlIn(用于memIn计数器)和OlOut(用于memOut计数器)的信号完成的。

    entity control is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           finish: out STD_LOGIC;
           op1, op2 : out  STD_LOGIC;
           muxes : out  STD_LOGIC_VECTOR (3 downto 0);
           enables : out  STD_LOGIC_VECTOR (2 downto 0);
           cenO, cenI : out STD_LOGIC;
           olIn, olOut : in STD_LOGIC;
           we: out STD_LOGIC);
end control;

architecture Behavioral of control is

type fsm_states is (s_init, load, cycle1, cycle2, cycle3, cycle4, cycle5, done);
signal next_state, state: fsm_states;
signal sfinish: STD_LOGIC;

begin
    state_reg : process(clk,rst)
    begin
        if (clk'event and clk='1') then
            if(rst = '1') then
                state <= s_init;
            else
                state <= next_state;
            end if;
        end if;             
    end process;

    state_comb: process(state,sfinish, olIn, olOut)
    begin
        next_state <= state;
        case state is
            when s_init =>
                next_state <= load;
            when load => 
                next_state <= cycle1;
            when cycle1 =>
                next_state <= cycle2;
            when cycle2 =>
                next_state <= cycle3;
            when cycle3 =>
                next_state <= cycle4;
            when cycle4 =>
                if(olIn='1') then
                    next_state <= cycle5;
                else
                    next_state <= cycle1;
                end if;
            when cycle5 =>
                if(olOut='1') then
                    next_state <= done;
                else 
                    next_state <= s_init;
                end if;
            when done =>
                next_state <= done;
        end case;
    end process;

    process (state,olIn)
    begin
        case state is
            when s_init =>  
                cenI <= '1';    
                cenO <= '0';
                muxes <= "XXXX"; 
                enables <= "X11";       
                op1 <= 'X';
                op2 <= 'X';
                sfinish <= '0';
                we <= '0';
            when load =>
                cenI <= '0';
                cenO <= '0';
                muxes <= "XXX0";
                enables <= "110"; 
                op1 <= 'X';
                op2 <= 'X';
                sfinish <= '0';
                we <= '0';
            when cycle1 =>
                cenI <= '0';
                cenO <= '0';
                muxes <= "0001";
                enables <= "110";
                op1 <= '0';
                op2 <= '0';
                sfinish <= '0';
                we <= '0';
            when cycle2 =>
                cenI <= '0';
                cenO <= '0';
                muxes <= "1011";
                enables <= "110";
                op1 <= '0';
                op2 <= '0';
                sfinish <= '0';
                we <= '0';
            when cycle3 =>  
                cenI <= '1';
                cenO <= '0';
                muxes <= "X101";
                enables <= "010";
                op1 <= '1';
                op2 <= '0';
                sfinish <= '0';
                we <= '0';
            when cycle4 =>
                cenI <= '0';
                cenO <= '0';
                muxes <= "XXXX";
                enables <= "100";
                op1 <= 'X';
                op2 <= 'X';
                sfinish <= '0';
                we <= '0';
                if(olIn = '1') then
                    we <= '1';
                    cenO <= '1';
                end if;
            when cycle5 =>
                cenI <= '0';
                cenO <= '1';
                muxes <= "XXXX";
                enables <= "110";
                op1 <= 'X';
                op2 <= 'X';
                sfinish <= '0';
                we <= '0';
                if (olIn = '1') then
                    we <= '1';
                    cenO<= '1';
                    cenI <= '1';
                end if;
            when done =>
                cenI <= '0';
                cenO <= '0';
                muxes <= "XXXX";
                enables <= "000";
                op1 <= 'X';
                op2 <= 'X';
                sfinish <= '1';
                we <= '0';
        end case;
    end process;

    finish <= sfinish;
end Behavioral;

我实现memIn计数器的方式是这样的:

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.all;


entity counter is
    generic (N : integer := 4;  -- numero de bits do contador global
             Ni : integer := 3; -- numero de bits do contador local
             I : integer := 0   -- valor inicial dos contadores
            ); 
    Port ( 
          clk : in STD_LOGIC;
          rst: in STD_LOGIC;
          cen : in  STD_LOGIC;
          ol : out STD_LOGIC;
          counter : out  STD_LOGIC_VECTOR (N-1 downto 0));
end counter;

architecture Behavioral of counter is
    signal counter2: std_logic_vector (Ni-1 downto 0);
    signal tmp, i_aux: std_logic_vector (N-1 downto 0);
begin

    i_aux<=std_logic_vector(to_unsigned(I, i_aux'length));

    process (clk, rst, cen, i_aux, counter2)
    begin
        if (rst ='1') then
            tmp <= i_aux;
            counter2 <= i_aux(Ni-1 downto 0);
        elsif (clk'event and clk = '1') and (cen = '1')  then
            ol <= '0';
            tmp <= tmp + 1;
            counter2 <= counter2 + 1;
        end if;
        if ( counter2 = "1010" ) then
            ol <= '1';
        end if;
        if ( counter2 = "1011" ) then
            ol <= '0';
            counter2 <= ( 0 => '1', others => '0');
        end if;
    end process;
    counter <= tmp;

end Behavioral;

但是,因为模式检测发生在进程外部,所以路由后模拟失败。如果我将模式检测放在流程中,它总是提前一个周期或持续太长时间,我无法纠正它。

要检测的模式是二进制数字9(1010),然后,计数器发送一个Ol信号来控制,该信号表示处理集合中所有数据的结束。

进行此检测的过程是在柜台内部的过程中,但我能使其工作的唯一方法是在该过程之外。

计数器的位0:输出不进入存储器(我必须在两个周期内保持相同的存储器地址),因此计数器应计为8(4个存储器地址(1到4)存储器地址0用于准备数据。

我怎么能做得更好?我是否应该将检测放在过程中并更加努力地找到一个有效的匹配检测器?

由于

1 个答案:

答案 0 :(得分:1)

反制过程正在转向危险的水域;它是部分同步过程和部分组合,并且几乎没有合成结果与模拟行为匹配的可能性。这可能是您报告路线后SIM卡问题的原因。

作为同步过程,其敏感性列表应该是process (clk, rst)而不是其他任何内容,模式测试应该在if rising_edge(clk)子句中。

但是,必须在理解how signal and variable assignments are scheduled.的情况下编写它。具体来说,如果你不理解这一点,你可能会发现事情发生的时间比预期的要晚。两种方法可能有所帮助:

  1. 如果counter2是变量,则对更新后的值进行比较,并在ol = 10时设置counter2
  2. 或者你可以简单地将比较推进一个周期,例如: if ( counter2 = "1001" ) then以便在counter2 成为 10的同一周期中设置标志。这实际上会生成更快的硬件,因为比较和增量并行发生,在注册时运行输入,而不是对组合加法器的输出进行比较。
  3. 对于alternative approach,您不仅可以消除计数器过程,还可以消除互连它们的四个控制信号。我强烈推荐这种单过程方法,用于更小,更简单,更可靠的代码,尽管在某些学术界似乎不受欢迎。