HDLBits答案(21)_Verilog有限状态机(8)
Verilog有限状态机(8)
前言
今天我们来学习HDLBits状态机部分的最后一组题目!这组题目涵盖了几个经典应用:
- 简单序列检测状态机
- 独热编码逻辑推导
- 资源仲裁器状态机
- 复杂协议状态机
状态机是数字电路设计的灵魂,把这些题目都掌握了,以后遇到类似问题就能得心应手!
题库
Q2a: FSM - 简单序列检测

题目理解
这是一道经典的”看图写状态机”题目。给了状态转移图,我们只需要照着实现就行。
Solution:
1 | module top_module ( |
Q2b: One-hot FSM equations - 独热编码逻辑推导
题目理解
这道题中状态使用独热编码,我们需要推导出Y1和Y3的逻辑表达式。
独热编码的特点就是简单!每个状态对应一位,我们只需要看哪些状态会转移到目标状态就行。
Solution:
1 | module top_module ( |
Q2a: FSM - 资源仲裁器

题目理解
这道题是用状态机实现一个仲裁器。想象一下有三台设备都想用同一个资源:
r[1]、r[2]、r[3]分别表示三台设备的请求g[1]、g[2]、g[3]表示资源分配给了哪台设备- 优先级:设备1 > 设备2 > 设备3(数字越小优先级越高)
- 设备获得资源后,要等它释放(请求信号变低)才会重新仲裁
这就像三个人排队用打印机,优先级高的可以插队,但正在用的人要用完才会让出来。
Solution:
1 | module top_module ( |
设计要点
优先级判断很重要:在空闲状态A中,我们按优先级顺序判断:先看r1,再看r2,最后看r3。这样保证高优先级设备能先获得资源。
低电平复位:注意信号名resetn后缀_n表示低电平有效,所以复位条件是~resetn。
Q2b: Another FSM - 复杂协议状态机
这道题比较复杂,让我们仔细分析一下要求:
题目理解
状态机有2个输入(x和y),2个输出(f和g),工作流程如下:
- 复位后:第一个周期输出
f=1(只持续1个周期) - 然后开始检测x序列:寻找连续的”1-0-1”序列
- 找到序列后:
g=1,此时看输入y:- 如果接下来2个周期内y有任意一个为1:
g永远保持1 - 如果接下来2个周期内y全是0:
g永远保持0
- 如果接下来2个周期内y有任意一个为1:
这就像一个闯关游戏:
- 第一关:复位后输出一个f=1的脉冲
- 第二关:找到”1-0-1”的序列
- 第三关:看y的表现,决定g是永远1还是永远0
Solution:
1 | module top_module ( |
设计心得
这道题的关键是状态规划!在动手写代码前,先画好状态转移图,想好每个状态的功能,能大大减少错误。

入门者避坑指南
在做最后这组题目时,初学者最容易犯以下错误:
错误1:复位信号的电平搞反
错误表现:1
2
3
4
5
6// resetn是低电平有效,却用posedge和高电平判断
always @(posedge clk or posedge resetn) begin
if (resetn) begin
current_state <= A;
end
end
错误原因:
- 信号名后缀
_n通常表示低电平有效(negative) - 同步复位的话,只在时钟边沿判断,不用放敏感信号列表
正确做法:1
2
3
4
5
6
7
8// 同步低电平复位的正确写法
always @(posedge clk) begin
if (~resetn) begin
current_state <= A;
end else begin
current_state <= next_state;
end
end
错误2:仲裁器优先级搞反
错误表现:1
2
3
4
5
6// 优先级搞反了!先看r3再看r1
A: begin
if (r[3]) next_state = D;
else if (r[2]) next_state = C;
else if (r[1]) next_state = B; // 错了!r1应该优先级最高
end
错误原因:
- 没有仔细看题目描述
- 题目说:”设备1、2、3的优先级依次递减”
正确做法:1
2
3
4
5
6// 正确的优先级:r1 > r2 > r3
A: begin
if (r[1]) next_state = B; // 先看r1
else if (r[2]) next_state = C; // 再看r2
else if (r[3]) next_state = D; // 最后看r3
end
错误3:永久状态没有自环
错误表现:1
2
3ALL_ONE: begin
// 没有写next_state!
end
错误原因:
- 永久状态应该永远保持在自己这个状态
- 如果没有default分支,会生成锁存器
正确做法:1
2
3
4
5
6ALL_ONE: begin
next_state = ALL_ONE; // 自环
end
ALL_ZERO: begin
next_state = ALL_ZERO; // 自环
end
错误4:输出f的状态没有及时切换
错误表现:1
2// f输出多个周期
FOUT: next_state = FOUT; // 错了!f只应该输出1个周期
错误原因:
- 题目明确说”在下一个周期内将f输出为1”
- f只应该持续1个周期
正确做法:1
FOUT: next_state = S1; // 只待一个周期就走
错误5:g的输出漏掉S4和S5状态
错误表现:1
2// g只在ALL_ONE时输出,漏掉了S4和S5
assign g = (current_state == ALL_ONE);
错误原因:
- 题目说:”下一周期将g输出为1,在保持g为1时判断y的输入”
- 在S4和S5状态时,g也应该是1
正确做法:1
2// S4、S5、ALL_ONE时g都是1
assign g = (current_state == S4) | (current_state == S5) | (current_state == ALL_ONE);
小结
恭喜你!终于完成了HDLBits状态机部分的所有题目!
最后这组题目涵盖了状态机设计的几个典型场景:
基础序列检测:看图写状态机,三段式结构要熟练
独热编码逻辑推导:利用独热编码的特性,直接看对应位,逻辑更简单
资源仲裁器:优先级判断和状态保持,这在实际工程中很常用(比如总线仲裁、中断控制器)
复杂协议状态机:这道题比较综合,需要仔细规划每个状态,画状态转移图很重要!
作为一名通信IC设计师,笔者想说:状态机是数字电路设计中最重要的技能之一!从简单的接口协议(UART、SPI)到复杂的处理器控制器,都离不开状态机。
回顾整个状态机系列,我们学习了:
- 摩尔型 vs 米利型状态机
- 二进制编码 vs 独热编码
- 同步复位 vs 异步复位
- 三段式状态机结构
- 状态+计数器的设计方法
- 各种实际应用场景:协议解析、序列检测、仲裁器、补码计算…
多练习,多画状态转移图,慢慢你就能体会到状态机设计的乐趣了!
结语
HDLBits状态机这部分题目终于全部更新完了!笔者自己在做这些题目的过程中收获也非常大,很感谢HDLBits网站的作者。
状态机的设计没有绝对的对错,只有好不好。同样的功能,不同的人可能会画出不同的状态转移图。在画状态转移图时可以多留点时间,多想想有没有更简洁的方式,这是一个需要经验积累的过程。
如果代码哪里有误,欢迎大家指正!评论区也欢迎大家交流不同的解题思路。




