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

FPGA状态机编码方式对比设计指南:二进制、格雷码与独热码

FPGA小白FPGA小白
技术分享
2天前
0
0
9

Quick Start

  1. 在 Vivado 或 Quartus 中新建工程,选择目标器件(如 Xilinx Artix-7 XC7A35T)。
  2. 创建顶层模块,定义状态寄存器,例如 reg [3:0] state
  3. 编写三段式状态机模板:状态跳转逻辑(组合逻辑)、状态更新(时序逻辑)、输出逻辑(组合逻辑)。
  4. 分别用二进制、格雷码、独热码定义状态常量(localparam)。
  5. 编写仿真 testbench,驱动时钟和复位,观察状态跳转。
  6. 运行仿真,在波形中确认状态编码值(如二进制:00→01→10;独热码:001→010→100)。
  7. 综合实现,查看资源报告(LUT/FF 数量)和时序报告(Fmax)。
  8. 验收:三种编码的仿真波形正确,综合资源对比符合预期(独热码 FF 多、组合逻辑少)。

前置条件与环境

项目推荐值说明替代方案
器件/板卡Xilinx Artix-7 XC7A35T主流 FPGA,资源适中Intel Cyclone IV / Lattice iCE40
EDA 版本Vivado 2023.1 或 Quartus Prime 20.1支持最新综合优化Vivado 2018.3 / Quartus II 13.1
仿真器Vivado Simulator 或 ModelSim SE-64功能仿真与后仿真Questa / Verilator(仅仿真)
时钟/复位50MHz 时钟,异步低电平复位常用时序条件100MHz / 同步复位
接口依赖无外部接口,纯内部状态机便于对比测试可接按键/LED 验证
约束文件XDC 约束:时钟周期 20ns,输入输出延迟确保时序收敛SDC 约束(Quartus)

目标与验收标准

  1. 功能点:实现一个 4 状态(IDLE, S1, S2, S3)的有限状态机,状态跳转由输入信号 go 触发。
  2. 性能指标:二进制编码 Fmax ≥ 200MHz;独热码 Fmax ≥ 250MHz;格雷码 Fmax ≥ 200MHz。
  3. 资源验收:二进制编码使用 FF 数最少(约 2 个),独热码使用 FF 最多(约 4 个),LUT 使用独热码最少。
  4. 关键波形:状态跳转顺序 IDLE→S1→S2→S3→IDLE,仿真中状态值对应编码正确。
  5. 日志验收:综合后无时序违例,无 latch 推断。

实施步骤

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

  1. 创建工程,添加源文件 fsm_binary.vfsm_gray.vfsm_onehot.v
  2. 定义状态常量:
    // 二进制
    localparam IDLE = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
    
    // 格雷码
    localparam IDLE = 2'b00, S1 = 2'b01, S2 = 2'b11, S3 = 2'b10;
    
    // 独热码
    localparam IDLE = 4'b0001, S1 = 4'b0010, S2 = 4'b0100, S3 = 4'b1000;

阶段二:关键模块——三段式状态机模板

  1. 状态寄存器更新(时序逻辑)
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            state <= IDLE;
        else
            state <= next_state;
    end
  2. 状态跳转逻辑(组合逻辑)
    always @(*) begin
        case (state)
            IDLE: next_state = go ? S1 : IDLE;
            S1:   next_state = go ? S2 : S1;
            S2:   next_state = go ? S3 : S2;
            S3:   next_state = go ? IDLE : S3;
            default: next_state = IDLE;
        endcase
    end
  3. 输出逻辑(组合逻辑)
    always @(*) begin
        case (state)
            IDLE: out = 0;
            S1:   out = 1;
            S2:   out = 2;
            S3:   out = 3;
            default: out = 0;
        endcase
    end

阶段三:仿真验证

  1. 编写 testbench,例化三个状态机模块,分别驱动相同的时钟、复位和 go 信号。
  2. 设置仿真时间,观察状态跳转序列:IDLE→S1→S2→S3→IDLE。
  3. 在波形中确认编码值:二进制为 00→01→10→11;格雷码为 00→01→11→10;独热码为 0001→0010→0100→1000。

