VHDL状态机陷入了不可能的状态

时间:2017-12-11 07:32:19

标签: vhdl state-machine

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

共有7个州,但其中只有两个对我们有意义。状态图很简单:

IDLE2< => IDLE< =>其他州

用语言来表示初始状态为IDLE。所有其他州都可以通过IDLE州达成。状态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下一个时钟周期。而且效果很好!

另外,您可能会注意到我通过STATE独立于州输出STS。在Altera SignalTap中,我看到正常操作:状态来回跳转,并在适当的输入事件中进入其他状态。

问题

突然经过多次正常操作后,我看到(在SignalTap中)STS = 0并且没有及时改变。这意味着STATE = IDLE,并且机器不会跳转到IDLE2STS = 6)。并且它不会通过任何输入事件跳转到任何状态,它只是处于状态IDLE。根据输出(PLD_WR = 1PLD_RD = 0)来判断代码会卡在上面代码中的评论<!> stuck附近,但STATE <= SEND1不会发生。

这怎么可能?

免责声明:已实施状态IDLE2和输出STS以调试此特定问题。

1 个答案:

答案 0 :(得分:0)

令人惊讶的是,在我发布这个问题之后,我设法解决了自己的问题,尽管事实上我已经挣扎了好几天了!

ANSWER :我将 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