第 16 章 有限状态机
1. 本章要解决的问题
计数器按照固定数值顺序更新状态,而实际控制器通常要根据输入选择下一步。例如:空闲时等待启动,请求到来后执行若干步骤,完成后产生通知,再回到空闲。仅靠一个计数序列无法完整表达这种带分支的行为。
有限状态机(finite-state machine, FSM)把控制问题拆成三部分:
- 当前处于什么状态;
- 在当前输入条件下,下一个状态是什么;
- 当前应产生什么输出。
本章回答七个问题:
- 怎样判断一个控制问题需要记住哪些历史?
- 状态图和状态表分别怎样表达状态转移?
- Moore 与 Mealy 状态机的输出为何具有不同时间语义?
- 怎样从文字规格完整设计一个小型 FSM?
- 状态名称怎样编码成触发器保存的位模式?
- 未使用状态、复位和异步输入应怎样处理?
- 怎样检查 FSM 的功能、时序和输出毛刺风险?
2. 与前面章节的联系
FSM 不是一种新的存储器件。它仍由第 12 章的寄存器和第 7~10 章的组合逻辑构成:
\[ Q^+=F(Q,X), \]
其中 \(Q\) 是当前状态,\(X\) 是当前输入,\(Q^+\) 是下一状态。第 13 章的计数器是状态转移规则特别规律的一类 FSM;第 14、15 章的时序约束与同步输入要求同样适用于 FSM。
3. 前置知识快速检查
- 同步寄存器在同一边沿读取旧状态还是已经更新的新状态?
- 组合逻辑输出只取决于当前输入,还是也能自己记住过去?
- 3 个状态至少需要多少个二进制状态位?
- 异步单比特电平进入同步控制器前,为什么通常先经过同步器?
- 状态寄存器到下一状态逻辑再返回状态寄存器,属于哪一类时序路径?
答案是:读取旧状态;组合逻辑不能独立记忆;2 bit;降低亚稳态传播风险;寄存器到寄存器路径。若第 1、3 题不熟,回看第 12、13 章;若第 4、5 题不熟,回看第 14、15 章。
4. 学习目标
完成本章后,你应能够:
- 从文字需求中识别必须保存的历史信息并定义状态;
- 按统一符号画出状态图、列出完整状态表;
- 区分 Moore 与 Mealy 状态机的输出依赖和响应时刻;
- 为小型 FSM 选择二进制或独热编码;
- 从状态表写出下一状态与输出逻辑;
- 为非法状态规定恢复路径;
- 根据复位、输入和时钟逐拍分析状态与输出;
- 检查异步输入、组合输出毛刺和状态路径时序。
5. 什么信息才需要成为状态
状态是为了正确处理未来输入而必须保留的过去信息。它不是程序执行到第几行,也不是任意给每个动作起一个名字。
考虑一个按钮控制的灯:每检测到一次有效按键事件,灯在开和关之间切换。当前输入只有“本拍是否有按键事件”,但相同的输入
press=1 可能产生两种结果:
- 灯原来关:下一拍开;
- 灯原来开:下一拍关。
电路必须记住“灯当前开还是关”,因此至少需要两个状态 OFF
与 ON。若输出灯光直接由状态决定,则
OFF + press=0 → OFF
OFF + press=1 → ON
ON + press=0 → ON
ON + press=1 → OFF
例题 1:从问题中识别状态
一个控制器接收同步输入 coin。第一次收到硬币后进入“已有 1
枚”,第二次收到后产生一次 vend
并重新开始。一次只考虑一枚硬币。
为了判断下一枚硬币是否应触发
vend,控制器只需记住此前是否已有一枚,因此两个状态足够:
EMPTY:尚未收到第一枚;ONE:已经收到一枚,等待第二枚。
不需要为“本拍 coin=0”单独建立状态,因为它是输入条件,不是必须跨时钟保存的历史。
变式: 若商品需要 3 枚硬币,至少要区分“0 枚、1 枚、2 枚”三个累计状态。
6. FSM 的三块硬件
同步 FSM 通常分成三块:
- 状态寄存器: 在有效边沿保存当前状态 \(Q\);
- 下一状态逻辑: 根据当前状态和输入计算 \(Q^+=F(Q,X)\);
- 输出逻辑: 根据状态,或根据状态与输入,计算输出 \(Y\)。
图 16-1 中橙色模块是唯一保存历史的部分。两个蓝色模块都是组合逻辑:输入变化后经过传播延迟产生结果,但只在时钟边沿由状态寄存器保存下一状态。
图 16-1 状态寄存器保存历史,下一状态逻辑决定转移,输出逻辑产生控制信号
这是一种 RTL/门级功能结构。具体逻辑门取决于状态编码、化简和综合;具体时间是否满足要求,仍按第 14 章检查寄存器反馈路径。
7. 状态图怎样阅读
状态图(state diagram)用圆或圆角框表示状态,用带方向的箭头表示转移。每条箭头都必须有明确条件;对某个状态,所有可能输入组合都应有去向。
本章采用以下约定:
- Moore 图的状态框写作“状态名 / 状态输出”;
- Moore 图的箭头只标输入条件;
- Mealy 图的状态框写状态名;
- Mealy 图的箭头写作“输入条件 / 转移输出”;
- 未写明的自环不能自动假定为保持,必须明确画出或在表中定义。
图 16-2 使用按钮灯控制器展示这些符号。press=0
时自环保持;press=1 时在两个状态之间切换。
图 16-2 状态框表示已保存历史,箭头条件决定下一个有效边沿后的状态
箭头不是输入一变化就立即跳转。同步 FSM 在有效时钟边沿读取输入和当前状态,随后状态寄存器经过 \(t_{cq}\) 更新。
8. 状态表:把图变成可逐行检查的规格
状态表(state table)为每个“当前状态 + 输入组合”列出下一状态和输出。按钮灯的 Moore 状态表为:
| 当前状态 | press |
下一状态 | lamp |
|---|---|---|---|
OFF |
0 | OFF |
0 |
OFF |
1 | ON |
0 |
ON |
0 | ON |
1 |
ON |
1 | OFF |
1 |
输出 lamp 由当前状态决定,因此在 press
的两行中相同。状态表比图更适合检查是否遗漏输入组合,也便于后续编码和逻辑推导。
9. Moore 状态机
Moore 状态机的输出只取决于当前状态:
\[ Q^+=F(Q,X), \]
\[ Y=G(Q). \]
若状态寄存器只在时钟边沿更新,Moore 输出通常随状态在边沿后变化,不会直接响应边沿之间的输入变化。这使控制输出的时间边界清楚。
“只由状态决定”不等于输出绝对无毛刺。若状态使用多 bit 编码,多个状态位经过 \(t_{cq}\) 后到达输出译码逻辑的时间不同,组合译码仍可能短暂毛刺。需要严格无毛刺的接口可以再把输出寄存。
10. Mealy 状态机
Mealy 状态机的输出同时取决于当前状态和当前输入:
\[ Q^+=F(Q,X), \]
\[ Y=G(Q,X). \]
输入在边沿之间改变时,Mealy 输出可在组合传播延迟后改变,不必等待状态寄存器更新。因此它往往能用较少状态、更快响应输入,但输出会继承输入毛刺和异步变化风险。
同步设计中,进入 Mealy 输出逻辑的输入应满足接口与同步要求。若输出用于重要控制,常对它再次寄存,或改用 Moore 表达换取清楚的周期边界。
11. Moore 与 Mealy 的差别
图 16-3 对同一个“检测到条件后给出完成信号”的任务进行对比。Moore 输出写在状态中,进入完成状态后为 1;Mealy 输出写在转移上,输入条件满足时可立即为 1。
图 16-3 Moore 输出随状态更新,Mealy 输出可直接响应当前输入,因此状态数和输出时刻可能不同
| 比较项 | Moore | Mealy |
|---|---|---|
| 输出关系 | \(Y=G(Q)\) | \(Y=G(Q,X)\) |
| 输入到输出路径 | 必须先影响状态,或不直接存在 | 存在组合输入到输出路径 |
| 响应时刻 | 通常在状态边沿后 | 可在边沿之间响应 |
| 状态数 | 有时较多 | 有时较少 |
| 毛刺关注 | 状态译码毛刺 | 状态译码及输入毛刺 |
例题 2:判断 Moore 还是 Mealy
设计 A 的 alarm 只在状态 ERROR 时为 1;设计
B 的 alarm 在状态 CHECK 且输入
bad=1 时立即为 1。
- A:\(alarm=G(Q)\),是 Moore 输出;
- B:\(alarm=G(Q,bad)\),是 Mealy 输出。
若 bad 在边沿之间出现窄毛刺,设计 B 的
alarm 也可能出现组合毛刺;设计 A 只有在状态寄存器进入
ERROR 后才持续拉高。
变式: 把 B 的 alarm
再经过一个输出寄存器,会使接口按边沿更新,但也增加一拍或相应采样延迟。
12. 贯穿例子:检测可重叠序列 101
现在设计一个同步串行序列检测器。输入 \(X\) 每个时钟周期提供 1
bit。每当最近收到的三位形成 101,输出 \(Z\) 产生一次有效指示。允许重叠,例如输入
10101 应检测两次。
本节先设计 Mealy FSM,因为读到最后一个 1
时即可在当前状态与输入组合上产生检测输出。
13. 第一步:找出必须记住的历史
为了判断下一位能否完成
101,不需要记住全部输入历史,只需记住当前历史中、同时又是目标序列前缀的最长后缀:
A:当前没有有用后缀;B:最近的有效后缀是1;C:最近的有效后缀是10。
状态名本身没有逻辑电压含义。它们先表达行为,稍后才编码成位模式。
14. 第二步:逐状态决定所有转移
状态 A:没有有用后缀
- 输入 0:仍没有目标前缀,留在 A;
- 输入 1:得到前缀
1,进入 B。
状态 B:已经看到后缀 1
- 输入 0:得到后缀
10,进入 C; - 输入 1:最近一位仍可作为新前缀
1,留在 B。
状态 C:已经看到后缀 10
- 输入 0:得到
100,没有有用后缀,回 A; - 输入 1:形成
101,令 \(Z=1\);最后这个 1 同时是下一次匹配的开头,所以进入 B,而不是回 A。
图 16-4 的箭头标签采用 X/Z。只有 C→B 且
\(X=1\) 的转移输出 1。
图 16-4 三个状态分别保存无前缀、后缀 1 和后缀 10;检测后回到 B 以保留重叠可能
15. 第三步:列出完整状态表
| 当前状态 | \(X\) | 下一状态 | \(Z\) |
|---|---|---|---|
| A | 0 | A | 0 |
| A | 1 | B | 0 |
| B | 0 | C | 0 |
| B | 1 | B | 0 |
| C | 0 | A | 0 |
| C | 1 | B | 1 |
表中共有 \(3\times2=6\) 行,覆盖了全部合法状态和单比特输入组合。若缺一行,硬件在对应条件下的行为就没有完整定义。
例题 3:逐拍验证重叠检测
从 A 开始,输入序列为 1、0、1、0、1:
| 边沿前状态 | 本拍 \(X\) | \(Z\) | 边沿后状态 |
|---|---|---|---|
| A | 1 | 0 | B |
| B | 0 | 0 | C |
| C | 1 | 1 | B |
| B | 0 | 0 | C |
| C | 1 | 1 | B |
第 3、5 个输入位分别完成一次 101。第一次检测后进入
B,使第 3 位的 1 同时成为第二次序列的开头。
变式: 若检测后错误地回到 A,输入 10101
只能检测到第一次。
16. 第四步:选择状态编码
三种常见编码思路是:
二进制编码
\(N\) 个状态至少需要
\[ K=\lceil\log_2N\rceil \]
个状态位。三个状态可编码为
A=00,B=01,C=10
位模式 11
未使用。二进制编码节省触发器,但下一状态和输出逻辑可能较复杂。
独热编码
每个状态使用一位,合法状态中恰有一位为 1:
A=001,B=010,C=100
它需要 3 个触发器,但状态判断通常直接、组合逻辑较浅。FPGA 或速度优先场景经常采用;ASIC 中是否合适取决于单元、功耗与时序目标。
格雷式编码
尽量让频繁相邻转移只改变一位,可减少某些状态译码瞬态。但任意状态图未必能让所有边都满足单比特变化。
图 16-5 对三个状态的二进制和独热编码进行并列比较。编码改变硬件实现,不改变状态图规定的行为。
图 16-5 相同的 A、B、C 行为可以用不同位模式保存,触发器数量与组合逻辑复杂度随之变化
例题 4:计算状态位数
一个 FSM 有 7 个合法状态。
- 二进制编码至少需要 \(\lceil\log_2 7\rceil=3\) bit,并留下 1 个未使用位模式;
- 独热编码需要 7 bit,合法状态中每次仅一位为 1。
不能只凭触发器数量判断哪个实现更快。独热编码减少译码复杂度,却增加寄存器、时钟负载和状态位布线。
变式: 9 个状态的二进制编码至少需要 4 bit,独热编码需要 9 bit。
17. 第五步:处理非法状态
对 A=00、B=01、C=10,位模式 11
是非法状态(illegal
state),也称未使用状态。真实电路可能因上电、复位问题、软错误或时序异常进入该位模式。
本例规定:无论 \(X\) 为 0 还是
1,只要当前状态为 11,下一状态都回到 A=00,且
\(Z=0\)。这样模块最多经过一个有效边沿回到合法状态。
“非法状态恢复”不等于证明系统永远安全。某些应用需要进入专门的故障状态、保留错误标志或执行受控停机。基础设计至少要让每个物理状态都有定义。
18. 第六步:由状态表得到逻辑方程
采用二进制编码 A=00、B=01、C=10,当前状态为 \(Q_1Q_0\),下一状态寄存器 D 输入为 \(D_1D_0\)。加入非法状态 11→00
后:
| \(Q_1Q_0\) | \(X\) | \(D_1D_0\) | \(Z\) |
|---|---|---|---|
| 00 | 0 | 00 | 0 |
| 00 | 1 | 01 | 0 |
| 01 | 0 | 10 | 0 |
| 01 | 1 | 01 | 0 |
| 10 | 0 | 00 | 0 |
| 10 | 1 | 01 | 1 |
| 11 | 0 | 00 | 0 |
| 11 | 1 | 00 | 0 |
从输出为 1 的行读取:
\[ Z=Q_1\overline{Q_0}X. \]
\(D_1=1\) 只出现在当前
B=01 且 \(X=0\):
\[ D_1=\overline{Q_1}Q_0\overline{X}. \]
\(D_0=1\) 出现在所有合法状态且 \(X=1\):
\[ D_0=X\cdot\overline{Q_1Q_0}. \]
这里 \(\overline{Q_1Q_0}\) 表示 NAND 条件:只在 \(Q_1Q_0=11\) 时为 0。三个方程与完整 8 行表一一对应。
例题 5:验证一个编码状态
当前状态为 C=10,输入 \(X=1\):
\[ D_1=\overline1\cdot0\cdot\overline1=0, \]
\[ D_0=1\cdot\overline{1\cdot0}=1, \]
\[ Z=1\cdot\overline0\cdot1=1. \]
因此下一状态 \(D_1D_0=01\),即
B,同时检测输出为 1,与状态图 C --1/1→ B 一致。
变式: 当前非法状态 11 且 \(X=1\) 时,\(D_1D_0=00\)、\(Z=0\),下一边沿恢复到 A。
19. Mealy 输出究竟在哪个时刻有效
在状态 C 期间,\(Z=Q_1\overline{Q_0}X\)。若 \(X\) 在两个边沿之间由 0 变为 1,\(Z\) 会在组合传播延迟后变为 1。若 \(X\) 又短暂回到 0,\(Z\) 也会跟随产生脉冲。
因此接口规格必须说明:
- \(X\) 是否已经与本时钟同步;
- 下游是在时钟边沿采样 \(Z\),还是把 \(Z\) 当作异步控制;
- 输出需要组合快速响应,还是必须整周期稳定;
- 是否需要把 \(Z\) 再寄存。
图 16-6 比较组合 Mealy 输出和寄存输出。前者能在边沿前响应输入,后者只在边沿后更新,代价是延迟到明确的时钟边界。
图 16-6 组合 Mealy 输出可能跟随输入毛刺,寄存输出把接口变化限制到有效边沿之后
20. 把 Mealy 101 检测器改成 Moore
Moore 输出只能由状态决定,因此需要增加一个“已经检测到 101”的状态 D,并令该状态输出 \(Z=1\):
- A:无有用后缀,\(Z=0\);
- B:后缀 1,\(Z=0\);
- C:后缀 10,\(Z=0\);
- D:刚检测到 101,\(Z=1\)。
从 C 收到 1 后进入 D,状态寄存器更新后 \(Z\) 才为 1。为了允许重叠,D 收到 0 时进入 C,收到 1 时进入 B,因为已经检测序列的最后一位仍是前缀 1。
Moore 版本通常多一个状态,输出周期边界更清楚;Mealy 版本状态更少,输出可在当前输入到来后较早响应。二者都能实现正确检测,区别在接口时间语义。
21. 完整设计流程
面对文字规格时,按下面顺序工作:
- 定义输入输出。 写清有效电平、同步关系和每个输出的周期语义;
- 找出必须保存的历史。 只保留影响未来判断的信息;
- 给状态命名并写含义。 名称描述行为,不先绑定编码;
- 逐状态枚举所有输入。 对每种条件决定下一状态和输出;
- 画状态图并列状态表。 两种表示互相核对;
- 决定 Moore 或 Mealy。 根据响应速度和输出稳定性选择;
- 选择状态编码。 比较触发器数量、组合逻辑和目标平台;
- 定义复位与非法状态。 复位进入已知状态,所有物理编码都有去向;
- 推导或综合逻辑。 得到状态寄存器 D 输入与输出逻辑;
- 逐拍验证。 覆盖正常转移、自环、分支、复位、连续事件和非法恢复;
- 检查时序与 CDC。 分析状态反馈关键路径,先同步异步输入;
- 检查输出接口。 确认组合毛刺、脉冲宽度和下游采样方式。
22. 三状态任务控制器
例题 6:从规格到逐拍检查
设计一个同步控制器:start=1
时从空闲开始任务;任务执行状态中等待同步输入
done=1;完成后输出 finish=1
一个完整周期,再回空闲。执行期间再次出现 start 忽略。
定义状态
IDLE:等待启动;RUN:任务进行中;FINISH:完成指示周期。
采用 Moore 输出:仅 FINISH 状态令
finish=1。
状态转移
IDLE: start=0 → IDLE,start=1 → RUN
RUN: done=0 → RUN, done=1 → FINISH
FINISH: 任意输入 → IDLE
复位进入 IDLE。RUN 中 start
不参与转移,符合“再次启动忽略”的规格。FINISH
无条件维持一个周期,然后回到 IDLE。
逐拍检查
从 IDLE 开始,若连续边沿的 (start,done) 为
(1,0)、(0,0)、(1,1)、(0,0):
IDLE → RUN → RUN → FINISH → IDLE
finish: 0 0 0 1 0
第三拍中即使 start=1,当前在 RUN,只按
done=1 进入 FINISH。
变式:
若希望任务完成的同一拍立即产生组合完成指示,可采用 Mealy 条件
RUN & done,但必须重新规定输出脉宽与毛刺要求。
23. 常见误区与反例
误区 1:每个输入组合都要建立一个状态
输入是当前条件,状态是必须跨周期保存的历史。只有影响未来行为的信息才需要成为状态。
误区 2:状态箭头表示输入一变化就立即跳转
同步 FSM 在有效边沿更新状态。输入变化先改变下一状态组合逻辑,真正状态转移发生在边沿后。
误区 3:没有画出的条件默认保持
未定义条件会造成规格缺口。每个状态的全部输入组合都应有明确去向。
误区 4:Moore 输出一定没有毛刺
多 bit 状态译码可能因状态位到达时间不同而毛刺。寄存输出提供更明确的无毛刺边界。
误区 5:Mealy 输出只会在时钟边沿变化
Mealy 输出存在输入到输出的组合路径,可以在边沿之间变化。
误区 6:状态名称就是硬件编码
IDLE、RUN
是行为名称。综合前还需选择二进制、独热或其他编码。
误区 7:未使用编码永远不会出现
物理寄存器能够保存全部位模式。复位、软错误或时序问题可能进入未使用编码,必须定义行为。
误区 8:异步输入可以直接接下一状态逻辑
异步输入靠近采样边沿可能使状态寄存器亚稳,并可能让不同逻辑分支对同一事件产生不一致判断。先按第 15 章完成同步或 CDC 协议。
误区 9:状态越少,设计一定越好
状态合并可能增加组合逻辑和输出条件复杂度。状态数量、编码、时序、面积与可验证性需要共同权衡。
24. 工程中的实际意义
FSM 是数字系统控制器的基本表达方式,常用于:
- 通信协议握手与帧控制;
- 存储器读写时序;
- 算法步骤调度;
- 电源、复位和启动流程;
- 总线仲裁与资源管理;
- 数据通路的操作选择和寄存器使能;
- 错误检测、超时和恢复控制。
从硬件实现看,FSM 的状态寄存器形成时序边界,下一状态逻辑和输出逻辑形成组合路径。状态编码会改变触发器数量、译码级数、开关活动和布线。综合工具可以重新编码状态,但设计者仍要提供完整、无歧义、可恢复的行为规格。
从验证角度看,状态图提供了天然的覆盖清单:每个状态是否到达、每条转移是否触发、非法状态是否恢复、输出是否只在规定条件有效。第 19、20 章会把这些检查写成 RTL、测试平台和断言。
25. 本章知识链
必须保存的历史 → 定义状态
↓
状态图 ↔ 状态表
↓
选择输出模型
├─ Moore:Y = G(Q)
└─ Mealy:Y = G(Q,X)
↓
选择状态编码 → 二进制 / 独热 / 其他
↓
完整定义复位、非法状态、下一状态和输出
↓
状态寄存器 + 下一状态逻辑 + 输出逻辑
↓
逐拍验证 + 时序检查 + CDC 检查
↓
模块三完成:进入数据通路与控制器
26. 本章小结
- FSM 用有限个状态保存影响未来行为的必要历史。
- 同步 FSM 由状态寄存器、下一状态逻辑和输出逻辑构成。
- 状态图适合观察转移结构,状态表适合检查全部状态—输入组合。
- Moore 输出满足 \(Y=G(Q)\),通常随状态边沿更新。
- Mealy 输出满足 \(Y=G(Q,X)\),可以在边沿之间直接响应输入。
- 状态名称描述行为,状态编码决定触发器保存的位模式。
- 二进制编码节省触发器,独热编码常使译码更直接;选择依赖实现目标。
- 所有物理状态编码都要有行为定义,未使用状态应恢复或进入规定安全状态。
- 可重叠
101检测器只需记住无前缀、后缀 1、后缀 10 三类历史。 - 检测后保留最后一个 1,才能正确识别重叠序列
10101。 - 异步输入进入 FSM 前必须按信号语义完成同步或 CDC 处理。
- 完整 FSM 设计还要检查状态反馈时序、组合输出毛刺、复位和逐拍覆盖。
27. 练习
基础题
- 用一句话说明 FSM 中“状态”的作用。
- 同步 FSM 的三块基本硬件是什么?
- 状态图中的箭头在什么时刻真正引起状态寄存器更新?
- Moore 与 Mealy 输出方程分别是什么?
- 为什么状态表应覆盖每个状态的全部输入组合?
- 5 个状态采用二进制编码和独热编码分别至少需要多少个触发器?
- 什么是非法状态?为什么要定义恢复行为?
分析与设计题
- 按钮灯控制器初始
OFF,连续四拍press=1、0、1、1。写出每拍后的状态和lamp。 - 两枚硬币售货控制器初始
EMPTY,连续输入coin=1、0、1。采用 Moore 状态表示累计硬币时,写出状态序列;若在第二枚到来时用 Mealy 输出,哪一拍vend=1? - 判断下列输出属于 Moore 还是
Mealy:
busy=(state==RUN);accept=(state==IDLE)&req。 - 对
101Mealy 检测器,输入1101011,写出每拍状态和 \(Z\)。 - 为什么状态 B 收到 \(X=1\) 时留在 B,而不是回到 A?
- 为什么状态 C 收到 \(X=1\) 并检测成功后进入 B,而不是 A?
- 使用
A=00、B=01、C=10,验证当前 B、\(X=0\) 时方程给出下一状态 C、\(Z=0\)。 - 当前非法状态
11,分别取 \(X=0\) 和 \(X=1\),本章方程给出什么下一状态与输出? - 一个 10 状态 FSM 用二进制编码和独热编码分别需要多少个状态位?二进制编码有多少个未使用位模式?
- Moore
101检测器为何需要额外的检测状态 D?D 状态收到 0 和 1 时分别去哪里? - 三状态任务控制器从
IDLE开始,连续输入(start,done)为(0,0)、(1,0)、(1,0)、(0,1)、(1,0)。写出每拍后的状态和finish。
综合题
- 设计一个两状态“允许/禁止”控制器:复位后禁止;同步输入
enable令其进入允许,disable令其进入禁止;若两者同时为 1,规定禁止优先。写出状态表。 - 设计一个检测连续两个 1 的 Mealy
FSM,允许重叠。定义状态、画出文字版转移并说明输入
111会检测几次。 - 某 Mealy FSM 的输入来自芯片外部按键,输出直接控制写使能。指出至少三个风险或缺口,并给出改进方向。
- 比较 8 状态二进制编码与独热编码在触发器数量、状态译码、时钟负载和非法编码数量上的差异。
- 为一个自选的三状态控制器写出:状态含义、全部转移、输出类型、复位状态、编码和非法状态恢复。再给出至少五个逐拍测试场景。
28. 练习答案
展开第 16 章练习答案
题 1
状态保存为了正确处理未来输入而必须保留的过去信息。
题 2
状态寄存器、下一状态组合逻辑和输出逻辑。
题 3
输入和当前状态先使下一状态逻辑形成结果,状态寄存器在有效时钟边沿采样该结果,并在边沿后更新。
题 4
Moore:\(Y=G(Q)\);Mealy:\(Y=G(Q,X)\)。
题 5
完整覆盖能保证硬件在每个可能条件下都有确定下一状态和输出,也便于发现遗漏、自锁或意外转移。
题 6
二进制编码至少需要 \(\lceil\log_2 5\rceil=3\) 个触发器;独热编码需要 5 个触发器。
题 7
非法状态是状态寄存器能够保存、但未分配正常行为含义的位模式。复位异常、软错误或时序问题可能使电路进入它,因此要规定恢复或安全处理。
题 8
初始 OFF,每个 press=1 切换:
| 拍后 | 状态 | lamp |
|---|---|---|
| 1 | ON |
1 |
| 2 | ON |
1 |
| 3 | OFF |
0 |
| 4 | ON |
1 |
题 9
状态序列为
EMPTY→ONE→ONE→EMPTY。第三拍的输入是第二枚硬币;若使用 Mealy
条件 state=ONE & coin=1,第三拍处理该输入时
vend=1。
题 10
busy 只依赖状态,是 Moore 输出;accept
同时依赖状态和当前 req,是 Mealy 输出。
题 11
从 A 开始:
| 输入位 | 边沿后状态 | \(Z\) |
|---|---|---|
| 1 | B | 0 |
| 1 | B | 0 |
| 0 | C | 0 |
| 1 | B | 1 |
| 0 | C | 0 |
| 1 | B | 1 |
| 1 | B | 0 |
检测发生在第 4、6 位。
题 12
当前已有后缀 1,再收到 1 后,最新一位仍然可以作为目标序列
101 的第一个 1,因此保留状态 B。
题 13
完成 101 后,最后收到的 1 同时是下一次匹配的开头。进入 B
能保留该前缀,支持重叠序列。
题 14
\(Q_1Q_0=01\)、\(X=0\):
\[ D_1=\overline0\cdot1\cdot\overline0=1, \]
\[ D_0=0\cdot\overline{0\cdot1}=0, \]
\[ Z=0\cdot\overline1\cdot0=0. \]
所以下一状态为 10,即 C,输出为 0。
题 15
当前 \(Q_1Q_0=11\) 时,\(D_1=0\),且 \(D_0=X\cdot\overline{1\cdot1}=0\);\(Z=1\cdot\overline1\cdot
X=0\)。两种输入都得到下一状态 00、输出 0。
题 16
10 状态二进制编码需要 \(\lceil\log_2 10\rceil=4\) bit,共有 \(16-10=6\) 个未使用位模式;独热编码需要 10 bit。
题 17
Moore 输出不能直接由当前输入决定,所以需要状态 D 保存“已经检测到 101”,并在 D 中令 \(Z=1\)。为保留重叠后缀,D 收到 0 进入 C,收到 1 进入 B。
题 18
按每个边沿后的 Moore 状态与输出:
| 拍后 | 状态 | finish |
|---|---|---|
| 1 | IDLE |
0 |
| 2 | RUN |
0 |
| 3 | RUN |
0 |
| 4 | FINISH |
1 |
| 5 | IDLE |
0 |
在 RUN 状态中,第三拍的 start=1
被忽略。
题 19
设状态 DISABLED、ENABLED,输出
allow 分别为 0、1。禁止优先的状态表:
| 当前状态 | enable |
disable |
下一状态 |
|---|---|---|---|
| 任意 | 任意 | 1 | DISABLED |
DISABLED |
0 | 0 | DISABLED |
DISABLED |
1 | 0 | ENABLED |
ENABLED |
0 | 0 | ENABLED |
ENABLED |
1 | 0 | ENABLED |
复位进入 DISABLED。allow 是 Moore
输出。
题 20
定义 A=“上一位不是 1 或尚无输入”,B=“上一位是 1”。转移:A 收到 0 留
A,收到 1 进 B;B 收到 0 回 A,收到 1 时输出 1 并留 B。输入
111 在第 2、3 位各完成一次
11,共检测两次。
题 21
至少存在三类问题:按键是异步输入,可能使状态寄存器亚稳;机械按键会抖动,可能被识别为多次事件;Mealy 写使能存在输入到输出组合路径,可能出现窄脉冲。改进方向是先进行输入同步和消抖,把一次按键变成一个同步事件,再将写使能寄存或改为周期边界明确的 Moore 控制。
题 22
| 项目 | 8 状态二进制 | 8 状态独热 |
|---|---|---|
| 状态触发器 | 3 | 8 |
| 状态译码 | 常需比较多位 | 单个状态位可直接使用 |
| 时钟负载 | 较小 | 较大 |
| 未使用位模式 | 0(若恰用满 8 个) | \(2^8-8=248\) 个非独热位模式 |
独热实现通常只把恰有一位为 1 的 8 个模式视为合法状态,因此需要明确全零、多热等异常状态的处理。
题 23
答案随设计而变化。一个合格答案应包含:三个互不含糊且必要的状态;每个状态对全部输入组合的转移;Moore 或 Mealy 输出及其时刻;确定复位状态;完整编码;所有未使用编码的恢复规则。测试至少覆盖复位、每个状态自环、每条跨状态转移、优先级冲突和非法状态恢复。
29. 自测清单
若第 1~3
项不稳定,请先用普通中文写出“当前记住了什么”和“每种输入后记住什么”,再画箭头。若第
4、11 项不稳定,请检查输出方程中是否直接出现输入 \(X\)。若第 5、8 项不稳定,请分别测试
10101 和非法编码 11。
30. 下一阶段衔接
第 11~16 章已经完成模块三“时序逻辑”:从反馈与锁存器开始,经过触发器、寄存器、计数器、时序约束、亚稳态与同步器,最终形成 FSM 控制器。下一批应先完成“阶段复习三”,设计一个带暂停、清零和完成指示的定时控制器;随后进入第 17 章《数据通路与控制器》,学习 FSM 怎样驱动寄存器、MUX、ALU 和总线完成多周期操作。