Quick Start
- 准备环境:安装 Vivado 2025.2 或更高版本,确保支持 SystemVerilog 与综合后仿真。
- 创建工程:新建 RTL 工程,选择器件
xc7a35tcsg324-1(Artix-7 系列)。 - 编写状态机 RTL:使用三段式状态机编码,状态编码采用 Gray 码或 One-hot 码。
- 添加约束:创建 XDC 文件,约束时钟周期为 10 ns(100 MHz),并设置 false_path 或 multicycle 路径(如适用)。
- 运行综合:执行 synthesis,观察综合报告中的状态机推断情况。
- 运行综合后仿真:使用 Vivado Simulator 运行综合后时序仿真(post-synth timing simulation)。
- 观察毛刺:在波形中检查状态机输出信号是否存在毛刺(glitch),尤其是组合逻辑输出。
- 消除毛刺:修改 RTL,将输出改为寄存器输出,或插入同步寄存器链;重新综合并仿真验证。
- 验收:毛刺消失,输出波形干净,满足时序约束。
前置条件与环境
| 项目 | 推荐值 | 说明 | 替代方案 |
|---|---|---|---|
| 器件/板卡 | Xilinx Artix-7 xc7a35tcsg324-1 | 典型 FPGA,支持综合后仿真 | 其他 7 系列或 UltraScale 器件 |
| EDA 版本 | Vivado 2025.2 | 支持 SystemVerilog 与高级综合后仿真 | Vivado 2024.x 或 Quartus Prime 24.x |
| 仿真器 | Vivado Simulator (xsim) | 内建,支持 SDF 反标 | ModelSim/QuestaSim 2024.3 |
| 时钟/复位 | 100 MHz 时钟,异步低电平复位 | 典型系统时钟,复位用于初始化状态机 | 50 MHz 或 200 MHz 时钟 |
| 接口依赖 | 无外部接口,纯内部状态机 | 便于聚焦毛刺问题 | 可添加 GPIO 输出观察 |
| 约束文件 | XDC 文件:时钟周期 10 ns,输入延迟 2 ns | 必须约束时钟以进行时序仿真 | SDC 格式(Quartus) |
目标与验收标准
- 功能点:状态机正确完成状态跳转,输出符合预期逻辑。
- 性能指标:综合后时序仿真中,所有输出信号无毛刺(glitch)持续时间超过 100 ps。
- 资源/Fmax:综合后 Fmax ≥ 100 MHz,资源占用在合理范围(LUT ≤ 50,FF ≤ 30)。
- 验收方式:在 Vivado 波形窗口中,放大观察输出信号跳变沿,无多余脉冲;日志中无 setup/hold 违例。
实施步骤
工程结构与 RTL 编写
- 创建工程目录:
src/(RTL 文件)、sim/(仿真脚本)、constr/(约束文件)。 - 编写状态机 RTL:使用三段式结构(状态寄存器、次态组合逻辑、输出组合逻辑)。
- 状态编码:使用 Gray 码(如 2’b00, 2’b01, 2’b11, 2’b10)以减少相邻跳变时的毛刺风险。
- 输出策略:所有输出信号采用寄存器输出(在时钟沿赋值),避免组合逻辑直接驱动输出。
// fsm_gray.v - 三段式状态机,Gray 编码,寄存器输出
module fsm_gray (
input wire clk,
input wire rst_n,
input wire start,
output reg [1:0] state_out // 寄存器输出
);
// 状态编码(Gray)
localparam [1:0] IDLE = 2'b00,
S1 = 2'b01,
S2 = 2'b11,
S3 = 2'b10;
reg [1:0] state_reg, state_next;
// 状态寄存器
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
state_reg <= IDLE;
else
state_reg <= state_next;
end
// 次态逻辑
always @(*) begin
state_next = state_reg; // 默认保持
case (state_reg)
IDLE: if (start) state_next = S1;
S1: state_next = S2;
S2: state_next = S3;
S3: state_next = IDLE;
default: state_next = IDLE;
endcase
end
// 寄存器输出
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
state_out <= IDLE;
else
state_out <= state_reg;
end
endmodule逐行说明
- 第 1 行:注释,说明文件功能:三段式状态机,Gray 编码,寄存器输出。
- 第 2 行:模块声明,模块名为
fsm_gray。 - 第 3 行:输入端口
clk,类型 wire,用于驱动状态机时钟。 - 第 4 行:输入端口
rst_n,类型 wire,异步低电平复位。 - 第 5 行:输入端口
start,类型 wire,启动信号。 - 第 6 行:输出端口
state_out,类型 reg [1:0],寄存器输出,用于观察状态。 - 第 7 行:模块声明结束。
- 第 9 行:注释,说明状态编码采用 Gray 码。
- 第 10-13 行:使用
localparam定义四个状态:IDLE (2’b00)、S1 (2’b01)、S2 (2’b11)、S3 (2’b10),相邻状态间仅一位变化。 - 第 15 行:声明
state_reg和state_next,均为 reg [1:0],分别用于当前状态寄存器和次态组合逻辑。 - 第 17 行:注释,开始状态寄存器逻辑。
- 第 18 行:
always块,敏感列表为posedge clk或negedge rst_n,实现异步复位。 - 第 19 行:条件判断,若
rst_n为低电平(复位有效),则执行复位。 - 第 20 行:复位时,
state_reg赋值为IDLE(2’b00)。 - 第 21 行:否则(复位无效),执行正常赋值。
- 第 22 行:时钟上升沿时,
state_reg更新为state_next。 - 第 23 行:状态寄存器
always块结束。 - 第 25 行:注释,开始次态组合逻辑。
- 第 26 行:
always块,敏感列表为*(所有信号),组合逻辑。 - 第 27 行:默认将
state_next赋值为state_reg,避免锁存器。 - 第 28 行:
case语句,根据state_reg决定次态。 - 第 29 行:当状态为
IDLE时,若start为高,则次态为S1,否则保持。 - 第 30 行:当状态为
S1时,次态无条件为S2。 - 第 31 行:当状态为
S2时,次态无条件为S3。 - 第 32 行:当状态为
S3时,次态无条件为IDLE。 - 第 33 行:
default分支,覆盖未定义状态,次态为IDLE,增强安全性。 - 第 34 行:
case结束。 - 第 35 行:次态逻辑
always块结束。 - 第 37 行:注释,开始寄存器输出逻辑。
- 第 38 行:
always块,敏感列表为posedge clk或negedge rst_n,实现同步输出。 - 第 39 行:条件判断,若复位有效,则执行复位。
- 第 40 行:复位时,
state_out赋值为IDLE(2’b00)。 - 第 41 行:否则(复位无效),执行正常赋值。
- 第 42 行:时钟上升沿时,
state_out更新为state_reg,实现寄存器输出。 - 第 43 行:输出
always块结束。 - 第 45 行:
endmodule,模块定义结束。
仿真脚本与运行
- 编写 testbench(如
tb_fsm_gray.v),实例化 fsm_gray,提供时钟和复位激励。 - 在 Vivado 中设置综合后仿真:
Tools → Simulation → Run Post-Synthesis Timing Simulation。 - 观察波形:放大输出信号跳变沿,检查是否存在多余脉冲(毛刺)。
毛刺消除机制分析
原因分析:组合逻辑输出毛刺的根本原因是路径延迟不匹配。在状态机中,次态组合逻辑的输出直接驱动外部信号时,由于不同路径的延迟差异,会导致短暂的错误电平(毛刺)。Gray 编码虽能减少相邻状态跳变时的位变化数量,但无法消除组合逻辑固有的延迟竞争。
落地路径:将输出改为寄存器输出(即在时钟沿赋值),利用触发器的同步特性,将组合逻辑的毛刺“屏蔽”在时钟采样窗口之外。具体做法是:在状态机中增加一个寄存器输出级,如上述 RTL 中的 state_out,在时钟上升沿锁存 state_reg 的值。
风险边界:寄存器输出会增加一个时钟周期的延迟,对于需要即时响应的应用(如高速握手协议),需评估是否可接受。此外,若输出信号本身需要组合逻辑快速反馈(如用于下一级组合逻辑的输入),则寄存器输出可能破坏时序关系,此时应改用双寄存器同步链或调整设计架构。
验证结果
- 运行综合后时序仿真,在波形窗口中放大输出信号
state_out的跳变沿,确认无多余脉冲。 - 检查 Vivado 日志,无 setup/hold 违例报告。
- 资源报告:LUT 占用 ≤ 50,FF 占用 ≤ 30,Fmax ≥ 100 MHz。
排障指南
- 毛刺仍存在:检查输出是否为寄存器输出;确认仿真模式为时序仿真(post-synth timing),而非功能仿真。
- 时序违例:检查时钟约束是否正确,尝试降低时钟频率或调整综合策略(如
-retiming)。 - 状态机推断失败:查看综合报告中的 FSM 部分,确认状态编码是否被正确识别;避免在 case 中使用
unique或priority关键字导致误判。
扩展实践
- 尝试 One-hot 编码(如 4’b0001, 4’b0010, 4’b0100, 4’b1000),观察资源占用与毛刺情况。
- 在输出端添加双寄存器同步链(两个级联的 D 触发器),进一步降低亚稳态风险。
- 使用 Vivado 的
report_glitch命令(如适用)自动检测毛刺。
参考文档
- Xilinx UG901: Vivado Design Suite User Guide: Synthesis
- Xilinx UG900: Vivado Design Suite User Guide: Logic Simulation
- IEEE Std 1364-2005: Verilog Hardware Description Language
附录:完整 RTL 与 Testbench 示例
完整项目文件(包括 testbench 和 XDC 约束)可从配套资源获取,或参考以下模板自行构建。

评论 0