FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-技术文章/快讯-技术分享-正文

有限状态机(FSM)Verilog编码实践指南:一段式、两段式与三段式对比与实现

FPGA小白FPGA小白
技术分享
4小时前
0
0
4

有限状态机(Finite State Machine, FSM)是数字逻辑设计的核心模式,用于描述具有有限个状态、并依据特定输入条件进行状态转移的系统。在Verilog HDL中,FSM的编码风格直接决定了设计的可读性、可维护性、综合结果(面积、时序)以及验证的便利性。本文将作为一份实施手册,深入对比并指导您完成一段式、两段式与三段式FSM的编码实践。

前置条件与环境

实施本指南中的FSM设计,您需要:

  • 支持Verilog-2001或SystemVerilog的RTL仿真环境(如ModelSim, VCS)。
  • FPGA或ASIC综合工具(如Vivado, Quartus, Design Compiler)。
  • 基础的Verilog语法与同步数字电路设计知识。

目标与验收标准

成功完成本指南后,您将能够:

  • 理解三种FSM编码风格的核心差异与适用场景。
  • 独立实现功能正确、代码清晰、综合结果优良的FSM模块。
  • 掌握避免常见设计陷阱(如锁存器推断、输出毛刺)的方法。
  • 为FSM编写有效的时序约束与验证测试平台。

实施步骤

阶段一:工程结构与状态定义

首先,为您的FSM定义明确的状态集合。推荐使用parameterlocalparam进行状态编码,避免在代码中直接使用数字“魔数”,这能极大提升代码的可读性和可维护性。例如,对于一个简单的序列检测器(检测输入序列“101”):

localparam S_IDLE = 3'b000,
           S_1    = 3'b001,
           S_10   = 3'b010,
           S_101  = 3'b100;

核心机制:清晰的状态定义是FSM设计的基石。它不仅是代码层面的抽象,更直接影响了综合工具对状态寄存器的编码方式(如二进制、独热码),进而影响时序和面积。

阶段二:关键模块编码风格对比与实现

以下以序列检测器为例,展示三种编码风格的具体实现与差异。

1. 一段式FSM(不推荐)

将状态转移、状态寄存和输出逻辑全部写在一个同步always @(posedge clk)块中。

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        state <= S_IDLE;
        out   <= 1'b0;
    end else begin
        case (state)
            S_IDLE: begin ... out <= 1'b0; end // 状态转移与输出耦合
            S_1:    begin ... out <= 1'b0; end
            // ... 其他状态
            default: state <= S_IDLE;
        endcase
    end
end

风险与边界:这种风格代码冗长,逻辑高度耦合,调试困难。更重要的是,它模糊了组合逻辑与时序逻辑的边界,可能违反同步设计原则,导致综合结果不可预测,且难以进行静态时序分析(STA)。仅在极简单的状态机中可考虑,但通常应避免。

2. 两段式FSM(结构化分离)

明确分离状态存储(时序逻辑)与次态和输出逻辑(组合逻辑)。

// 第一段:状态寄存器(时序逻辑)
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) state <= S_IDLE;
    else        state <= next_state;
end

// 第二段:次态与输出逻辑(组合逻辑)
always @(*) begin
    next_state = S_IDLE; // 默认赋值,避免锁存器
    out = 1'b0;
    case (state)
        S_IDLE: if (in) begin next_state = S_1; out = 1'b0; end
        S_1:    if (!in) begin next_state = S_10; out = 1'b0; end
        // ... 其他状态转移与输出赋值
    endcase
end

落地路径与风险:两段式结构清晰,是良好的工程实践。其核心风险在于组合逻辑输出可能产生毛刺(Glitch)。如果输出信号直接驱动异步电路或作为时钟使能,毛刺可能导致功能错误。因此,两段式适用于输出仅作为内部组合条件,或对毛刺不敏感的场景。

3. 三段式FSM(推荐最佳实践)

在两段式的基础上,将输出逻辑也寄存器化,即增加一个专用的输出寄存器级。

// 第一段:状态寄存器(时序逻辑)- 同两段式
// 第二段:次态逻辑(组合逻辑)- 仅计算次态,不包含输出
always @(*) begin
    next_state = S_IDLE;
    case (state)
        S_IDLE: if (in) next_state = S_1;
        S_1:    if (!in) next_state = S_10;
        // ...
    endcase
end

// 第三段:输出寄存器(时序逻辑)
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) out <= 1'b0;
    else begin
        case (state) // 注意:此处判断的是当前状态`state`,输出与状态同步
            S_101: out <= 1'b1;
            default: out <= 1'b0;
        endcase
    end
end

