有限状态机(Finite State Machine, FSM)是数字逻辑设计的核心控制骨架,其Verilog编码风格直接决定了代码的可读性、可维护性、综合后的时序性能及资源利用率。本文旨在系统对比一段式、两段式与三段式FSM编码方法,提供从快速验证到深度分析的完整实施路径,阐明不同风格的内在机制与适用边界,帮助设计者根据具体场景做出最优选择。
快速上手指南
本指南将通过一个对比实验,引导您直观感受三种编码风格的差异。请按顺序完成以下步骤:
- 步骤1: 在Vivado或Quartus中创建新工程,或打开现有工程。
- 步骤2: 新建Verilog源文件(如
fsm_compare.v)。 - 步骤3: 使用三段式风格编写一个简单状态机(例如:IDLE → S1 → S2 → IDLE)。
- 步骤4: 编写基础测试平台,提供时钟与复位信号,并实例化该状态机模块。
- 步骤5: 进行行为仿真,验证状态转移与输出逻辑是否符合预期。
- 步骤6: 对设计进行综合,查看报告中的时序裕量(Slack)和触发器(FF)使用量。
- 步骤7: 在同一文件中,使用两段式风格重写相同逻辑,重复步骤5与6。
- 步骤8: 使用一段式风格再次重写,并重复仿真与综合步骤。
- 步骤9: 对比三份综合报告,重点关注最大时钟频率(Fmax)、触发器及查找表(LUT)数量的差异。
- 步骤10: 分析仿真波形,确认功能一致性,并观察输出信号与时钟沿的关系在不同风格下的表现。
前置条件与环境配置
| 项目 | 推荐值/说明 | 替代方案/备注 |
|---|---|---|
| FPGA器件/板卡 | Xilinx Artix-7系列 (如XC7A35T) | Intel Cyclone IV/V系列,任何主流FPGA均可 |
| EDA工具版本 | Vivado 2022.1 或 Quartus Prime 21.1 | 其他支持SystemVerilog-2005及以上标准的版本 |
| 仿真工具 | Vivado Simulator (XSim) / ModelSim SE | VCS, IES,或开源工具如Verilator(需注意行为差异) |
| 设计语言 | Verilog-2001 或 SystemVerilog | 建议使用SystemVerilog的enum定义状态,增强可读性 |
| 时钟与复位 | 单时钟域,同步低有效复位 | 对比实验需保持时钟频率(如100MHz)和复位方式一致 |
| 约束文件 | 基本的时钟和复位约束(.xdc 或 .sdc) | 必须提供,否则时序分析无意义 |
| 状态编码 | 使用工具默认(如Binary)或显式指定 | One-Hot编码方式会显著影响比较结果,本文默认Binary |
| 输出类型 | 摩尔型(Moore)输出 | 米利型(Mealy)输出逻辑位置不同,但风格对比原理相同 |
目标与验收标准
- 功能验收: 三种编码风格实现的状态机,在仿真中必须表现出完全相同的状态转移行为和输出逻辑。
- 性能验收: 通过综合报告,量化对比三种风格在时序性能(Fmax/建立时间裕量)和资源占用(触发器、查找表)上的差异。典型趋势是:三段式时序最优,一段式资源可能最少但时序路径最长。
- 代码质量验收: 理解三段式结构最清晰,易于添加同步寄存器输出;两段式的组合逻辑输出可能存在毛刺风险;一段式代码将时序与组合逻辑混合,最难维护和调试。
- 波形验收: 在仿真波形中,能清晰观察到:状态寄存器在时钟有效沿更新;三段式的输出与状态寄存器同步变化;而两段式/一段式若采用组合输出,则输出可能随输入异步变化。
实施步骤详解
阶段一:工程结构与基础模块
建议创建一个顶层模块,用于分别实例化三种不同风格的状态机,并连接至相同的输入激励。测试平台应能支持单独或并行测试,便于对比。
以下为三段式FSM(Moore型,输出同步于时钟)的骨架代码示例:
// 示例:三段式FSM的骨架 (Moore型,输出同步于时钟)
module fsm_three_segment (
input wire clk,
input wire rst_n,
input wire trigger,
output reg out_valid
);
// 1. 状态定义
parameter S_IDLE = 2'b00;
parameter S_WORK = 2'b01;
parameter S_DONE = 2'b10;
reg [1:0] current_state, next_state;
// 2. 状态寄存器(第一段:时序逻辑)
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
current_state <= S_IDLE;
else
current_state <= next_state;
end
// 3. 下一状态逻辑(第二段:组合逻辑)
always @(*) begin
next_state = current_state; // 默认保持当前状态
case (current_state)
S_IDLE: if (trigger) next_state = S_WORK;
S_WORK: next_state = S_DONE;
S_DONE: next_state = S_IDLE;
default: next_state = S_IDLE;
endcase
end
// 4. 输出逻辑(第三段:时序逻辑,实现同步寄存器输出)
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
out_valid <= 1'b0;
else begin
case (current_state)
S_DONE: out_valid <= 1'b1;
default: out_valid <= 1'b0;
endcase
end
end
endmodule阶段二:两段式与一段式实现
两段式实现: 通常将上述的“下一状态逻辑”和“输出逻辑”合并为一个组合逻辑always块,而状态寄存器单独为一个时序逻辑块。注意,若输出逻辑是组合的,则输出可能存在毛刺。
一段式实现: 将所有逻辑(状态转移、输出生成)塞进同一个时序always块中。这种风格代码紧凑,但将组合逻辑嵌入时序块,可能导致更长的关键路径,且不利于代码维护与功能扩展。
验证结果分析
完成仿真与综合后,请从以下维度进行对比分析:
- 功能一致性: 三种设计的仿真波形应完全一致,确保逻辑功能正确。
- 时序报告解读: 重点关注最差负时序裕量(WNS)。三段式设计由于将输出寄存器化,通常能获得最好的WNS,即更高的Fmax。一段式设计的关键路径可能包含状态译码和输出逻辑,因此时序最差。
- 资源报告解读: 对比触发器(FF)和查找表(LUT)的使用量。一段式可能因为逻辑更合并而使用略少的LUT,但这是以牺牲时序为代价的。三段式会多用一些触发器来寄存输出。
常见问题与排障
- 仿真与综合行为不一致: 检查组合逻辑块(
always @(*))是否对所有输入条件都有明确的赋值,避免产生锁存器(Latch)。在两段式/一段式中尤其要注意输出信号的完备赋值。 - 时序违例严重: 如果一段式设计时序不满足,首要考虑将其重构为三段式。对于两段式设计,可以考虑将关键输出信号寄存器化(即转为三段式)。
- 状态机无法跳出某状态: 检查状态转移条件是否完备,特别是
case语句中是否添加了default分支,并将next_state赋予安全值(如IDLE)。
扩展与最佳实践
- 状态编码选择: 对于状态数较少(如少于8个)的状态机,Binary编码与One-Hot编码差异不大。对于状态数较多的状态机,One-Hot编码(每个状态用一个触发器表示)通常能获得更好的时序性能,但会消耗更多触发器资源。综合工具通常能自动优化,但显式指定编码方式可使结果更可控。
- 输出寄存器化: 强烈推荐使用三段式风格,并将输出逻辑放在单独的时序
always块中。这不仅能消除组合输出毛刺,提升系统稳定性,还能将输出路径从状态机的关键路径中剥离,显著改善时序。 - 使用SystemVerilog增强可读性: 使用
typedef enum定义状态,使代码更清晰,并能减少编码错误。 - 明确的设计边界: 一段式风格仅推荐用于极其简单、对时序要求不高的控制逻辑。对于任何需要维护、优化或复用的设计,三段式是事实上的工业标准。
核心机制与选择依据
不同编码风格的本质差异在于时序路径的划分:
- 三段式: 将“状态转移计算”和“输出生成”这两个组合逻辑阶段,用状态寄存器隔离开。这相当于在两个组合逻辑块之间插入了流水线寄存器,将长路径切分为两个较短的时钟周期路径(当前状态→下一状态;当前状态→输出),从而大幅提升系统时钟频率。
- 两段式: 将两个组合逻辑阶段合并,其关键路径是从“当前状态寄存器”经过“下一状态与输出组合逻辑”再回到“状态寄存器”或直接输出。这条路径比三段式更长,因此Fmax更低。
- 一段式: 所有逻辑在一个时序块中完成,综合工具会试图将组合逻辑吸收到触发器之前的输入路径中。这通常会导致从模块输入/当前状态到触发器D端之间形成非常复杂的组合逻辑链,成为难以优化的超长关键路径。
因此,选择依据非常明确:追求高性能、高可靠性与可维护性,必选三段式;仅在面积极度受限且时序宽松的极简场景下,可考虑一段式;两段式可作为理解中间过程,但实际工程中已不推荐。
参考与附录
- IEEE Standard for SystemVerilog (IEEE Std 1800-2017).
- Xilinx UG901 (Vivado Design Suite User Guide: Synthesis). 其中有关FSM编码风格与优化的章节。
- Clifford E. Cummings, “The Fundamentals of Efficient Synthesizable Finite State Machine Design using NC-Verilog and BuildGates”. SNUG 1999 经典论文,详细论述了各种FSM编码风格。
- 附录: 完整的三段式、两段式、一段式Verilog代码对比示例文件(
fsm_compare.v)可在实践工程中根据上述骨架自行补全。




