一、状态机基础回顾
状态机这东西,说白了就是数字电路里的「大脑」。我做了十几年RTL设计,可以负责任地告诉你——状态机写得好不好,直接决定了你芯片的成败。今天咱们就从最基础的东西聊起。
1.1 Moore机与Mealy机的区别
这两种状态机的区别,我当年刚入行时也搞混过。其实记住一句话就行:Moore机的输出只跟当前状态有关,Mealy机的输出还跟输入有关。
| 对比项 | Moore机 | Mealy机 |
|---|---|---|
| 输出依赖 | 仅当前状态 | 当前状态 + 输入 |
| 输出时序 | 比状态变化晚一个时钟 | 输入变化后立即响应 |
| 状态数量 | 通常较多 | 通常较少 |
| 抗毛刺能力 | 较强 | 较弱 |
我的经验之谈:做控制逻辑时,我偏爱Moore机。为什么?因为输出稳定,不容易出毛刺。但如果你对延迟敏感,比如高速数据通路,Mealy机反而更合适。
举个例子。你设计一个自动售货机,投入硬币后输出饮料。用Moore机的话,你得先进入一个「已投币」状态,下一个时钟才输出饮料。用Mealy机呢?投币瞬间就输出饮料,但万一输入有毛刺,饮料可能就白给了——嗯,这问题我在项目里真遇到过。
1.2 状态编码方式
编码方式选不对,后面优化起来可费劲了。我见过太多新手在这上面栽跟头。
二进制编码
最省触发器的方式。n个状态只需要log₂(n)个触发器。但问题是——状态跳转时多个比特同时变化,容易产生竞争冒险。
// 二进制编码示例
localparam IDLE = 2'b00;
localparam S1 = 2'b01;
localparam S2 = 2'b10;
localparam S3 = 2'b11;
格雷码编码
相邻状态只有1比特变化。我建议在跨时钟域场景下优先考虑它。为什么?因为亚稳态概率大大降低。
// 格雷码编码示例
localparam IDLE = 2'b00;
localparam S1 = 2'b01;
localparam S2 = 2'b11;
localparam S3 = 2'b10;
独热码编码
每个状态对应一个触发器,只有1位为1。面积大,但译码逻辑简单,速度最快。
// 独热码编码示例
localparam IDLE = 4'b0001;
localparam S1 = 4'b0010;
localparam S2 = 4'b0100;
localparam S3 = 4'b1000;
| 编码方式 | 触发器数 | 组合逻辑 | 速度 | 适用场景 |
|---|---|---|---|---|
| 二进制 | 最少 | 复杂 | 慢 | 状态数多、面积敏感 |
| 格雷码 | 较少 | 中等 | 中等 | 跨时钟域、低功耗 |
| 独热码 | 最多 | 简单 | 快 | 状态数少(<16)、高速 |
我曾经踩过的坑:有个项目用了16个状态的独热码,综合后面积爆炸。后来改成格雷码,面积直接砍了一半。所以别盲目追求独热码,状态数超过8个就得掂量掂量。
1.3 三段式写法规范
三段式状态机,我个人认为是RTL设计里最优雅的写法之一。它把状态机拆成三个always块,各司其职。
// 三段式状态机模板
// 第一段:状态转移
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
state <= IDLE;
else
state <= next_state;
end
// 第二段:次态逻辑
always @(*) begin
next_state = state;
case (state)
IDLE: if (start) next_state = S1;
S1: if (done) next_state = S2;
S2: next_state = IDLE;
default: next_state = IDLE;
endcase
end
// 第三段:输出逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
out <= 1'b0;
else begin
case (state)
IDLE: out <= 1'b0;
S1: out <= 1'b1;
S2: out <= 1'b0;
default: out <= 1'b0;
endcase
end
end
我的习惯:第二段用组合逻辑写next_state,第三段用时序逻辑输出。这样综合工具能更好地优化时序。你想想看,如果输出也写成组合逻辑,那毛刺问题就够你喝一壶的。
三段式的核心优势在于:状态转移、次态计算、输出生成完全解耦。改输出逻辑不会影响状态机跳转,调试起来特别方便。
避坑指南:我曾经见过有人把三段式写成两段式,把次态逻辑和输出逻辑混在一起。结果呢?综合后时序一塌糊涂。所以老老实实按三段式来,别耍小聪明。
知识体系总览
下面这张图,是我自己总结的状态机设计核心脉络。你把它记在心里,后面学优化技巧就轻松多了。
好了,第一章的内容就这些。记住:基础不牢,地动山摇。Moore和Mealy的区别、三种编码的取舍、三段式的规范——这些是你后面学优化技巧的根基。