【问题标题】:VHDL reset during execution执行期间 VHDL 复位
【发布时间】:2018-12-05 07:58:59
【问题描述】:

我正在开发一个安全序列检测器,它是一个 FSM,它使用 3 个不同的过程。它具有表示输入数字的输入 num_in(8 位)和仅在第一个数字期间必须为“1”的 first 输入(1 位),否则FSM 进入固定输出状态。如果用户插入 3 个错误的输入序列,这种情况可能会再次发生。输出由 unlock 信号(如果序列正确则等于 '1')和 warning 信号(如果序列错误则等于'1' ),并且它们都必须每 5 个时钟周期更新一次,因为序列由 5 个数字组成,即使其中一个输入是错误的。第一个过程是:

state_register_p : process(rst, clk)
        begin 
            if rst = '0' then   -- initial state, asynchronous rst
                current_state <= S0;
            elsif (clk'EVENT and clk = '1') then
                if(rst = '0') then
                    current_state <= S0;
                    --errors <= -1;
                else
                    current_state <= next_state;
                    five_cycles <= std_logic_vector(to_unsigned((to_integer(unsigned(five_cycles)) + 1), five_cycles'length));
                    if to_integer(unsigned(five_cycles)) = 5 then
                        five_cycles <= "001";
                    end if;
                 end if;
            end if;
    end process state_register_p;

在这个 FSM 中,我收到每个时钟的 8 位数字,我必须检查它是否在正确的序列中,如果不是,从开始的 5 个周期后我设置一个错误。当 error = 3 时,FSM 进入另一种状态,其中 unlock 固定为 0,warning 固定为 1,直到再次给出复位作为输入,并且FSM 从初始 S0 状态开始。 我的测试台代码是这样的:

clk_tb <= (not(clk_tb) and end_sim) after T_CLK / 2; 
rst_tb <= '1' after T_RESET;

d_process: process(clk_tb, rst_tb)
    variable t : integer := 0; 
  begin
    if(rst_tb = '0') then
      num_in_tb <= (others => '0');
      first_tb <= '0';
      t := 0;
    elsif(rising_edge(clk_tb)) then
      case(t) is 
        -- correct
        when 1 => num_in_tb <= "00100100"; first_tb <= '1';  --36
        when 2 => num_in_tb <= "00010011"; first_tb <= '0';  --19
        when 3 => num_in_tb <= "00111000"; first_tb <= '0';  --56
        when 4 => num_in_tb <= "01100101"; first_tb <= '0';  --101
        when 5 => num_in_tb <= "01001001"; first_tb <= '0';  --73

        --invalid because of the num_in (error = 1, but still < 3)
        when 6 => num_in_tb <= "00100100"; first_tb <= '1';  --36
        when 7 => num_in_tb <= "00010011"; first_tb <= '0';  --19
        when 8 => num_in_tb <= "00111000"; first_tb <= '0';  --56
        when 9 => num_in_tb <= "01100100"; first_tb <= '0';  --100
        when 10 => num_in_tb <= "01001001"; first_tb <= '0';  --73

        --invalid because of the two first (blocking condition) 
        when 11=> num_in_tb <= "00100101"; first_tb <= '0';  --37
        when 12=> num_in_tb <= "00100110"; first_tb <= '1';  --38
        when 13=> num_in_tb <= "00100111"; first_tb <= '1';  --39

        --reset is needed
        when 14=> rst_tb <= '0', '1' after T_RESET;  --unknown behavior here

        -- correct
        when 15 => num_in_tb <= "00100100"; first_tb <= '1';  --36
        when 16 => num_in_tb <= "00010011"; first_tb <= '0';  --19
        when 17 => num_in_tb <= "00111000"; first_tb <= '0';  --56
        when 18 => num_in_tb <= "01100101"; first_tb <= '0';  --101
        when 19 => num_in_tb <= "01001001"; first_tb <= '0';  --73

        when 20 => end_sim <= '0';
        when others => null; -- Specifying that nothing happens in the other cases 

      end case;
      t := t + 1;
    end if;
  end process;

我想在 T_RESET 之后插入类似 when 14=> rst_tb 的内容来重置我的 FMS。我该怎么做?谢谢

【问题讨论】:

    标签: vhdl reset fsm


    【解决方案1】:

    您目前在多个位置驾驶rst_tb,这是一个冲突。从d_process 之外删除它,并从您的敏感列表中删除rst_tb。那么你的 if 语句将是:

    if rising_edge(clk_tb) then ...
    

    您可以在执行重置的t 变量上创建when 0 =&gt; 子句:

    when 0 =>
      num_in_tb <= (others=>'0');
      first_tb <= '0';
      t := 0;
      rst_tb <= '0', '1' after T_RESET;
    

    然后您可以在您的when 14 =&gt; 子句中再次驱动rst_tb

    ...
    
    when 14 =>
      rst_tb <= '0', '1' after T_RESET;
    
    ...
    

    您必须使您的 T_RESET 短于 clk_tb 期间,否则您的 state_register_p 进程将开始缺少来自 d_process 的刺激。

    编辑:

    library IEEE;
    use IEEE.std_logic_1164.all;
    library STD;
    use STD.textio.all;
    
    entity tb is
    end tb;
    
    architecture arch of tb is
    
    constant T_RESET : time := 5 ns;
    constant T_CLK   : time := 10 ns;
    
    signal clk_tb    : std_logic := '0';
    signal rst_tb    : std_logic := '0';
    signal trig_rst  : std_logic := '0';
    signal num_in_tb : std_logic_vector(7 downto 0);
    signal first_tb  : std_logic := '0';
    signal end_sim   : std_logic := '1';
    
    begin
    
    --  rst_tb <= '0','1' after T_RESET;
    clk_tb <= (not(clk_tb) and end_sim) after T_CLK / 2; 
    
    --d_process: process(clk_tb, rst_tb)
    d_process: process(clk_tb)
      variable t : integer := 0; 
    begin
    --    if(rst_tb = '0') then
    --      num_in_tb <= (others => '0');
    --      first_tb <= '0';
    --      t := 0;
    --    elsif(rising_edge(clk_tb)) then
      if(rising_edge(clk_tb)) then
        case(t) is 
        when 0 =>
          num_in_tb <= (others=>'0');
          first_tb <= '0';
          rst_tb <= '0', '1' after T_RESET;
        -- correct
        when 1 => num_in_tb <= "00100100"; first_tb <= '1';  --36
        when 2 => num_in_tb <= "00010011"; first_tb <= '0';  --19
        when 3 => num_in_tb <= "00111000"; first_tb <= '0';  --56
        when 4 => num_in_tb <= "01100101"; first_tb <= '0';  --101
        when 5 => num_in_tb <= "01001001"; first_tb <= '0';  --73
    
        --invalid because of the num_in (error = 1, but still < 3)
        when 6 => num_in_tb <= "00100100"; first_tb <= '1';  --36
        when 7 => num_in_tb <= "00010011"; first_tb <= '0';  --19
        when 8 => num_in_tb <= "00111000"; first_tb <= '0';  --56
        when 9 => num_in_tb <= "01100100"; first_tb <= '0';  --100
        when 10 => num_in_tb <= "01001001"; first_tb <= '0';  --73
    
        --invalid because of the two first (blocking condition) 
        when 11 => num_in_tb <= "00100101"; first_tb <= '0';  --37
        when 12 => num_in_tb <= "00100110"; first_tb <= '1';  --38
        when 13 => num_in_tb <= "00100111"; first_tb <= '1';  --39
    
        --reset is needed
        when 14 => rst_tb <= '0', '1' after T_RESET;  --unknown behavior here
    
        -- correct
        when 15 => num_in_tb <= "00100100"; first_tb <= '1';  --36
        when 16 => num_in_tb <= "00010011"; first_tb <= '0';  --19
        when 17 => num_in_tb <= "00111000"; first_tb <= '0';  --56
        when 18 => num_in_tb <= "01100101"; first_tb <= '0';  --101
        when 19 => num_in_tb <= "01001001"; first_tb <= '0';  --73
    
        when 20 => end_sim <= '0';
        when others => null; -- Specifying that nothing happens in the other cases 
    
        end case;
        t := t + 1;
      end if;
    end process d_process;
    
    end arch;
    

    【讨论】:

    • 我正在尝试您的解决方案,但我的 rst_tb 仍然处于 X 状态一个时钟周期,在 ModelSim 中显示红色图,其中时钟周期为 10ns,我的 T_RESET 为 5ns。
    • 我注意到如果我在 t = 0 => rst = 0、t=1 => rst = 0 时开始工作,然后当我输入我的t = 2 => rst = 1, num_in = ... 中的第一个数字,但在模拟图中,我在第一个从 0 到 1 的上升沿上有一条小红线,它在 t 时仍保持在 X 状态= 14
    • 如果将rst_tb 初始化为'0' 声明它的位置:signal rst_tb : std_logic := '0';,那么它不应该是'X'。你可以对first_tb做同样的事情。
    • 问题是,当我在 T_RESET 之后的 case 14 rst = '0', '1' 的情况下,直到那个 istant 的整个信号变成红色,处于 X 状态,就像它也是由其他进程
    • 您在 X 状态下看到的信号是什么?在使用 ModelSim 进行仿真时,我没有看到这一点。用我正在模拟的代码更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多