如何在 vhdl 中重置序列识别自动机中的变量?
Posted
技术标签:
【中文标题】如何在 vhdl 中重置序列识别自动机中的变量?【英文标题】:How to reset variables in a sequence recognition automaton in vhdl? 【发布时间】:2018-05-18 11:42:42 【问题描述】:我是 vhdl 的初学者。我创建了一个 000010 序列的识别器自动机 (Moore) 来访问电梯。识别全序列后,在X1状态电梯门打开,两个LED灯亮,X2和X3在5秒后门关闭,10秒后,电梯到达所需楼层。 用Modelsim模拟一切,没有错误。
我的问题是想要重置所有变量(然后返回到初始状态 X0)以防万一,例如,您处于任何状态。例如,在 X1 中,变量“esito”、led1 和 led2 应该返回 0。
由于无法在第一个过程中重置这些变量(重置条件 = 1),因为我会遇到错误“无法解析网络的多个常量驱动程序”(两者都使用相同的变量进程),我想问一下我在下面的代码中采用的解决方案是否正确(在对插入的序列执行控制之前重置X0中的变量)。
我希望我已经清楚了,你可以帮助我。
这是代码:
library IEEE;
use IEEE.std_logic_1164.all;
entity riconoscitore is
port(
simbolo:inout std_logic_vector(5 downto 0);
clock,esito,reset:inout std_logic;
led1,led2:out std_logic
);
end riconoscitore;
architecture myriconosc of riconoscitore is
type state_values is
(X0,X1,X2,X3);
signal current_st,next_st:state_values;
signal timer:std_logic;
begin
process(clock,reset)
begin
if(reset='1') then
current_st<=X0;
elsif(rising_edge(clock))then
current_st<=next_st;
end if;
end process;
process(current_st,simbolo,timer,reset)
begin
next_st<=X0;
case current_st is
when X0 =>
esito<='0';
led1<='0';
led2<='0';
reset<='0';
timer<='0';
simbolo<=('U','U','U','U','U','U');
if(simbolo="000010")then
next_st<=X1;
else
next_st<=X0;
end if;
when X1 =>
esito<='1';
led1<='1';
led2<='1';
timer<= transport '1' after 5 sec;
next_st<=X2;
when X2=>
led1<='0';
if(timer='1') then
next_st<=X3;
reset<= transport '1' after 10 sec;
else next_st<=X2;
end if;
when X3=>
if (reset='1') then
next_st<=X0;
esito<='U';
reset<='U';
timer<='U';
simbolo<=('U','U','U','U','U','U');
led2<='0';
else
next_st<=X3;
end if;
end case;
end process;
end myriconosc;
【问题讨论】:
【参考方案1】:您在顺序过程中的重置是异步的:
process(clock,reset)
begin
if(reset='1') then
current_st<=X0;
elsif(rising_edge(clock))then
current_st<=next_st;
end if;
end process;
只有在发生某些异常时才使用异步复位将触发器置于已知状态,目前最常见的是上电。永远不要将异步复位用于任何其他目的。永远不要将异步复位作为电路正常操作的一部分。
例如,假设您有一个带有两个按钮的秒表:START/STOP 和 RESET。因此,在比赛开始时,计时员会按 START/STOP 开始计时,而在比赛结束时,计时员会再次按 START/STOP停止计时。记录时间后,计时员将按下 RESET 将手表归零,为下一场比赛做好准备。假设一段时间后,电池耗尽。计时员会装上新电池,然后会发现秒表已经重置,为下一场比赛做好了准备。您可以使用异步重置来重置第二个(新电池)外壳中的手表;你永远不应该在第一种情况下使用一个,因为这不是一个例外 - 为下一场比赛重置为零是秒表作为其正常操作的一部分所做的事情。
因此,异步复位应该只连接到顺序进程(如上面的那个),并且应该用于将触发器无条件置于已知状态(即复位状态不应依赖于任何其他信号)。如果您不遵循这些规则,您将不会有同步设计,并且会给自己带来问题。
因此,在您的设计中,您应该使用异步复位将触发器置于已知状态 - X0
(正如您所做的那样) - 并且处于该状态时 FSM 的状态输出就是该状态他们有重置。就是这样。如果您不喜欢X0
状态下的输出状态,那么您需要更改它或者您需要将触发器重置为不同的状态。
【讨论】:
【参考方案2】:一个 您遇到问题的原因是您没有遵循 HDL 的编码规则。
您有两个部分:寄存器/时钟部分和组合部分。
在组合部分,您必须为每个状态下的每个信号和变量赋值。如果您忘记创建闩锁。应该避免闩锁,当然如果你只是开始编程的话。 这些锁存器保持其价值,这就是导致您的问题的原因。
有两种解决方案:
-
为每个状态下的每个信号和变量分配一个值。
使用默认值
两个
还有一个我以前没有见过的错误:
您的process(clock,reset)
取决于重置。在该过程中,您设置状态。
然后在下一个过程中您使用状态来设置重置。你刚刚创建了一个最讨厌的循环状态机! 从第二个过程中删除所有重置的使用。重置应该只控制你的第一个进程!
【讨论】:
啊,是的,我来自 Verilog,我们只有信号,我经常将信号称为变量。我会更新文字。以上是关于如何在 vhdl 中重置序列识别自动机中的变量?的主要内容,如果未能解决你的问题,请参考以下文章