提问人:David 提问时间:1/5/2017 最后编辑:David 更新时间:1/12/2017 访问量:394
无法使简单的位序列识别器电路正常工作 (FSM)
Can't get simple Bit Sequence Recognizer circuit to work (FSM)
问:
这是我正在参加的硬件课程的简单练习。我们需要使用 Altera Quartus II 和 ModelSim 来测试实现;我以前从未使用过的工具,所以我可能遗漏了一些东西,而我的解释也有所欠缺。
该电路有 3 个输入(数据、时钟和复位)和 2 个输出(锁定、错误)。本练习中使用的顺序是 。10001
问题要求设计一个能够识别位序列的电路。当输入正确的序列时,您将被授予访问权限(电路进入“解锁”状态;锁定输出为 0)。否则,如果在任何时候您输入了错误的位,您将触发警报,并且您应该保持“错误”状态,直到电路被手动复位。
“锁定”始终为 1,除非它进入“解锁”状态。“Error”始终为 0,除非它进入“ERROR”状态。
电路应该始终以“RESET”状态启动。一旦它进入“解锁”状态,只要提供的位是 1,它就会保持在那里,或者如果遇到 0,它就会进入“RESET”。
这是我制定的状态图:
欢迎任何帮助或想法!
事实证明,我的实现背后的几乎所有逻辑都是正确的,问题是在人字拖上使用 CLRN 的误解和其中一个作业中的错别字。因此,大多数图像都被删除以消除混乱。
-- 编辑 1
使用以下代码(应该是正确的),波形与预期不符(至少不是)lock
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity dlock is
port
(
DATA : IN STD_LOGIC;
RESET : IN STD_LOGIC;
CLOCK : IN STD_LOGIC;
LOCK : OUT STD_LOGIC;
ALARM : OUT STD_LOGIC
);
end dlock;
architecture bdf_type of dlock is
type STATE_type is (S_RESET, S1, S2, S3, S4, UNLOCK, S_ALARM);
signal state : STATE_type := S_RESET;
begin
process (clock) is
begin
if (rising_edge(clock)) then
-- `reset` always puts us back in the reset state
if (RESET = '1') then
state <= S_RESET;
else
case state is
when S_RESET =>
-- Reset; lock active and alarm off
LOCK <= '1';
ALARM <= '0';
if (DATA = '1') then
-- Correct bit, proceed to next state
state <= S1;
else
-- Incorrect bit; ALARM
state <= S_ALARM;
end if;
when S1 =>
if (DATA = '0') then
state <= S2;
else
state <= S_ALARM;
end if;
when S2 =>
if (DATA = '0') then
state <= S3;
else
state <= S_ALARM;
end if;
when S3 =>
if (DATA = '0') then
state <= S4;
else
state <= S_ALARM;
end if;
when S4 =>
if (DATA = '1') then
state <= UNLOCK;
else
state <= S_ALARM;
end if;
when UNLOCK =>
-- Lock inactive!
LOCK <= '0';
if (data = '0') then
state <= S_RESET;
else
state <= UNLOCK;
end if;
when S_ALARM =>
-- Alarm active in ALARM state
ALARM <= '1';
end case;
end if;
end if;
end process;
end bdf_type;
答:
VHDL中写入的复位为低电平有效。这意味着您大部分时间都在复位电路。您的数据模式看起来像您认为您的重置处于高电平有效状态。
就我在发布的波形图像中看到的而言,您的错误信号表现正常。每次退出一个周期的重置时,您的数据都是 0,这会将您发送到错误状态。当然,这只持续一个周期,因为您立即再次重置。
这些只是小故障,如果你放大,你会看到幻影解锁发生 0 次(或非常小的时间段,具体取决于您的门型号)。这就是为什么组合逻辑的输出不用于时钟数据的原因之一。通过触发器传递值将消除毛刺。
编辑:
此外,状态分配表和状态输出表彼此不一致。一个列出 downto 的值,另一个列出 to 的值,但两者都将状态列为 。这不会给状态带来问题,因为向前和向后读取相同。Q
Q2
Q0
Q0
Q2
unlocked
"110"
Error
"111"
编辑2: 至于避免故障......毛刺是组合逻辑的本质。
您可以直接从翻牌中获取数据,而不会增加延迟,方法是让“锁定”翻牌的输入由解锁状态的相同前提条件决定(即 并使用 .locked
locked_d = not((state=s4 or state=locked) and data=1)
locked_q
您可以通过将状态机机编码转换为单热或混合单热编码来避免锁定成为多个状态位的函数(其中有一个用于锁定/错误状态的专用位,因为它们驱动输出位,但其他 5 个状态使用 3 个共享状态位)。
可以考虑如下状态表:
Q4 Q3 Q2 Q1 Q0 State
0 1 0 0 0 Reset
0 1 0 0 1 S1
0 1 0 1 0 S2
0 1 0 1 1 S3
0 1 1 0 0 S4
0 0 X X X Unlock
1 1 X X X Error
1 0 X X X X
0 1 1 0 1 X
0 1 1 1 X X
你的位在哪里,你的位在哪里Q4
error
Q3
locked
也就是说,避免毛刺通常并不重要,因为在D输入或时钟使能时序逻辑中使用毛刺时,毛刺不会引起问题。
评论
1
Q
Q2
Q0
Q0
Q2
"110"
UNLOCK
我想说的是,你的方法让你的生活变得不必要地变得更加困难。你根本不需要这些和信号,只需完全按照你在问题开头的优秀图表中看到的那样对状态机进行编码。我还没有编写完整的代码,但这应该显示了导致最小、易于阅读结果的基本方法:D
Q
type STATE_type is (S_RESET, S1, UNLOCK, ERROR);
signal state : STATE_type := S_RESET;
...
process (clock) is
begin
if (rising_edge(clock)) then
-- `reset` always puts us back in the reset state
if (reset = '1') then
state <= S_RESET;
else
case state is
when S_RESET =>
-- Reset; lock active and alarm off
lock <= '1';
alarm <= '0';
if (data = '1') then
-- Correct bit, proceed to next state
state <= S1;
else
-- Incorrect bit; error
state <= ERROR;
end if;
when S1 =>
if (data = '0') then
state <= UNLOCK;
else
state <= ERROR;
end if;
when UNLOCK =>
-- Lock inactive!
lock <= '0';
if (data = '0') then
state <= RESET;
end if;
when ERROR =>
-- Alarm active in error state
alarm <= '1';
end case;
end if;
end if;
end process;
您应该能够轻松地添加其他状态并继续添加其他状态。S2
如果需要 和 在断言后立即更改状态,则应实现异步重置,而不是上面示例中的同步重置:lock
alarm
reset
if (reset = '1') then
state <= S_RESET;
alarm <= '0';
lock <= '1';
elsif (rising_edge(clock)) then
case state is
-- `when` statements
end case;
end if;
以这种方式编写它的另一个优点是,您可以轻松地将所需的模式设置为常量:
constant PATTERN : std_logic_vector(0 to 4) := "10001";
然后,不同状态下的数据比较将如下所示:
when S_RESET =>
if (data = PATTERN(0)) then
...
when S1 =>
if (data = PATTERN(1)) then
等。然后,您可以通过简单的单行更改来更改所需的模式。
评论
reset
lock
UNLOCK
lock
reset
lock
lock
lock <= '0';
state <= UNLOCK;
else
UNLOCK
alarm
0
reset
1
lock
1
alarm
state <= ERROR;
评论