FPGA状态机推荐三段式:第一段时序逻辑描述状态寄存器(现态→次态),第二段组合逻辑描述状态转移条件(次态计算),第三段时序或组合逻辑描述输出;状态编码用独热码(One-hot)速度快面积大,二进制码面积小速度慢,格雷码适合低功耗;复位用同步复位,避免异步复位的恢复时间问题。
本文概述
状态机(FSM)是FPGA设计中最常用的时序电路,用于控制逻辑、协议处理、数据通路调度。设计质量直接影响系统稳定性和资源利用率。三段式是工业界推荐写法,状态转移和输出分离,可读性好、易于综合和时序收敛。
核心要点
状态机三要素:现态(current state)、次态(next state)、输出(output)
一段式:状态转移+输出都在一个always块,简单但时序混乱,不推荐
两段式:一个时序块(状态寄存器)+一个组合块(转移+输出),输出可能有毛刺
三段式:状态寄存器(时序)+转移逻辑(组合)+输出逻辑(时序/组合),推荐
状态编码:独热码(One-hot)速度快、译码简单,二进制码省资源,格雷码切换功耗低
同步复位优于异步复位,避免复位释放时的恢复时间(recovery time)违例
状态机必须有默认状态(default),防止进入非法状态挂死

面试官考察点
考察状态机设计规范、Verilog写法、状态编码选择、复位策略、可综合性和时序意识。回答思路
先讲状态机三要素,再对比三种写法(重点讲三段式),然后讲状态编码选择,最后讲复位和默认状态等工程细节。参考回答
FPGA状态机我推荐三段式写法,结构清晰、综合效果好:
三段式结构:
// 第一段:时序逻辑,状态寄存器 always @(posedge clk) begin if (!rst_n) current_state <= IDLE; else current_state <= next_state; end // 第二段:组合逻辑,状态转移 always @(*) begin next_state = current_state; // 默认保持,避免latch case(current_state) IDLE: if(start) next_state = WORK; WORK: if(done) next_state = IDLE; default: next_state = IDLE; endcase end // 第三段:输出逻辑(时序输出,无毛刺) always @(posedge clk) begin if (!rst_n) begin valid <= 1'b0; cnt_en <= 1'b0; end else begin case(next_state) // 用next_state提前一拍输出 IDLE: begin valid <= 1'b0; cnt_en <= 1'b0; end WORK: begin valid <= 1'b1; cnt_en <= 1'b1; end default: ... endcase end end
三种写法对比:
| 写法 | 结构 | 优点 | 缺点 |
|---|---|---|---|
| 一段式 | 一个always块 | 代码少 | 时序组合混杂,难维护,不推荐 |
| 两段式 | 时序+组合 | 结构较清晰 | 组合输出可能有毛刺 |
| 三段式 | 时序+组合+时序输出 | 清晰、无毛刺、易综合 | 代码略多 |
状态编码选择:
① 独热码(One-hot):每个状态一位,如IDLE=4'b0001, WORK=4'b0010。状态比较只看一位,速度快、译码简单,但状态多时占用触发器多。FPGA触发器资源丰富,一般优先用独热码。
② 二进制码:IDLE=2'b00, WORK=2'b01。省触发器,但需要全译码,组合逻辑深,状态多时速度慢。
③ 格雷码:相邻状态只有一位变化,降低动态功耗和切换噪声,适合低功耗或异步跨时钟域场景。
工程要点:
① 组合逻辑块必须给所有变量赋默认值(next_state=current_state),否则综合出latch。
② case必须有default,防止状态机进入非法状态后挂死。
③ 用同步复位,异步复位释放时可能违反recovery time,导致状态不确定。
④ 输出用时序逻辑(第三段用posedge clk),避免组合逻辑输出的毛刺。
⑤ 状态名用parameter或localparam定义,不要直接用数字。

扫码关注



























