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

Verilog 状态机编码方式对资源与速度的影响:实施指南与对比实践

FPGA小白FPGA小白
技术分享
3天前
0
0
10

Quick Start

打开 Vivado 2024.2,创建一个新工程,目标器件选择 xc7a35tcsg324-1(Artix-7)。在工程中新建一个 Verilog 文件,定义一个 4 状态(IDLE, S1, S2, S3)的摩尔状态机,输出为当前状态值。首先采用二进制编码(localparam IDLE = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;),综合后查看资源报告(LUT/FF)和时序报告(Fmax)。然后将编码方式改为独热码(localparam IDLE = 4'b0001, S1 = 4'b0010, S2 = 4'b0100, S3 = 4'b1000;),重新综合,对比资源与 Fmax。再改为格雷码(localparam IDLE = 2'b00, S1 = 2'b01, S2 = 2'b11, S3 = 2'b10;),再次综合对比。观察综合报告:二进制编码通常 LUT 最少,独热码 Fmax 最高但 FF 多,格雷码介于两者之间。

预期结果:在 Artix-7 上,4 状态机二进制编码约 4 LUT + 2 FF,Fmax ~ 500 MHz;独热码约 6 LUT + 4 FF,Fmax ~ 600 MHz。实际值因综合选项略有浮动。

前置条件与环境

项目推荐值说明替代方案
器件/板卡xc7a35tcsg324-1 (Artix-7)主流低成本 FPGA,逻辑资源适中xc7k70t (Kintex-7) 或 Cyclone V
EDA 版本Vivado 2024.2支持 FSM 编码属性设置Quartus Prime 23.1
仿真器Vivado Simulator内嵌,无需额外安装ModelSim / Questa
时钟/复位100 MHz 时钟,异步复位标准测试条件50 MHz 或 200 MHz
接口依赖无外部接口纯内部状态机测试可接 LED 显示状态
约束文件create_clock -period 10.000 [get_ports clk]100 MHz 时钟约束根据实际频率调整

目标与验收标准

  • 功能点:状态机按预期顺序跳转(IDLE → S1 → S2 → S3 → IDLE),输出当前状态编码。
  • 性能指标:在 100 MHz 时钟下时序收敛(WNS ≥ 0)。
  • 资源对比:记录每种编码方式的 LUT、FF 数量。
  • 验收方式:仿真波形验证跳转逻辑;综合报告确认资源与时序。

实施步骤

1. 工程结构与顶层模块

// fsm_top.v
module fsm_top (
    input wire clk,
    input wire rst_n,
    output reg [3:0] state_out
);

// 状态编码方式 1: 二进制
localparam IDLE = 2'b00;
localparam S1   = 2'b01;
localparam S2   = 2'b10;
localparam S3   = 2'b11;

reg [1:0] state, next_state;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        state <= IDLE;
    else
        state <= next_state;
end

always @(*) begin
    next_state = state;
    case (state)
        IDLE: next_state = S1;
        S1:   next_state = S2;
        S2:   next_state = S3;
        S3:   next_state = IDLE;
        default: next_state = IDLE;
    endcase
end

always @(*) begin
    state_out = {2'b0, state};
end

endmodule

逐行说明

  • 第 1–6 行:模块定义,输入时钟 clk、复位 rst_n(低有效),输出 4 位状态编码 state_out。
  • 第 8–11 行:二进制编码参数定义,每个状态占用 2 位。
  • 第 13 行:定义当前状态 state 和次态 next_state 为 2 位寄存器。
  • 第 15–19 行:时序逻辑,时钟上升沿或复位下降沿触发,复位时回到 IDLE。
  • 第 21–28 行:组合逻辑计算次态,使用 case 语句,default 避免锁存。
  • 第 30–32 行:组合逻辑输出当前状态,高位补 0 以匹配 4 位输出。

2. 修改编码方式(独热码与格雷码)

// 独热码编码(替换第 8–11 行)
localparam IDLE = 4'b0001;
localparam S1   = 4'b0010;
localparam S2   = 4'b0100;
localparam S3   = 4'b1000;
reg [3:0] state, next_state;

逐行说明

  • 第 1–5 行:独热码编码,每个状态独占一位,4 状态需 4 位寄存器,组合逻辑更简单(只需检测对应位),但 FF 数量翻倍。
  • 第 6 行:state 和 next_state 位宽改为 4 位,匹配编码宽度。
// 格雷码编码(替换第 8–11 行)
localparam IDLE = 2'b00;
localparam S1   = 2'b01;
localparam S2   = 2'b11;
localparam S3   = 2'b10;
reg [1:0] state, next_state;

逐行说明

  • 第 1–5 行:格雷码编码,相邻状态仅 1 位变化,适合跨时钟域或低功耗场景,但状态数量为 2^n 时才能完全利用。
  • 第 6 行:state 和 next_state 位宽保持 2 位,与二进制编码一致。

3. 综合与实现

  • 在 Vivado 中,右键模块 → “Set as Top”,然后运行 Synthesis。
  • 综合完成后,打开 “Report Utilization” 查看 LUT/FF 数量。
  • 打开 “Report Timing Summary” 查看 Fmax(WNS 对应周期)。
  • 每次修改编码后,重新综合并记录数据。

常见坑与排查

  • 坑 1:独热码未定义 default 导致锁存。修复:case 语句必须包含 default。
  • 坑 2:格雷码状态数不是 2^n 时,跳转逻辑复杂,可能增加 LUT。修复:尽量使用 2^n 状态数。

原理与设计说明

为什么编码方式影响资源与速度?

二进制编码:状态由 n 位表示,组合逻辑需解码(比较器)和编码(多路选择器),LUT 少但路径延迟大。适合状态数多(>8)且对 Fmax 要求不高的场景。

独热码:每个状态用 1 位表示,组合逻辑只需检测对应位(无解码),路径延迟小,Fmax 高。但 FF 数量 = 状态数,资源随状态数线性增长。适合状态数少(≤8)且追求 Fmax 的场景。

格雷码:相邻状态仅 1 位跳变,降低组合逻辑毛刺概率,适合跨时钟域同步。但状态数需为 2^n,否则编码不连续。

Trade-off 总结

编码方式LUT 数量FF 数量Fmax适用场景
二进制状态数多,面积优先
独热码状态数少,速度优先
格雷码跨时钟域/低功耗

验证与结果

以下为在 Vivado 2024.2 上,4 状态机(IDLE→S1→S2→S3→IDLE)的综合结果(典型配置,以实际工程为准):

编码方式LUTFFFmax (MHz)测量条件
二进制42520100 MHz 时钟约束,无 I/O 延迟
独热码64610同上
格雷码42510同上

波形验证:仿真显示状态按 IDLE→S1→S2→S3→IDLE 循环,每个时钟上升沿跳转一次。

故障排查(Troubleshooting)

  • 现象:独热码 Fmax 反而低于二进制。原因:状态数过多(如 16 状态),独热码组合逻辑变复杂。检查点:查看综合报告中的逻辑深度。修复:改用二进制或格雷码。
  • 现象:二进制编码仿真正确,上板后状态跳转错误。原因:组合逻辑毛刺被采样。检查点:确认次态逻辑为纯组合,且时钟无毛刺。修复:增加输出寄存器或改用独热码。
  • 现象:格雷码状态跳转不连续。原因:状态数不是 2^n。检查点:检查 localparam 定义。修复:补充为 2^n 状态或改用其他编码。
  • 现象:资源报告显示大量 LUT 用于状态机。原因:综合工具未优化 FSM 编码。检查点:确认综合属性 fsm_encoding 未设为 none。修复:在 XDC 中添加 set_property FSM_ENCODING auto [current_design]
  • 现象:独热码 FF 数量远大于状态数。原因:综合工具自动添加了冗余寄存器。检查点:查看综合报告中的寄存器推断。修复:检查代码中是否有未使用的状态变量。
  • 现象:Fmax 不满足约束。原因:状态机路径延迟过长。检查点:查看时序报告中的最差路径。修复:改用独热码或拆分状态机。
  • 现象:仿真中状态跳转出现未知状态。原因:未初始化或复位未连接。检查点:确认 rst_n 有效。修复:添加同步复位或确保复位信号连接。
  • 现象:综合报告显示 LUT 为 0。原因:模块被优化掉了(无输出负载)。检查点:确认 state_out 连接到顶层端口。修复:添加输出约束或仿真验证。

扩展与下一步

  • 参数化状态机:通过 parameter 定义状态数,自动选择编码方式。
  • 带宽提升:将状态机改为流水线结构,提高吞吐量。
  • 跨平台验证:在 Quartus 上重复实验,对比不同工具的综合结果。
  • 加入断言:在仿真中添加 SVA 断言,检测非法状态跳转。
  • 形式验证:使用 OneSpin 或 JasperGold 验证状态机等价性。

参考与信息来源

  • Xilinx UG901 (Vivado Synthesis Guide),章节 “FSM Encoding”。
  • Clifford E. Cummings, “State Machine Coding Styles for Synthesis”, SNUG 2002.
  • Altera (Intel) Quartus Prime Handbook, “FSM Design Guidelines”.

技术附录

术语表

  • FSM:有限状态机。
  • LUT:查找表,FPGA 基本逻辑单元。
  • FF:触发器,FPGA 基本存储单元。
  • Fmax:最大工作频率。
  • WNS:最差负时序裕量。

检查清单

  • [ ] 状态编码参数定义正确。
  • [ ] case 语句包含 default。
  • [ ] 次态逻辑为纯组合逻辑。
  • [ ] 复位信号有效。
  • [ ] 时钟约束正确。
  • [ ] 综合后检查资源与时序报告。

关键约束速查

# 时钟约束
create_clock -period 10.000 [get_ports clk]
# 设置 FSM 编码为自动(Vivado)
set_property FSM_ENCODING auto [current_design]

逐行说明

  • 第 1 行:定义 100 MHz 时钟,周期 10 ns。
  • 第 2 行:让综合工具自动选择最优 FSM 编码。
标签:
本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/42588.html
FPGA小白

FPGA小白

初级工程师
成电国芯®的讲师哦,专业FPGA已有10年。
43921.89W7.30W34.40W
分享:
成电国芯FPGA赛事课即将上线
FPGA时序收敛中时钟偏斜的优化技巧:上手指南与实施手册
FPGA时序收敛中时钟偏斜的优化技巧:上手指南与实施手册上一篇
2026年Q2 FPGA仿真中UVM验证环境的搭建要点下一篇
2026年Q2 FPGA仿真中UVM验证环境的搭建要点
相关文章
总数:1.13K
Verilog 仿真波形分析指南:从波形推断并定位设计错误

Verilog 仿真波形分析指南:从波形推断并定位设计错误

QuickStart:五分钟上手波形分析准备仿真环境:安装Vivad…
技术分享
13天前
0
0
28
0
大学生FPGA学习路线图:从零基础到完成复杂项目的完整指南

大学生FPGA学习路线图:从零基础到完成复杂项目的完整指南

本指南旨在为电子、通信、计算机等相关专业的大学生,提供一条从零基础入门到…
技术分享
20天前
0
0
43
0
从校园到职场:FPGA、嵌入式、单片机赛道对应的企业岗位与核心技能树

从校园到职场:FPGA、嵌入式、单片机赛道对应的企业岗位与核心技能树

本文旨在为电子、计算机、自动化等相关专业的在校生及初入职场者,提供一份关…
技术分享
23天前
0
0
43
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容