状态机;为什么只有最后一个状态在工作? [英] State machine; why only last state is working?

查看:27
本文介绍了状态机;为什么只有最后一个状态在工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有 6 个状态(3 个主要状态)的状态机.只有最后一个状态有效,但前 2 个状态无效(共 3 个).只有最后一个状态有效.我发现了问题,当我移除去抖动电路时它可以工作,但我需要去抖动电路.我从互联网上得到了去抖动电路.如果有人可以提供帮助,我会很高兴.

I have a state machine with 6 states(3 main states). Only the last state is working but the first 2 doesn't(out of 3).Only the last state is working. I found out the problem, when I remove the debounce circuit it works, but I need the debouncing circuit. I got the debouncing circuit from the internet. I would be glad if someone can help.

 type SM_STATES is (state_column_1, scan_col_1, state_column_2, scan_col_2,
                          state_column_3, scan_col_3);
 signal my_state     : SM_STATES                   := state_column_1;

下面是状态机:

scanner_sm : process (clk)
begin  -- process key_scanner
  if clk'event and clk = '1' then

  if state_inc = '1' then -- clock divider finished counting down 100000

    -- reset scan_complete
    scan_complete <= '0';

case my_state is

  when state_column_1 =>
    scanned_val  <= (others => '0');
    original_col   <= "110";
    my_state <= scan_col_1;

  when scan_col_1 =>
    case bcd_val is
      when "1110" => scanned_val <= "1100100";  -- 1 wrong
      when "1101" => scanned_val <= "1100010";  -- 2 wrong
      when others => scanned_val <= "0010000";
    end case;
    my_state <= state_column_2;

  when state_column_2 =>
    original_col   <= "011";
    my_state <= scan_col_2;

  when scan_col_2 =>
    case bcd_val is
      when "1110" => scanned_val <= "1011011";  -- 5 wrong
      when "1101" => scanned_val <= "1011111";  -- 6 wrong
      when others => scanned_val <= "0000000";
    end case;
    my_state <= state_column_3;

  when state_column_3 =>
    original_col   <= "101";
    my_state <= scan_col_3;

  when scan_col_3 => -- Reading S1 // The only working state
    case bcd_val is
      when "1110" => scanned_val <= "1100000";  -- 9/ 1
      when "1101" => scanned_val <= "0111110";  -- X/ 2
      when others => scanned_val <= "0000000";
    end case;
    my_state <= state_column_1; -- ************ Error might be here
    scan_complete <= '1'; -- ********** Error might be here

  when others => scanned_val <= "0000000";
end case;

      end if;
  end if;
end process scanner_sm;

