这是我正在修的一门硬件课程的简单练习。我们需要使用Altera和ModelSim来测试实现,这是我以前从未使用过的工具,所以我可能遗漏了一些东西,以及我的解释。
该电路有3个输入(数据、时钟和复位)和2个输出(锁定,错误)。本练习中使用的序列是10001。
这个问题要求设计一个能识别一个位序列的电路。当输入正确的序列时,您将被授予访问权限(电路进入“解锁”状态;锁定输出为0)。否则,如果您在任何点输入错误的位,您触发一个警报,您应该保持“错误”状态,直到电路是手动复位。
除非进入“解锁”状态,否则“锁定”始终是1。除非达到“错误”状态,否则"Error“始终为0。
电路应该总是在“重置”状态下启动。一旦进入“解锁”状态,只要提供的位数为1,它就会留在那里,如果遇到0,则会进入“重置”状态。
这是我绘制的状态图:

欢迎任何帮助或想法!
事实证明,我的实现背后几乎所有的逻辑都是正确的,问题是在触发器上使用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;发布于 2017-01-05 19:38:09
编辑:此外,您的状态赋值表和状态输出表彼此不一致。一个列出了从Q到Q0的Q2值,另一个列出了从Q0到Q2的列表,但两者都将unlocked状态列表为"110"。这不会给Error状态带来问题,因为"111"会前后读取相同的内容。
EDIT2:为了避免小故障.故障是组合逻辑的本质。
您可以通过“锁定”触发器的输入由未锁定状态的相同先决条件(即,locked并使用locked_q )指定,从而直接从flop中获得源,而不增加延迟。
您可以通过将状态机编码转换为一个单一热状态或混合状态,从而避免锁定是多个状态位的函数(其中,锁定/错误状态有一个专用位,因为它们驱动输出位,而其他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输入或时钟启用时,它们在顺序逻辑中使用时不会引起问题。
发布于 2017-01-06 09:36:10
我想说的是,你的做法使你的生活变得不必要地困难。您根本不需要这些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然后,您可以通过简单的一行更改来更改所需的模式。
https://stackoverflow.com/questions/41483597
复制相似问题