【问题标题】:VHDL State machine stucks in an impossible stateVHDL 状态机卡在不可能的状态
【发布时间】:2017-12-11 07:32:18
【问题描述】:

我写了一个 VHDL 状态机。它会工作一段时间,直到陷入不可能的状态。

总共有 7 个州,但我们只对其中两个州感兴趣。状态图很简单:

IDLE2 IDLE 其他状态

也就是说,初始状态是IDLE。所有其他状态都可以通过IDLE state 到达。状态IDLE2只能跳转到IDLE状态。

代码片段:

ENTITY MC_PLD_vhd IS
    PORT
    (
        --INPUTS
        MC_WR: IN STD_LOGIC;
        MC_RD: IN STD_LOGIC;
        Tstart: IN STD_LOGIC;
        CLK: IN STD_LOGIC;
        --OUTPUTS
        PLD_WR: OUT STD_LOGIC;
        PLD_RD: OUT STD_LOGIC;
        STS: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
    );
END MC_PLD_vhd;

ARCHITECTURE MC_PLD_vhd_dff OF MC_PLD_vhd IS
    TYPE tSTATE is 
    (
        IDLE   --0
        ,REC1  --1
        ,SEND1 --2
        --I omit some not significant states
        ,IDLE2 --6
         
    );
    SIGNAL STATE :tSTATE := IDLE;
BEGIN
    PROCESS(CLK) IS
    BEGIN
        IF RISING_EDGE(CLK) THEN
            STS <= std_logic_vector(to_unsigned(tSTATE'pos(STATE), 8));
            CASE STATE IS
                WHEN IDLE =>
                    IF Tstart = '1' THEN
                        PLD_WR <= '1';
                        PLD_RD <= '0';
                        STATE <= SEND1; -- <!> stuck
                    ELSE
                        IF MC_WR = '1' THEN 
                            PLD_RD <= '1';
                            PLD_WR <= '0';
                            STATE <= REC1;
                        ELSE
                            PLD_WR <= '0';
                            PLD_RD <= '0';
                            STATE <= IDLE2;
                        END IF;
                    END IF;
                WHEN IDLE2 =>
                        PLD_WR <= '0';
                        PLD_RD <= '0';
                        STATE <= IDLE;
                WHEN IsReceiving_wait_RD_rise_1 => <...>
-- Other left away, as they don't add any information to my question.

您可能会注意到,IDLE 状态不是“稳定的”。机器在每个周期都必须离开IDLE 状态,即使没有发生任何事情:IDLE 跳转到IDLE2,并从IDLE2 返回到IDLE 下一个时钟周期。而且效果很好!

您还可能注意到,我独立于状态输出STATESTS。在 Altera SignalTap 中,我看到正常操作:状态来回跳转,并在适当的输入事件处进入其他状态。

问题

在多次正常运行后,我突然看到(在 SignalTap 中)STS = 0 并没有及时改变。这意味着STATE = IDLE,并且机器不会跳转到IDLE2STS = 6)。它不会通过任何输入事件跳转到任何状态,它只是停留在状态IDLE。从输出(PLD_WR = 1PLD_RD = 0)来看,代码卡在上面代码中的注释 &lt;!&gt; stuck 附近,但不会出现 STATE &lt;= SEND1

这怎么可能??

免责声明:状态 IDLE2 和输出 STS 是为调试此特定问题而实现的。

【问题讨论】:

  • 你的时钟停止了吗?否则,您的代码看起来很合理。如需更多调试,请在STS &lt;= ...; 之后添加一个新信号,即STS_d1 &lt;= STS; STS_d2 &lt;= STS_d1,然后在STS = STS_d1 = STS_d2 = 0x0 时在信号分接中设置触发
  • @Bill,时钟工作正常,因为其他不相关的逻辑工作正常。令人惊讶的是,我设法解决了将 switch-enum 块更改为 if-integer 的问题。
  • 请参阅下面的 matthew 评论以及您的答案。
  • 而你使用if->elsif->else->end if,而不是if->else if->else->@987654357 @->end if

标签: vhdl state-machine


【解决方案1】:

令人惊讶的是,我在发布此问题后就设法解决了自己的问题,尽管我为此苦苦挣扎了几天!

回答:我将 switch-enum 块更改为 if-integer

    PROCESS(CLK) IS
        CONSTANT STATE_IDLE :INTEGER := 0;
        CONSTANT STATE_RECEIVE :INTEGER := 1;
        --I omit other states
        CONSTANT STATE_IDLE2 :INTEGER := 6;
        VARIABLE STATE :INTEGER := 0;
    BEGIN
        IF RISING_EDGE(CLK) THEN
            STS <= std_logic_vector(to_unsigned(STATE, 8));
            IF STATE = STATE_IDLE THEN
                IF Tstart = '1' THEN
                    PLD_WR <= '1';
                    PLD_RD <= '0';
                    STATE := STATE_SEND_wait_RD;
                ELSE
                    IF MC_WR = '1' THEN 
                        PLD_RD <= '1';
                        PLD_WR <= '0';
                        STATE := STATE_RECEIVE;
                    ELSE
                        PLD_WR <= '0';
                        PLD_RD <= '0';
                        STATE := STATE_IDLE2;
                    END IF;
                END IF;
        ELSIF STATE = STATE_IDLE2 THEN
            PLD_WR <= '0';
            PLD_RD <= '0';
            STATE := STATE_IDLE;
        ELSIF STATE = STATE_RECEIVE THEN 
--Unsignificant states omitted

此外,我删除了调试 STS 输出和 IDLE2 状态,因为它们不再需要。幸运的是,它仍然有效!

但我仍然想知道为什么 switch-enum 不能正常工作。 可能是编译器错误,我使用的是“老好”的 Quartus II 8.1 Web

【讨论】:

  • 输入是否来自异步域? (传感器、开关、另一个时钟?)如果是,它们是否正确同步?
  • matthew 在这里所说的是状态机卡在未定义状态的最常见原因。状态机的所有输入都需要完全时钟同步,否则您的 fsm 状态将被破坏。
  • 首先,您从未在您的 Case 语句中向我们展示过 when Others 子句。此外,Matthew 指出必须将异步输入重新同步到时钟。这也困扰着IF 语句,尽管结果可能不同..(在 IF 语句中测试枚举并没有错,恢复为数字是完全没有必要的)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2012-10-16
  • 2019-07-23
  • 1970-01-01
  • 2013-07-22
  • 2015-08-10
相关资源
最近更新 更多