debounce: process (CLK) is 
begin 
 if (CLK'event and CLK = '1') then  
  Q0 <= scannel_val; 

  Q1 <= Q0; 

  Q2 <= Q1; 

 end if; 

end process; 

Final_val <= Q0 and Q1 and (not Q2);

end Behavioral; 

推荐答案

到目前为止您的代码是不完整的 - 您在 case 语句中直接分配给由状态机评估的信号 my_state.要理解这个问题,我们需要知道模拟器是如何工作的:

Your code so far is incomplete - you directly assign within your case statement to the signal my_state which is evaluated by the state machine. To understand the problem with this we need to know how the simulator works:

与实际硬件相比,模拟器必须按顺序使用顺序 CPU 处理代码.这是通过在无穷小的时间距离内一遍又一遍地运行代码来实现的 - 所谓的 Delta 延迟 - 直到所有依赖项都解决了,即没有任何变化.

In comparison to actual hardware the simulator has to process the the code with a sequential CPU in a sequential matter. This works by running through the code over and over again in infinitesimal time distances - the so called Delta delay - until all dependencies have resolved, i.e. nothing changes anymore.

请注意,在此迭代期间没有经过实际时间.在正确编写的设计中,模拟器现在等待下一个事件发生 - 通常是由再次重新启动顺序迭代的时钟滴答引起的.

Note that no actual time has passed during this iterations. In a correctly written design the simulator now waits until the next event occurs - usually caused by the tick of a clock which again restarts the sequential iterations.

您的示例基本上类似于一个无限循环:my_state 的更改总是会导致 my_state 的下一次更改,因此模拟器永远不会确定一个值 - 直到它达到硬编码的迭代限制,这碰巧在你的情况下是第三种状态.

Your example basically resembles an infinite loop: a change of my_state always causes the next change of my_state and thus the simulator never settles to a value - until it reaches a hardcoded iteration limit which, by chance in your case is the third state.

那么,如何解决这个问题?我们需要引入一个时钟,需要根据实际仿真时间进行状态转换,通常是等待一个时钟事件.最佳做法是将组合部分和顺序部分分成两个不同的过程,如状态机的这个最小示例所示:

So, how to fix this? We need to introduce a clock and need to make the state transition depending on the actual simulation time, usually by waiting for a clock event. Best practice is to separate the combinatoric and sequential parts into two different processes as shown in this minimal example of your state machine:

library ieee;
use ieee.std_logic_1164.all;

entity foo is

end entity foo;

architecture bar of foo is
  type SM_STATES is (state_column_1, scan_col_1, state_column_2, scan_col_2, state_column_3, scan_col_3);
  signal my_state, my_state_next : SM_STATES;
  signal bcd_val                 : std_logic_vector(3 downto 0) := "1110";
  signal clk                     : std_logic                    := '1';
  signal nRST                    : std_logic                    := '0';
  signal scanned_val             : std_logic_vector(6 downto 0);
  signal original_col            : std_logic_vector(2 downto 0);
  signal scan_complete           : std_logic;
begin  -- architecture bar

  comb : process (my_state, bcd_val) is
  begin  -- process baz
    case my_state is

      when state_column_1 =>
        scanned_val   <= (others => '0');
        original_col  <= "110";
        my_state_next <= scan_col_1;

      when scan_col_1 =>
        case bcd_val is
          when "1110" => scanned_val <= "1100100";  -- 1 wrong
          when "1101" => scanned_val <= "1100010";  -- 2 wrong
          when others => scanned_val <= "0010000";
        end case;
        my_state_next <= state_column_2;

      when state_column_2 =>
        original_col  <= "011";
        my_state_next <= scan_col_2;

      when scan_col_2 =>
        case bcd_val is
          when "1110" => scanned_val <= "1011011";  -- 5 wrong
          when "1101" => scanned_val <= "1011111";  -- 6 wrong
          when others => scanned_val <= "0000000";
        end case;
        my_state_next <= state_column_3;

      when state_column_3 =>
        original_col  <= "101";
        my_state_next <= scan_col_3;

      when scan_col_3 =>                -- Reading S1 // The only working state
        case bcd_val is
          when "1110" => scanned_val <= "1100000";  -- 9/ 1
          when "1101" => scanned_val <= "0111110";  -- X/ 2
          when others => scanned_val <= "0000000";
        end case;
        my_state_next <= state_column_1;  -- ************ Error might be here
        scan_complete <= '1';           -- ********** Error might be here

      when others => scanned_val <= "0000000";
    end case;
  end process comb;

  process (clk, nRST) is
  begin  -- process
    if nRST = '0' then                  -- asynchronous reset (active low)
      my_state <= state_column_1;
    elsif clk'event and clk = '1' then  -- rising clock edge
      my_state <= my_state_next;
    end if;
  end process;

  -- this clock and reset signal would usually be supplied from the outside
  clk  <= not clk after 10 ns;
  nRST <= '1'     after 101 ns;
end architecture bar;

如果我们现在在模拟器中运行这个文件,我们可以看到每个时钟周期的状态切换:

If we run this file now within a simulator we can see the states switching with each clock cycle:

这篇关于状态机;为什么只有最后一个状态在工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