【发布时间】: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 下一个时钟周期。而且效果很好!
您还可能注意到,我独立于状态输出STATE 到STS。在 Altera SignalTap 中,我看到正常操作:状态来回跳转,并在适当的输入事件处进入其他状态。
问题
在多次正常运行后,我突然看到(在 SignalTap 中)STS = 0 并没有及时改变。这意味着STATE = IDLE,并且机器不会跳转到IDLE2(STS = 6)。它不会通过任何输入事件跳转到任何状态,它只是停留在状态IDLE。从输出(PLD_WR = 1 和 PLD_RD = 0)来看,代码卡在上面代码中的注释 <!> stuck 附近,但不会出现 STATE <= SEND1。
这怎么可能??
免责声明:状态 IDLE2 和输出 STS 是为调试此特定问题而实现的。
【问题讨论】:
-
你的时钟停止了吗?否则,您的代码看起来很合理。如需更多调试,请在
STS <= ...;之后添加一个新信号,即STS_d1 <= STS; STS_d2 <= 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