1. 状态机基础回顾:Mealy与Moore状态机区别、状态编码方式、三段式写法规范
状态机这东西,说白了就是数字电路里的"大脑"。它决定了你的设计在什么时候该做什么事。我做了这么多年验证,见过太多因为状态机写崩了导致芯片功能异常的案例。今天咱们就把基础打扎实。
1.1 Mealy与Moore状态机:到底差在哪?
先问个问题:你写的状态机,输出是跟当前状态有关,还是跟输入也有关?这就是Mealy和Moore的核心区别。
Moore状态机:输出只取决于当前状态。说白了就是——你处在哪个状态,输出就是固定的。比如你处在S1状态,输出就是1;到了S2状态,输出自动变成0。输入信号只影响状态怎么跳,不影响输出本身。
Mealy状态机:输出不仅跟当前状态有关,还跟输入有关。这意味着同样的状态,输入不同,输出可能完全不同。我有个项目是做串行数据检测器,用Mealy机就比Moore机少用一个状态,面积省了不少。
嗯,这里要注意:Mealy机的输出是组合逻辑产生的,容易出毛刺。我在项目中吃过这个亏——仿真时波形看着没问题,上板子就抓瞎了。后来老老实实在输出端加了寄存器打一拍,问题解决。
| 对比项 | Moore机 | Mealy机 |
|---|---|---|
| 输出依赖 | 仅当前状态 | 当前状态 + 输入 |
| 状态数量 | 通常较多 | 通常较少 |
| 输出时序 | 同步,无毛刺 | 组合逻辑,可能有毛刺 |
| 响应速度 | 慢一拍 | 快,输入变化立即响应 |
| 典型应用 | 控制逻辑、协议解析 | 高速数据通路、检测器 |
1.2 状态编码方式:二进制、格雷码、独热码
状态编码这事儿,很多人觉得随便选就行。其实不然。编码方式直接影响面积、功耗、还有时序收敛。我见过一个项目,就因为用了独热码,状态数一多,综合出来的面积直接爆炸。
二进制编码:最直观,用n个寄存器表示2^n个状态。比如状态0=00,状态1=01,状态2=10,状态3=11。优点是寄存器用得少,缺点是状态跳变时可能多位同时变化,容易产生毛刺。
格雷码:相邻状态只有1位变化。比如00→01→11→10。你想想看,如果状态机在高速时钟下连续跳转,格雷码能大大降低动态功耗。我在做低功耗项目时特别喜欢用格雷码,尤其是状态机跑在几百兆赫兹的时候,省电效果肉眼可见。
独热码:每个状态对应一个寄存器,只有1位为1。比如状态0=0001,状态1=0010,状态2=0100,状态3=1000。优点是译码逻辑简单,速度快,适合FPGA。缺点是状态多了寄存器消耗大。
| 编码方式 | 寄存器数 | 组合逻辑 | 功耗 | 速度 | 适用场景 |
|---|---|---|---|---|---|
| 二进制 | 最少 | 复杂 | 中等 | 中等 | 状态数多、面积敏感 |
| 格雷码 | 最少 | 复杂 | 低 | 中等 | 低功耗、连续跳转 |
| 独热码 | 最多 | 简单 | 高 | 快 | FPGA、状态数少 |
1.3 三段式写法规范
三段式状态机,我个人认为是Verilog里最优雅的写法之一。它把状态机的三个核心功能拆开写,调试时一眼就能看出问题在哪。
第一段:状态跳转(时序逻辑)
这段代码负责把次态更新为现态。说白了就是每个时钟沿把next_state赋给current_state。代码很简单,但千万别写错。
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
end
第二段:次态逻辑(组合逻辑)
这段是状态机的"大脑",根据当前状态和输入信号,决定下一个状态是什么。我习惯用case语句写,清晰明了。
always @(*) begin
next_state = current_state; // 默认保持
case (current_state)
IDLE: if (start) next_state = READ;
READ: if (done) next_state = DONE;
DONE: next_state = IDLE;
default: next_state = IDLE;
endcase
end
第三段:输出逻辑(组合或时序)
输出逻辑可以单独写一段。如果是Moore机,输出只跟current_state有关;如果是Mealy机,还要看输入。我个人建议输出用组合逻辑,然后在模块边界加寄存器打一拍,这样既快又干净。
always @(*) begin
case (current_state)
IDLE: data_out = 0;
READ: data_out = 1;
DONE: data_out = 0;
default: data_out = 0;
endcase
end
知识体系结构图
好了,状态机基础就聊到这儿。这些内容看着简单,但真到了项目里,每一步都有坑。记住:类型选对、编码选好、三段式写规范,你的状态机就成功了一大半。