首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使简单的位序列识别电路工作(FSM)

无法使简单的位序列识别电路工作(FSM)
EN

Stack Overflow用户
提问于 2017-01-05 11:14:33
回答 2查看 361关注 0票数 2

这是我正在修的一门硬件课程的简单练习。我们需要使用Altera和ModelSim来测试实现,这是我以前从未使用过的工具,所以我可能遗漏了一些东西,以及我的解释。

该电路有3个输入(数据、时钟和复位)和2个输出(锁定,错误)。本练习中使用的序列是10001

这个问题要求设计一个能识别一个位序列的电路。当输入正确的序列时,您将被授予访问权限(电路进入“解锁”状态;锁定输出为0)。否则,如果您在任何点输入错误的位,您触发一个警报,您应该保持“错误”状态,直到电路是手动复位。

除非进入“解锁”状态,否则“锁定”始终是1。除非达到“错误”状态,否则"Error“始终为0。

电路应该总是在“重置”状态下启动。一旦进入“解锁”状态,只要提供的位数为1,它就会留在那里,如果遇到0,则会进入“重置”状态。

这是我绘制的状态图:

欢迎任何帮助或想法!

事实证明,我的实现背后几乎所有的逻辑都是正确的,问题是在触发器上使用CLRN时出现了误解,在其中一个任务中出现了错误。因此,大多数图像被移除以消除杂乱。

-编辑1

使用下面的代码(应该是正确的),波形不是预期的(至少lock不是)。

代码语言:javascript
复制
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;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-05 19:38:09

  1. 您的重置,如用VHDL编写的,是活动低的。这意味着你大部分时间都在重设电路。您的数据模式看起来像是您认为您的重置是有效的高。
  2. 你的错误信号,在我可以看到的图像波形张贴,是正确的行为。每次退出某个周期的重置时,数据都是0,这会将您发送到错误状态。当然,这只持续一个周期,因为您立即重新设置。
  3. 这些只是小故障,如果你放大,你会发现幻影解锁发生了0次(或者很小的时间周期取决于你的门模型)。这就是为什么组合逻辑的输出不用于时钟数据的原因之一。通过触发器传递值将消除故障。

编辑:此外,您的状态赋值表和状态输出表彼此不一致。一个列出了从QQ0Q2值,另一个列出了从Q0Q2的列表,但两者都将unlocked状态列表为"110"。这不会给Error状态带来问题,因为"111"会前后读取相同的内容。

EDIT2:为了避免小故障.故障是组合逻辑的本质。

您可以通过“锁定”触发器的输入由未锁定状态的相同先决条件(即,locked并使用locked_q )指定,从而直接从flop中获得源,而不增加延迟。

您可以通过将状态机编码转换为一个单一热状态或混合状态,从而避免锁定是多个状态位的函数(其中,锁定/错误状态有一个专用位,因为它们驱动输出位,而其他5个状态使用3个共享状态位)。

想象一下这样的状态表:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2017-01-06 09:36:10

我想说的是,你的做法使你的生活变得不必要地困难。您根本不需要这些DQ信号,只需按照问题开始时出色的图表中所看到的那样对状态机进行编码即可。我还没有编写完整的代码,但这应该会显示出一种基本的方法,可以得到最小的、易于阅读的结果:

代码语言:javascript
复制
type STATE_type is (S_RESET, S1, UNLOCK, ERROR);
signal state : STATE_type := S_RESET;

..。

代码语言:javascript
复制
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并继续添加到此状态。

如果您需要lockalarm在断言reset时立即更改状态,则应该实现异步重置,而不是上面示例中的同步重置:

代码语言:javascript
复制
  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;

用这种方式编写它的另一个优点是,您可以轻松地将所需的模式作为常量:

代码语言:javascript
复制
constant PATTERN : std_logic_vector(0 to 4) := "10001";

然后,您在各个州的数据比较如下:

代码语言:javascript
复制
when S_RESET =>
  if (data = PATTERN(0)) then

..。

代码语言:javascript
复制
when S1 =>
  if (data = PATTERN(1)) then

然后,您可以通过简单的一行更改来更改所需的模式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41483597

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档