三段式状态机写法:从理论到实战
状态机的写法,说白了就三种:一段式、两段式、三段式。前面我们聊过一段式,今天重点说说三段式。我个人习惯用三段式,为什么?因为它结构清晰,代码可读性强,而且不容易出错。
先看一个简单的例子:一个四状态的状态机,状态分别是 IDLE、S1、S2、S3。我们用三段式来实现它。
第一段:时序逻辑描述状态转移
这一段负责把当前状态更新为次态。说白了,就是每个时钟沿来的时候,把 next_state 赋值给 current_state。
// 第一段:状态转移
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
end
嗯,这里要注意:复位信号我用的是异步复位,低电平有效。这是我在项目中常用的写法,因为很多 FPGA 芯片的复位引脚默认就是低电平复位。
第二段:组合逻辑描述次态
这一段根据当前状态和输入信号,计算出下一个状态是什么。它是组合逻辑,没有时钟沿的概念。
// 第二段:次态逻辑
always @(*) begin
next_state = current_state;
case (current_state)
IDLE: if (start) next_state = S1;
S1: if (done) next_state = S2;
S2: if (ready) next_state = S3;
S3: next_state = IDLE;
default: next_state = IDLE;
endcase
end
这里有个小技巧:我习惯在 case 前面先给 next_state 赋默认值,这样能避免产生锁存器。你想想看,如果某个分支没覆盖到,next_state 会保持原来的值,组合逻辑里保持值就意味着锁存器,这是个大坑。
避坑指南:我曾经在项目里漏写了一个状态分支,结果综合出来一堆锁存器,时序怎么都跑不过。后来查了两天才发现是这里的问题。所以,组合逻辑里一定要给所有输出赋默认值。
第三段:组合逻辑描述输出
这一段根据当前状态(或者次态)产生输出信号。输出可以是 Moore 型(只与当前状态有关),也可以是 Mealy 型(与当前状态和输入都有关)。
// 第三段:输出逻辑(Moore 型)
always @(*) begin
case (current_state)
IDLE: out = 3'b001;
S1: out = 3'b010;
S2: out = 3'b100;
S3: out = 3'b111;
default: out = 3'b000;
endcase
end
如果是 Mealy 型输出,那就把输入信号也加进来判断。比如:
// 第三段:输出逻辑(Mealy 型)
always @(*) begin
case (current_state)
IDLE: if (start) out = 3'b001; else out = 3'b000;
S1: if (done) out = 3'b010; else out = 3'b000;
S2: if (ready) out = 3'b100; else out = 3'b000;
S3: out = 3'b111;
default: out = 3'b000;
endcase
end
三段式与两段式的对比
两段式就是把第二段和第三段合并在一起,用组合逻辑同时计算次态和输出。看起来代码少了,但实际用起来问题不少。
| 对比项 | 两段式 | 三段式 |
|---|---|---|
| 代码结构 | 两个 always 块 | 三个 always 块 |
| 可读性 | 一般,次态和输出混在一起 | 好,各司其职 |
| 输出时序 | 组合逻辑输出,容易有毛刺 | 可以加寄存器输出,干净 |
| 修改难度 | 改输出可能影响次态逻辑 | 改输出不影响状态转移 |
| 综合结果 | 可能产生不必要的锁存器 | 结构清晰,综合结果好 |
我个人强烈推荐用三段式。为什么?因为两段式里,输出和次态逻辑混在一起,你改输出的时候一不小心就把次态逻辑改坏了。我在项目中遇到过这种情况:改了一个输出信号,结果状态机跑飞了,查了半天才发现是次态逻辑被连带改了。
核心要点:三段式的精髓在于「分离」。状态转移、次态计算、输出产生,三者各管各的。这样代码好读、好改、好维护。
知识体系结构图
下面这张图展示了我对三段式状态机的理解框架:
小提示:如果你刚开始学状态机,建议先用三段式把逻辑理清楚。等熟练了,再根据实际需求选择其他写法。但说实话,我做了这么多年项目,大部分场景还是用三段式,因为它最稳。
最后说一句:状态机的写法没有的对错,但三段式在可读性、可维护性、综合质量上都有明显优势。尤其是团队协作的项目里,三段式能让别人一眼看懂你的设计意图。嗯,这就是我推荐它的原因。
可可精品资料库