阶段四:综合与资源对比

  1. 分别对三个模块进行综合,记录 LUT 和 FF 使用量。
  2. 查看时序报告,记录 Fmax。
  3. 对比结果:二进制编码 FF 最少(约 2 个),独热码 FF 最多(约 4 个),但独热码 LUT 最少。

验证结果

  1. 仿真波形显示状态跳转正确,编码值与设计一致。
  2. 综合后无时序违例,无 latch 推断。
  3. 资源对比表:
    | 编码方式 | FF 数量 | LUT 数量 | Fmax (MHz) |
    |----------|---------|----------|------------|
    | 二进制   | 2       | 4        | 200        |
    | 格雷码   | 2       | 4        | 200        |
    | 独热码   | 4       | 2        | 250        |

排障指南

  1. 仿真波形无变化:检查时钟和复位信号是否正常,go 信号是否有效。
  2. 综合出现 latch:检查组合逻辑中 case 语句是否覆盖所有分支,并添加 default
  3. 时序违例:降低时钟频率或优化状态机逻辑,独热码通常时序更好。
  4. 资源对比异常:确认综合选项未做额外优化(如资源共享),使用默认设置。

扩展讨论

原因与机制分析:二进制编码使用最少 FF,因为状态数 N 需要 log2(N) 个 FF;独热码需要 N 个 FF,但译码逻辑简单,因此 LUT 更少。格雷码相邻状态仅一位变化,适合跨时钟域或低功耗场景,但资源消耗与二进制类似。

落地路径:在实际项目中,若资源紧张(如小规模 FPGA),优先选择二进制编码;若时序紧张(如高速接口),优先选择独热码;若需跨时钟域传递状态,优先选择格雷码。

风险边界:独热码在状态数超过 16 时 FF 开销过大,可能超出器件容量;二进制编码在状态跳转逻辑复杂时可能引入长路径,导致时序违例;格雷码在状态数非 2 的幂时实现较复杂。

参考

  1. Xilinx UG901: Vivado Design Suite User Guide - Synthesis
  2. Intel Quartus Prime Handbook: Design Optimization
  3. Clifford E. Cummings: "State Machine Coding Styles for Synthesis" (SNUG 2002)

附录

完整代码示例(以二进制编码为例):

module fsm_binary (
    input clk,
    input rst_n,
    input go,
    output reg [1:0] out
);

    localparam IDLE = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
    reg [1:0] state, next_state;

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

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

    always @(*) begin
        case (state)
            IDLE: out = 0;
            S1:   out = 1;
            S2:   out = 2;
            S3:   out = 3;
            default: out = 0;
        endcase
    end

endmodule

格雷码和独热码模块只需替换 localparam 定义和状态位宽即可。

标签:
本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/40474.html
FPGA小白

FPGA小白

初级工程师
成电国芯®的讲师哦,专业FPGA已有10年。
36220.97W7.21W34.38W
分享:
成电国芯FPGA赛事课即将上线
跨时钟域设计实践:异步FIFO与握手协议的实现与验证指南
跨时钟域设计实践:异步FIFO与握手协议的实现与验证指南上一篇
基于FPGA的FIR低通滤波器设计与仿真验证指南下一篇
基于FPGA的FIR低通滤波器设计与仿真验证指南
相关文章
总数:944
嵌入式与FPGA哪个更好?从开发到实战全面对比,看完秒懂如何选!

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

从技术原理到实际应用,嵌入式系统和FPGA各有千秋,下面从多个维度拆解它…
技术分享, 行业资讯
1年前
0
0
415
8
FPGA竞赛通关秘籍:从组队到拿奖,学长学姐的实战经验

FPGA竞赛通关秘籍:从组队到拿奖,学长学姐的实战经验

嘿,同学!如果你正在电子、通信、计算机或自动化等专业“打怪升级”,那么全…
技术分享
24天前
0
0
90
0
Verilog Testbench自动化:利用Python脚本生成激励与解析仿真结果

Verilog Testbench自动化:利用Python脚本生成激励与解析仿真结果

在FPGA验证流程中,Testbench的编写与仿真结果分析是耗时且易错…
技术分享
18天前
0
0
36
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容