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

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

二牛学FPGA二牛学FPGA
技术分享
4小时前
0
0
6

有限状态机(Finite State Machine, FSM)是数字逻辑设计的核心范式,广泛应用于控制流、通信协议和序列检测等场景。在Verilog HDL中,FSM的编码风格直接决定了设计的可读性、可维护性、综合后的电路质量(面积与时序)以及验证的便利性。本指南将系统对比一段式、两段式和三段式FSM的编码方法,深入剖析其工作机制、适用场景与潜在风险,并提供从快速实现到深度优化的完整实施路径。

快速上手指南

  • 步骤1:环境准备。安装Vivado 2022.1或更高版本,准备一块带有LED和按键的FPGA开发板(如Basys3)。
  • 步骤2:创建工程。在Vivado中创建新工程,选择与开发板对应的器件型号(例如:xc7a35t-1cpg236c)。
  • 步骤3:编写三段式FSM示例。新建Verilog源文件,输入下文“实施步骤”章节中的“三段式FSM(推荐)”代码。
  • 步骤4:添加约束文件。新建XDC约束文件,为时钟(clk)、复位(rst_n)、输入(key)和输出(led)分配正确的物理管脚。
  • 步骤5:综合与实现。在Vivado中依次运行综合(Synthesis)和实现(Implementation)。
  • 步骤6:生成比特流并下载。生成比特流文件(Generate Bitstream),连接开发板并完成下载。
  • 步骤7:功能验证。操作板载按键,观察LED是否按照预设状态序列(IDLE→S1→S2→IDLE)循环变化。
  • 步骤8:对比分析。将代码分别替换为一段式或两段式风格,重复步骤3至7,观察综合报告中LUT、FF使用量以及时序报告(WNS)的变化。

前置条件与环境配置

项目推荐值/说明替代方案/注意事项
FPGA器件/开发板Xilinx 7系列 (如Artix-7 xc7a35t)Intel Cyclone IV/V, Lattice iCE40等均可,需对应调整约束文件。
EDA工具与版本Vivado 2022.1Quartus Prime 21.1或支持Verilog-2001及以上标准的工具。
仿真工具(可选)Vivado Simulator / ModelSim用于前期行为仿真,验证状态转移逻辑的正确性。
时钟频率100 MHz (来自板载晶振)需根据实际板卡调整,并在约束文件中正确定义。
复位方式低电平有效的异步复位 (rst_n)也可采用高电平有效或同步复位,但代码和约束需统一。
输入去抖需对机械按键(key)进行去抖处理可同步使用边沿检测电路或软件去抖模块,否则状态可能因抖动跳变异常。
约束文件(XDC)必须包含时钟定义、管脚分配、I/O延迟缺少时钟约束将导致时序分析失效,最大频率(Fmax)结果无意义。
代码风格标准使用 parameter 定义状态,而非 `define`define 宏全局可见,易造成命名空间污染,不利于模块化。

目标与验收标准

  • 功能正确:实现一个可综合、功能正确的FSM,例如一个简单的按键控制LED状态循环机。
  • 编码风格掌握:清晰区分并实现一段式、两段式、三段式FSM,理解各自代码结构与设计思想。
  • 量化对比:通过综合报告,对比不同编码风格在触发器(FF)、查找表(LUT)使用量以及最大时钟频率(Fmax)上的差异(预期趋势:资源消耗接近,但三段式在时序上通常更优)。
  • 波形可验证:在仿真中捕获清晰的波形,能显示当前状态(state_cur)、次态(state_nxt)、输入输出信号,且状态转移完全符合预期。
  • 规避常见错误:避免产生锁存器(Latch)、状态编码冲突、异步逻辑毛刺等典型设计问题。

实施步骤

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

所有编码风格的第一步都是明确定义状态机状态。状态编码方式影响综合结果:独热码(One-hot)状态译码简单,时序通常更好,但占用较多触发器;格雷码(Gray Code)状态变化时仅一位翻转,抗干扰能力强;二进制编码最节省寄存器,但组合逻辑可能更复杂。本指南以二进制编码为例。

