我写了一个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
,并且机器不会跳转到IDLE2
(STS = 6
)。并且它不会通过任何输入事件跳转到任何状态,它只是处于状态IDLE
。根据输出(PLD_WR = 1
和PLD_RD = 0
)来判断代码会卡在上面代码中的评论<!> stuck
附近,但STATE <= SEND1
不会发生。
免责声明:已实施状态IDLE2
和输出STS
以调试此特定问题。
答案 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