Verilog 低功耗 FSM 编码设计指南:2026 年方法对比与实施

FPGA小白
文章2026-07-23
24 0 0 0

Quick Start

  1. 准备 Vivado 2024.2 或更高版本(2026 年推荐使用 Vivado 2026.1 或 Vitis Unified IDE)。
  2. 新建 RTL 工程,选择目标器件(示例:Xilinx Artix-7 XC7A35T,低功耗场景可选 Spartan-7 或 UltraScale+)。
  3. 创建顶层模块 fsm_low_power,包含时钟、异步复位低有效、输入信号和输出信号。
  4. 编写三个 FSM 实现:二进制编码(Binary)、格雷编码(Gray)、One-Hot 编码,分别命名为 fsm_binary、fsm_gray、fsm_onehot。
  5. 添加时钟约束(create_clock -period 10.000 [get_ports clk])和输入输出延迟约束。
  6. 运行综合(Synthesis),查看资源利用率报告(Report Utilization)。
  7. 运行实现(Implementation),查看时序报告(Report Timing Summary)和功耗报告(Report Power)。
  8. 对比三种编码的 Fmax、动态功耗、静态功耗和 LUT/FF 占用,记录于表格。

前置条件与环境

项目推荐值说明替代方案
器件/板卡Xilinx Artix-7 XC7A35T-1CSG324C低功耗 28nm 工艺,适合对比 FSM 编码功耗Spartan-7 (28nm)、UltraScale+ (16nm)
EDA 版本Vivado 2026.12026 年最新版本,支持先进功耗分析Vivado 2024.2 或 2025.1
仿真器Vivado Simulator (xsim)内置于 Vivado,无需单独安装ModelSim/Questa、Verilator
时钟/复位时钟 100 MHz,异步复位低有效典型同步设计基础时钟 50 MHz 或 200 MHz
接口依赖无外部接口,纯逻辑验证仅需顶层输入输出可添加 AXI-Stream 接口—
约束文件XDC 文件:时钟周期 10 ns,输入延迟 2 ns,输出延迟 2 ns确保时序收敛根据实际板级调整

目标与验收标准

  • 功能点:三种 FSM 实现相同的状态转移逻辑(4 状态:IDLE, S1, S2, S3),输出相同。
  • 性能指标:Fmax ≥ 100 MHz(时钟周期 10 ns),建立时间裕量 > 0.2 ns。
  • 资源占用:记录 LUT、FF、Slice 数量,One-Hot 编码 LUT 数应比二进制多 30%~80%(示例数据,以实际综合为准)。
  • 功耗对比:动态功耗(mW)格雷编码最低,One-Hot 次之,二进制最高(示例趋势,以实际工艺为准)。
  • 验收方式:运行仿真验证功能正确;查看实现后时序报告和功耗报告;记录并对比表格。

实施步骤

工程结构与模块划分

// 文件结构示例
// src/
//   fsm_top.v (顶层,实例化三个 FSM)
//   fsm_binary.v (二进制编码 FSM)
//   fsm_gray.v (格雷编码 FSM)
//   fsm_onehot.v (One-Hot 编码 FSM)
//   tb_fsm_top.v (测试平台)
// constraints/
//   top.xdc (时序约束)

逐行说明

  • 第 1 行:注释,说明文件结构,便于工程管理。
  • 第 2 行:src 目录存放所有 RTL 源文件。
  • 第 3 行:顶层模块 fsm_top,负责连接三个 FSM 实例,共享时钟和复位。
  • 第 4 行:二进制编码 FSM 模块文件。
  • 第 5 行:格雷编码 FSM 模块文件。
  • 第 6 行:One-Hot 编码 FSM 模块文件。
  • 第 7 行:测试平台文件,用于仿真验证。
  • 第 8 行:constraints 目录存放约束文件。
  • 第 9 行:时序约束文件 top.xdc。

关键模块:二进制编码 FSM

module fsm_binary (
    input wire clk,
    input wire rst_n,
    input wire start,
    output reg [1:0] state_out
);

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

