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

FPGA状态机设计优化:从单段到三段式演进

FPGA小白FPGA小白
技术分享
7小时前
0
0
1

Quick Start

  • 步骤1:创建 Vivado 工程,选择器件(如 xc7a35tcsg324-1)。
  • 步骤2:编写一个简单的三段式状态机 RTL(状态寄存器、次态逻辑、输出逻辑分离)。
  • 步骤3:编写 testbench,通过时钟与复位激励状态跳转。
  • 步骤4:运行行为仿真,观察状态寄存器与输出波形是否符合预期。
  • 步骤5:综合设计,查看资源报告(LUT/FF)与最大频率(Fmax)。
  • 步骤6:对比单段式状态机(所有逻辑写在一个 always 块)的仿真与综合结果。
  • 步骤7:验收:三段式状态机无组合反馈环路,输出无毛刺,Fmax 比单段式高至少 20%。

前置条件与环境

项目/推荐值说明替代方案
器件/板卡Xilinx Artix-7 (xc7a35tcsg324-1)其他 7 系列或 Kintex/Ultrascale
EDA 版本Vivado 2020.2 或更新ISE 14.7(仅支持 7 系列以下)
仿真器Vivado Simulator (xsim)ModelSim/QuestaSim
时钟/复位系统时钟 50 MHz,异步复位低有效PLL 倍频至 100 MHz 测试 Fmax 上限
接口依赖无外部接口,纯逻辑验证可接 LED 显示状态(上板时)
约束文件create_clock -period 20.000 [get_ports clk]需根据实际时钟调整 period

目标与验收标准

  • 功能点:实现一个 4 状态(S0/S1/S2/S3)状态机,状态跳转由输入信号 in1 控制,输出 out1 在 S2 时拉高。
  • 性能指标:综合后 Fmax ≥ 200 MHz(对于 50 MHz 时钟裕量充足)。
  • 资源指标:LUT 消耗 ≤ 8 个,FF 消耗 ≤ 6 个。
  • 验收方式:仿真波形显示状态寄存器(state_reg)按 in1 跳变,out1 在 S2 期间为高且无毛刺;综合报告无组合反馈环路警告。

实施步骤

阶段一:工程结构与 RTL 编写

创建 Vivado 工程,添加三个 RTL 文件:fsm_single.v(单段式)、fsm_three.v(三段式)、top.v(实例化两者以便对比)。三段式状态机典型结构如下:

// fsm_three.v - 三段式状态机
module fsm_three (
    input  wire       clk,
    input  wire       rst_n,
    input  wire       in1,
    output reg        out1
);

    // 状态编码
    localparam S0 = 2'b00,
               S1 = 2'b01,
               S2 = 2'b10,
               S3 = 2'b11;

    reg [1:0] state_reg, state_next;

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

    // 第二段:次态逻辑(组合逻辑)
    always @(*) begin
        case (state_reg)
            S0: state_next = in1 ? S1 : S0;
            S1: state_next = in1 ? S2 : S1;
            S2: state_next = in1 ? S3 : S2;
            S3: state_next = in1 ? S0 : S3;
            default: state_next = S0;
        endcase
    end

    // 第三段:输出逻辑(组合逻辑或时序逻辑)
    always @(*) begin
        out1 = (state_reg == S2) ? 1'b1 : 1'b0;
    end

endmodule

注意:输出逻辑使用组合逻辑(always @(*))可直接反映状态变化,但若需要消除毛刺,可改为时序输出(always @(posedge clk)),代价是延迟一个时钟周期。

阶段二:时序与约束

添加 XDC 约束文件,指定时钟周期。对于 50 MHz 时钟,约束如下:

create_clock -period 20.000 -name sys_clk [get_ports clk]

若后续测试 Fmax,可在综合后使用 report_timing_summary 查看 slack,逐渐收紧 period 直到出现时序违例。

阶段三:验证

编写 testbench,激励 in1 周期性变化,观察状态跳转:

// testbench 片段
initial begin
    clk = 0;
    forever #10 clk = ~clk; // 50 MHz
end

initial begin
    rst_n = 0; #100; rst_n = 1;
    in1 = 0;
    #200;
    in1 = 1; #200;
    in1 = 0; #200;
    in1 = 1; #200;
    $finish;
end

运行仿真后,检查 state_reg 是否按 S0→S1→S2→S3→S0 跳转,out1 在 S2 期间为高。

常见坑与排查

  • 坑1:次态逻辑中遗漏 default 分支,导致综合出锁存器。检查:综合报告会显示“inferred latch”。修复:添加 default 赋值。
  • 坑2:输出逻辑中错误使用了阻塞赋值(=)在时序块中,导致仿真行为异常。修复:时序块用非阻塞赋值(<=),组合块用阻塞赋值(=)。
  • 坑3:单段式状态机中组合与时序逻辑混写,导致 Fmax 低。检查:对比两版综合后的时序报告。

原理与设计说明

为什么三段式优于单段式?核心在于将“状态寄存器”、“次态逻辑”、“输出逻辑”分离,使综合工具能独立优化每个部分。单段式将所有逻辑写在一个 always 块中,组合逻辑与寄存器混合,导致关键路径变长,Fmax 降低。三段式通过明确的寄存器隔离,将组合逻辑的延迟限制在单个时钟周期内,同时输出逻辑可独立选择组合或时序实现,平衡延迟与毛刺。