机制分析与优势:三段式通过将输出寄存器化,从根本上消除了输出毛刺,使输出信号干净稳定。这带来了三大核心优势:1) 改善时序:输出路径的时序计算变得简单明确,易于满足建立/保持时间;2) 简化验证:同步输出便于在Testbench中采样和检查;3) 提升可靠性。其代价是输出会延迟一个时钟周期,但在绝大多数同步系统中,这可以通过整体流水线设计来规划和接受,是换取设计鲁棒性的极小开销。

阶段三:约束、验证与结果分析

1. 时序约束:对于三段式FSM,需要对时钟clk创建基本周期约束。综合工具会自动对状态寄存器和输出寄存器进行时序分析。清晰的代码结构使得时序约束的编写和调试更为直观。

2. 验证Testbench:编写Testbench时,应覆盖所有状态转移路径,包括正常序列和异常输入。对于三段式设计,由于输出是寄存的,在时钟有效沿后采样输出进行判断即可。

3. 综合结果对比:对上述三种风格的同一功能FSM进行综合(以FPGA为目标),通常会观察到:三段式在关键路径时序(Slack)上更优,因为输出路径的寄存器化打破了长组合链;面积可能因额外寄存器而微增,但换取的是确定性的时序和可靠性,在现代设计中是值得的。

故障排查

  • 状态机卡死或无法跳出某状态:检查次态逻辑(第二段)的组合always块,确保所有可能的输入分支都有明确的next_state赋值,并为next_state设置默认值。
  • 综合报告推断出锁存器(Latch):这几乎总是因为在不完整的if-elsecase语句中,对组合逻辑块内的变量(如两段式中的outnext_state)未在所有分支下赋值。解决方法:1) 使用always @(*);2) 在组合块开始处为所有变量赋默认值。
  • 仿真结果与预期差一个时钟周期:检查Testbench的采样时机。对于三段式FSM,输出在状态变化后的下一个时钟沿才有效,确保您的断言或检查与此同步。

扩展与进阶

掌握基础三段式后,可进一步探索:

  • 状态编码优化:根据状态数量选择二进制编码(Binary)或独热编码(One-Hot)。独热编码在FPGA中通常有更好的时序表现,但占用更多触发器。
  • 输出逻辑优化:输出可能是摩尔型(Moore,仅与当前状态有关)或米利型(Mealy,与当前状态和输入有关)。三段式同样支持米利型,只需在第三段的case语句中结合输入条件判断即可。
  • 使用SystemVerilog增强:使用enum定义状态类型,结合always_ffalways_comb块,能使代码意图更清晰,并获得更好的语言安全检查。

参考

  • Clifford E. Cummings, “The Fundamentals of Efficient Synthesizable Finite State Machine Design using NC-Verilog and BuildGates”. SNUG 1999.
  • IEEE Standard for SystemVerilog (IEEE Std 1800-2017).

附录:编码风格选择速查表

编码风格核心特点输出特性推荐场景风险提示
一段式所有逻辑耦合在一个时序块同步,可能有不可预测延迟极简单、非关键逻辑(不推荐)代码混乱,时序难分析,维护性差
两段式状态寄存与次态/输出逻辑分离组合输出,可能有毛刺输出为内部中间信号,对毛刺不敏感输出毛刺可能引发异步错误
三段式状态寄存、次态逻辑、输出寄存三者分离同步寄存器输出,无毛刺绝大多数同步设计,尤其是输出驱动后续模块或需要稳定时序的场景输出延迟一个周期,需在系统级考虑
标签:
本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/33848.html
FPGA小白

FPGA小白

初级工程师
成电国芯®的讲师哦,专业FPGA已有10年。
25119.63W7.12W34.38W
分享:
成电国芯FPGA赛事课即将上线
基于FPGA的边缘AI可定制化推理加速:2026架构趋势与实施指南
基于FPGA的边缘AI可定制化推理加速:2026架构趋势与实施指南上一篇
FPGA VGA显示控制器设计与实现指南:从时序生成到图像叠加下一篇
FPGA VGA显示控制器设计与实现指南:从时序生成到图像叠加
相关文章
总数:365
FPGA与Verilog数字系统设计入门实践指南

FPGA与Verilog数字系统设计入门实践指南

本指南旨在为电子、计算机、通信等相关专业的学生,提供一条结构清晰、可操作…
技术分享
21小时前
0
0
6
0
2026年FPGA与芯片技术前沿观察:架构、封装、安全与生态的深度演进

2026年FPGA与芯片技术前沿观察:架构、封装、安全与生态的深度演进

作为成电国芯FPGA云课堂的特邀观察员,我,林芯语,将持续为您梳理硬件技…
技术分享
9天前
0
0
100
0
FPGA图像处理实战:基于Vivado HLS的实时边缘检测系统设计

FPGA图像处理实战:基于Vivado HLS的实时边缘检测系统设计

本工程旨在构建一个基于VivadoHLS(高层次综合)的实时图像边缘检…
技术分享
2天前
0
0
9
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容