逐行说明

  • 第 1 行:模块声明,名称为 fsm_binary,端口包括时钟 clk、异步复位 rst_n(低有效)、输入 start、输出 state_out(2 位)。
  • 第 2 行:时钟输入端口声明。
  • 第 3 行:复位输入端口声明,低有效。
  • 第 4 行:启动信号输入端口声明。
  • 第 5 行:状态输出端口声明,reg 类型,位宽 2 位。
  • 第 6 行:空行,用于分隔端口声明与内部定义。
  • 第 7 行:定义状态 IDLE 为 2’b00。
  • 第 8 行:定义状态 S1 为 2’b01。
  • 第 9 行:定义状态 S2 为 2’b10。
  • 第 10 行:定义状态 S3 为 2’b11。
  • 第 11 行:空行,用于分隔参数定义与寄存器声明。
  • 第 12 行:声明当前状态寄存器 state 和下一状态寄存器 next_state,均为 2 位 reg 类型。
  • 第 13 行:空行,用于分隔声明与 always 块。
  • 第 14 行:时序 always 块,敏感列表为时钟上升沿或复位下降沿。
  • 第 15 行:判断复位是否有效(rst_n 为低)。
  • 第 16 行:复位有效时,当前状态赋值为 IDLE。
  • 第 17 行:复位无效时,执行 else 分支。
  • 第 18 行:当前状态更新为下一状态。
  • 第 19 行:end 结束 always 块。

关键模块:格雷编码 FSM

module fsm_gray (
    input wire clk,
    input wire rst_n,
    input wire start,
    output reg [1:0] state_out
);

localparam IDLE = 2'b00;
localparam S1   = 2'b01;
localparam S2   = 2'b11;
localparam S3   = 2'b10;

reg [1:0] state, next_state;

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

逐行说明

  • 第 1 行:模块声明,名称为 fsm_gray,端口与二进制版本相同。
  • 第 2 行:时钟输入端口声明。
  • 第 3 行:复位输入端口声明,低有效。
  • 第 4 行:启动信号输入端口声明。
  • 第 5 行:状态输出端口声明,reg 类型,位宽 2 位。
  • 第 6 行:空行。
  • 第 7 行:定义状态 IDLE 为 2’b00。
  • 第 8 行:定义状态 S1 为 2’b01。
  • 第 9 行:定义状态 S2 为 2’b11(格雷编码相邻状态仅一位变化)。
  • 第 10 行:定义状态 S3 为 2’b10。
  • 第 11 行:空行。
  • 第 12 行:声明当前状态和下一状态寄存器。
  • 第 13 行:空行。
  • 第 14 行:时序 always 块,敏感列表为时钟上升沿或复位下降沿。
  • 第 15 行:判断复位是否有效。
  • 第 16 行:复位有效时,当前状态赋值为 IDLE。
  • 第 17 行:复位无效时,执行 else 分支。
  • 第 18 行:当前状态更新为下一状态。
  • 第 19 行:end 结束 always 块。

关键模块:One-Hot 编码 FSM

module fsm_onehot (
    input wire clk,
    input wire rst_n,
    input wire start,
    output reg [3:0] state_out
);

localparam IDLE = 4'b0001;
localparam S1   = 4'b0010;
localparam S2   = 4'b0100;
localparam S3   = 4'b1000;

reg [3:0] state, next_state;

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

逐行说明

  • 第 1 行:模块声明,名称为 fsm_onehot,端口与之前类似,但 state_out 位宽为 4 位。
  • 第 2 行:时钟输入端口声明。
  • 第 3 行:复位输入端口声明,低有效。
  • 第 4 行:启动信号输入端口声明。
  • 第 5 行:状态输出端口声明,reg 类型,位宽 4 位(One-Hot 编码需要每位对应一个状态)。
  • 第 6 行:空行。
  • 第 7 行:定义状态 IDLE 为 4’b0001。
  • 第 8 行:定义状态 S1 为 4’b0010。
  • 第 9 行:定义状态 S2 为 4’b0100。
  • 第 10 行:定义状态 S3 为 4’b1000。
  • 第 11 行:空行。
  • 第 12 行:声明当前状态和下一状态寄存器,位宽 4 位。
  • 第 13 行:空行。
  • 第 14 行:时序 always 块,敏感列表为时钟上升沿或复位下降沿。
  • 第 15 行:判断复位是否有效。
  • 第 16 行:复位有效时,当前状态赋值为 IDLE。
  • 第 17 行:复位无效时,执行 else 分支。
  • 第 18 行:当前状态更新为下一状态。
  • 第 19 行:end 结束 always 块。

状态转移逻辑(以二进制 FSM 为例)

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

assign state_out = state;

endmodule

逐行说明

  • 第 1 行:组合逻辑 always 块,敏感列表为所有输入信号(自动推导)。
  • 第 2 行:默认保持当前状态(避免锁存器)。
  • 第 3 行:case 语句,根据当前状态决定下一状态。
  • 第 4 行:IDLE 状态下,若 start 有效则跳转到 S1,否则保持。
  • 第 5 行:S1 状态下无条件跳转到 S2。
  • 第 6 行:S2 状态下无条件跳转到 S3。
  • 第 7 行:S3 状态下无条件跳转到 IDLE。
  • 第 8 行:default 分支,覆盖未定义状态,回到 IDLE。
  • 第 9 行:endcase 结束 case 语句。
  • 第 10 行:end 结束 always 块。
  • 第 11 行:空行。
  • 第 12 行:将当前状态直接赋值给输出。
  • 第 13 行:空行。
  • 第 14 行:endmodule 结束模块。

时序约束文件 (top.xdc)

create_clock -period 10.000 [get_ports clk]
set_input_delay -clock [get_clocks clk] 2.0 [get_ports start]
set_output_delay -clock [get_clocks clk] 2.0 [get_ports state_out]

逐行说明

  • 第 1 行:创建时钟 clk,周期为 10 ns(对应 100 MHz)。
  • 第 2 行:设置输入延迟,start 端口相对于时钟上升沿延迟 2 ns。
  • 第 3 行:设置输出延迟,state_out 端口相对于时钟上升沿延迟 2 ns。

验证结果

运行仿真后,观察三个 FSM 的输出波形,应完全一致:在 start 有效后,状态依次从 IDLE → S1 → S2 → S3 → IDLE 循环。时序报告应显示所有路径建立时间裕量均大于 0.2 ns。功耗报告应显示格雷编码动态功耗最低,One-Hot 次之,二进制最高。资源占用方面,One-Hot 编码 LUT 数量约为二进制的 1.3~1.8 倍。

排障指南

  • 时序不满足:检查时钟约束是否正确;尝试降低时钟频率或优化组合逻辑深度。
  • 功能不正确:确认复位信号极性(低有效);检查状态转移条件是否写反。
  • 功耗异常:确认是否开启了功耗分析(Report Power);检查是否有未使用的逻辑被综合掉。
  • 资源占用差异不明显:确保三种 FSM 状态数相同(4 状态);检查综合选项是否优化了冗余逻辑。

扩展讨论

本指南以 4 状态 FSM 为例,实际设计中状态数可能更多(如 8、16 状态)。随着状态数增加,One-Hot 编码的资源开销会线性增长,但 Fmax 优势更明显;格雷编码在状态转移频繁的场景下动态功耗优势突出;二进制编码在资源受限时仍为首选。建议在项目早期进行多种编码的预综合对比,以选择最优方案。

参考

  • Xilinx UG901: Vivado Design Suite User Guide (Synthesis)
  • Xilinx UG906: Vivado Design Suite User Guide (Power Analysis)
  • IEEE Std 1364-2001: Verilog Hardware Description Language

附录

附录 A:完整测试平台代码(tb_fsm_top.v)可参考 Vivado 示例模板。附录 B:功耗对比表格模板(动态功耗、静态功耗、总功耗,单位 mW)。附录 C:资源对比表格模板(LUT、FF、Slice 数量)。

分类
技术分享
标签
FSMVerilog低功耗
浏览 24收藏 0赞 0评论 0
分享:

相关推荐

同频道 · 相近分类

暂无相关推荐

作者

FPGA小白查看主页

同分类阅读

文章

延伸阅读与实操

  • 文章 + 课程联动深度文章常对应体系课章节,可一键选课。
  • 学习产出可参考笔记与作业案例在学习产出广场持续更新。

探索全站