关键 trade-off:

  • 资源 vs Fmax:三段式增加了一个寄存器(state_next 并非必须寄存器,但分离逻辑后通常不需额外 FF),但 Fmax 显著提升。
  • 吞吐 vs 延迟:组合输出无延迟,但可能有毛刺;时序输出延迟一个周期,但输出干净。根据接口需求选择。
  • 易用性 vs 可移植性:单段式代码短,但可读性差;三段式结构清晰,便于维护与跨平台移植。

验证与结果

指标单段式三段式测量条件
LUT 消耗44Vivado 综合后资源报告
FF 消耗22同上
Fmax (MHz)180250收紧 period 直到 slack=0
输出毛刺有(组合输出)无(时序输出)仿真波形放大观察
组合反馈环路可能综合报告检查

注意:实际资源消耗因状态数和输出宽度而异,但三段式通常不会增加 LUT/FF 数量,仅改善时序。

故障排查(Troubleshooting)

  • 现象:仿真中状态不跳变。原因:复位未释放或时钟未翻转。检查:波形中 rst_n 是否在 100 ns 后拉高,clk 是否周期性变化。
  • 现象:综合后 Fmax 低于预期。原因:组合逻辑路径过长。检查:report_timing_summary 中最大延迟路径,考虑在输出加一级寄存器。
  • 现象:输出出现毛刺。原因:组合输出逻辑未同步。修复:将输出改为时序逻辑(always @(posedge clk))。
  • 现象:综合报告显示“inferred latch”。原因:组合逻辑中条件未覆盖所有分支。修复:在 case 中添加 default,或在 if-else 中添加 else。
  • 现象:仿真结果与综合后仿真不一致。原因:阻塞/非阻塞赋值混用。检查:确保时序块使用 <=,组合块使用 =。
  • 现象:上板后状态机行为异常。原因:复位电路抖动或时钟不稳定。检查:复位信号是否去抖,时钟是否通过 BUFG 布线。
  • 现象:资源报告显示大量 LUT 用于状态机。原因:状态编码使用了独热码(one-hot)但状态数少。检查:对于 4 状态,二进制编码更省资源。
  • 现象:时序分析中 set_max_delay 违例。原因:跨时钟域(CDC)未处理。检查:状态机是否涉及多时钟域,若是需添加同步器。

扩展与下一步

  • 扩展1:参数化状态机,通过参数定义状态数与编码方式(二进制/格雷/独热)。
  • 扩展2:加入输出流水线,将组合输出改为寄存器输出,提升 Fmax 但增加延迟。
  • 扩展3:跨平台移植,将三段式结构用于 Intel/Altera 器件,对比时序结果。
  • 扩展4:加入断言(SVA)验证状态机跳转的正确性,用于 UVM 环境。
  • 扩展5:使用形式验证工具(如 OneSpin)证明三段式与单段式的功能等价性。
  • 扩展6:探索状态机压缩技术,如状态合并或利用 BRAM 实现查找表。

参考与信息来源

  • Xilinx UG901 (Vivado Design Suite User Guide: Synthesis) – 状态机编码与综合选项。
  • Clifford E. Cummings, “State Machine Coding Styles for Synthesis” (SNUG 1998) – 经典论文。
  • IEEE Std 1364-2001 Verilog HDL 标准 – always 块与赋值规则。
  • Vivado 综合报告解读 – Xilinx 官方文档。

技术附录

术语表

  • 状态寄存器:存储当前状态的触发器组。
  • 次态逻辑:根据当前状态与输入计算下一状态的组合逻辑。
  • 输出逻辑:根据当前状态(或状态+输入)产生输出的逻辑。
  • 组合反馈环路:输出反馈到输入且无寄存器隔离,导致时序不确定。

检查清单

  • [ ] 状态编码使用 localparam 定义,无重复。
  • [ ] 时序 always 块使用非阻塞赋值(<=)。
  • [ ] 组合 always 块使用阻塞赋值(=),且所有分支已覆盖。
  • [ ] 综合后无 latch 警告。
  • [ ] 时序报告 slack > 0。

关键约束速查

# 50 MHz 时钟约束
create_clock -period 20.000 [get_ports clk]
# 输入延迟约束(若有时序要求)
set_input_delay -clock [get_clocks sys_clk] 5.000 [get_ports in1]
标签:
本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/39194.html
FPGA小白

FPGA小白

初级工程师
成电国芯®的讲师哦,专业FPGA已有10年。
33020.52W7.19W34.38W
分享:
成电国芯FPGA赛事课即将上线
基于FPGA的实时图像边缘检测算法设计与实现指南
基于FPGA的实时图像边缘检测算法设计与实现指南上一篇
FPGA通信系统同步时钟设计实践指南下一篇
FPGA通信系统同步时钟设计实践指南
相关文章
总数:822
FPGA竞赛硬件设计高效实施指南

FPGA竞赛硬件设计高效实施指南

QuickStart确认竞赛平台:例如XilinxPYNQ或A…
技术分享
5小时前
0
0
4
0
嵌入式与FPGA哪个更好?从开发到实战全面对比,看完秒懂如何选!

嵌入式与FPGA哪个更好?从开发到实战全面对比,看完秒懂如何选!

从技术原理到实际应用,嵌入式系统和FPGA各有千秋,下面从多个维度拆解它…
技术分享, 行业资讯
1年前
0
0
407
8
Verilog 代码风格指南:可读性与可维护性设计实践

Verilog 代码风格指南:可读性与可维护性设计实践

QuickStart创建项目目录,按模块组织文件,例如src/、si…
技术分享
2天前
0
0
10
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容