// 状态定义:使用parameter,便于维护和复用
parameter IDLE = 2'b00;
parameter S1   = 2'b01;
parameter S2   = 2'b10;
// 状态寄存器声明
reg [1:0] state_cur, state_nxt; // 当前状态,次态

阶段二:关键模块编码对比

1. 一段式FSM(不推荐用于复杂设计)

所有逻辑(状态转移与输出生成)集中在同一个时序always块中。这种风格代码紧凑,但将组合逻辑和时序逻辑混合,可读性差,且不利于综合工具优化时序路径,容易在输出端产生毛刺。

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        state_cur <= IDLE;
        led <= 1'b0;
    end else begin
        case (state_cur)
            IDLE: begin
                if (key_pressed) begin
                    state_cur <= S1;
                    led <= 1'b1;
                end
            end
            S1: begin
                state_cur <= S2;
                led <= 1'b0;
            end
            S2: begin
                state_cur <= IDLE;
                led <= 1'b1;
            end
            default: state_cur <= IDLE;
        endcase
    end
end

2. 两段式FSM

使用两个always块:一个时序逻辑块用于状态寄存器更新,一个组合逻辑块用于产生次态和输出。它分离了时序与组合逻辑,比一段式清晰。但输出仍由组合逻辑产生,存在产生毛刺的风险,若输出用于驱动异步电路可能带来问题。

// 时序逻辑部分:状态寄存器更新
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        state_cur <= IDLE;
    else
        state_cur <= state_nxt;
end

// 组合逻辑部分:次态与输出逻辑
always @(*) begin
    // 默认赋值,避免锁存器
    state_nxt = state_cur;
    led = 1'b0;
    
    case (state_cur)
        IDLE: if (key_pressed) begin
                state_nxt = S1;
                led = 1'b1;
              end
        S1:   begin
                state_nxt = S2;
                led = 1'b0;
              end
        S2:   begin
                state_nxt = IDLE;
                led = 1'b1;
              end
        default: state_nxt = IDLE;
    endcase
end

3. 三段式FSM(推荐)

使用三个always块,清晰地将功能划分为:时序状态更新、组合次态逻辑、时序输出逻辑。这是业界推崇的风格,其核心优势在于输出由寄存器驱动,消除了组合逻辑毛刺,提高了系统的稳定性,并且输出延迟固定为一个时钟周期,时序更容易预测和满足。

// 第一段:时序逻辑,状态寄存器更新
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        state_cur <= IDLE;
    else
        state_cur <= state_nxt;
end

// 第二段:组合逻辑,次态逻辑
always @(*) begin
    state_nxt = state_cur; // 默认保持当前状态
    case (state_cur)
        IDLE: if (key_pressed) state_nxt = S1;
        S1:   state_nxt = S2;
        S2:   state_nxt = IDLE;
        default: state_nxt = IDLE;
    endcase
end

// 第三段:时序逻辑,输出寄存器
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        led <= 1'b0;
    else begin
        case (state_cur)
            IDLE: led <= 1'b0;
            S1:   led <= 1'b1;
            S2:   led <= 1'b0;
            default: led <= 1'b0;
        endcase
    end
end

验证结果与对比分析

完成上述三种风格的实现并综合后,您应重点关注Vivado综合报告中的以下指标:

  • 资源使用(Utilization):对比LUT和FF的数量。理论上,对于简单FSM,三种风格消耗的FF数量应相同(等于状态位数),LUT用量可能因逻辑优化略有差异,但通常接近。
  • 时序性能(Timing):查看“Timing Summary”中的WNS(Worst Negative Slack)。三段式FSM由于输出路径被寄存器打拍,其关键路径通常更短(仅包含状态转移逻辑),因此WNS往往更优,能达到更高的Fmax。两段式和一段式的关键路径可能包含输出组合逻辑,在高速设计下可能成为瓶颈。
  • 仿真波形:在Vivado Simulator中观察波形。三段式FSM的输出(led)变化会严格对齐时钟上升沿,且无毛刺。而一段式和两段式的输出可能在状态变化后立即改变(组合逻辑延迟),在信号线上可能观察到短暂的毛刺。

常见问题与排障

  • 锁存器(Latch)推断:在组合逻辑always块(always @(*))中,如果未在所有可能的执行分支中对某个信号赋值,综合工具会推断出锁存器。务必为所有输出信号和次态信号设置默认值。
  • 状态未完全定义:case语句中未使用default分支,或者状态编码未覆盖所有向量。这会导致综合出不可控的逻辑。始终添加default分支将状态导向安全状态(如IDLE)。
  • 异步复位问题:复位信号(rst_n)应列入敏感列表,且其电平应与设计一致。注意复位时状态必须被初始化为定义好的状态之一。
  • 输入信号同步与去抖:来自异步域(如按键)的信号必须经过同步器处理,否则可能导致状态机亚稳态。机械按键必须进行去抖,否则单次按压会被识别为多次状态触发。

扩展与深入优化

掌握基础编码后,可考虑以下进阶方向:

  • 状态编码优化:根据设计需求选择编码方式。对性能要求高、状态数较少的设计,使用独热码。对状态顺序变化严格的设计(如计数器型FSM),考虑格雷码。对资源极度敏感的设计,使用二进制编码。
  • 输出编码(Output Encoding):将输出逻辑与状态编码合并,直接用状态位作为输出,可以节省逻辑资源,但会降低代码可读性和灵活性。
  • 使用enum定义状态(SystemVerilog):如果工具支持SystemVerilog,使用typedef enum定义状态机,可进一步增强类型安全和代码可读性。
  • FSM分解:对于过于复杂的状态机,可考虑分解为多个协同工作的子状态机,降低单个状态机的复杂度。

参考与附录

  • IEEE Standard for Verilog Hardware Description Language (IEEE Std 1364-2005).
  • Xilinx UG901 (Vivado Design Suite User Guide: Synthesis). 其中包含HDL编码风格指南。
  • Clifford E. Cummings, “The Fundamentals of Efficient Synthesizable Finite State Machine Design using NC-Verilog and BuildGates”. SNUG 1999/2000 经典论文,详细论述了各种FSM编码风格。
  • 附录A:完整的、带注释的测试平台(Testbench)示例代码(可在项目网站获取)。
标签:
本文原创,作者:二牛学FPGA,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/33845.html
二牛学FPGA

二牛学FPGA

初级工程师
这家伙真懒,几个字都不愿写!
34816.55W3.89W3.67W
分享:
成电国芯FPGA赛事课即将上线
Verilog有限状态机(FSM)编码实践指南:一段式、两段式与三段式对比
Verilog有限状态机(FSM)编码实践指南:一段式、两段式与三段式对比上一篇
Verilog有限状态机高效编码实践指南:一段式、两段式与三段式对比下一篇
Verilog有限状态机高效编码实践指南:一段式、两段式与三段式对比
相关文章
总数:365
FPGA功耗优化指南:让你的设计更“冷静”更省电

FPGA功耗优化指南:让你的设计更“冷静”更省电

在FPGA的世界里,性能、面积和功耗,就像是一个“不可能三角”。但如今,…
技术分享
10天前
0
0
79
0
FPGA的优势,很强大

FPGA的优势,很强大

与CPU、GPU、ASIC相比,FPGA主要存在如下四个方面的优势:并行…
技术分享
3年前
7
0
924
1
FPGA如何成为边缘AI的“灵活大脑”?

FPGA如何成为边缘AI的“灵活大脑”?

引言:当AI来到你身边你有没有发现,AI正悄悄从云端“大服务器”…
技术分享
1个月前
0
0
62
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容