到目前为止,您的代码还不完整 - 您直接在 case 语句中分配给信号my_state由状态机评估。要理解这个问题,我们需要知道模拟器是如何工作的:
与实际硬件相比,模拟器必须使用顺序 CPU 按顺序处理代码。这是通过在无限小的时间距离内一遍又一遍地运行代码来实现的 - 所谓的达美延迟 http://en.wikipedia.org/wiki/Delta_delay- 直到所有依赖关系都解决了,即不再发生任何变化。
请注意,在此迭代期间没有实际时间过去。在正确编写的设计中,模拟器现在会等待直到下一个事件发生——通常是由时钟的滴答声引起的,该时钟滴答声再次重新启动顺序迭代。
你的例子基本上类似于一个无限循环:改变my_state总是会导致 my_state 的下一次更改,因此模拟器永远不会稳定在某个值 - 直到它达到硬编码的迭代限制,在您的情况下碰巧是第三种状态。
那么,如何解决这个问题呢?我们需要引入一个时钟,并需要根据实际的模拟时间进行状态转换,通常是通过等待时钟事件来实现。最佳实践是将组合部分和顺序部分分成两个不同的进程,如状态机的这个最小示例所示:
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;
如果我们现在在模拟器中运行此文件,我们可以看到每个时钟周期的状态切换: