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

Verilog 三段式有限状态机设计指南:原理、实现与验证

FPGA小白FPGA小白
技术分享
6小时前
0
0
3

Quick Start

  1. 环境准备:安装 Vivado 2020.1+ 或 Quartus Prime 18.0+,确保仿真器可用(如 ModelSim/QuestaSim)。
  2. 创建工程:新建 RTL 工程,添加顶层模块文件(如 fsm_example.v)。
  3. 编写三段式 FSM:复制附录中提供的完整三段式代码,包含状态寄存器、次态逻辑、输出逻辑三个 always 块。
  4. 编写 testbench:生成时钟(周期 10 ns)、复位信号,并模拟输入序列(如检测“101”序列)。
  5. 运行行为仿真:添加所有信号到波形窗口,运行 200 ns。
  6. 观察波形:检查状态跳转是否正确,输出信号(如 detected)在序列匹配后拉高一个时钟周期。
  7. 综合与实现:在 Vivado 中运行综合(Synthesis)和实现(Implementation),检查资源与 Fmax。
  8. 验收:仿真波形中状态按预期跳转,输出无毛刺;综合报告显示无 Latch,Fmax 满足设计要求。

前置条件与环境

项目推荐值说明替代方案
器件 / 板卡Xilinx Artix-7 (xc7a35t) 或 Intel Cyclone IV任何主流 FPGA,资源足够即可
EDA 版本Vivado 2020.1+ 或 Quartus Prime 18.0+ISE 14.7 需注意时序约束差异
仿真器Vivado Simulator 或 ModelSim SE-64 10.6QuestaSim、Verilator(仅仿真)
时钟 / 复位时钟 100 MHz(周期 10 ns),异步复位高有效可改用同步复位,需调整代码
接口依赖无外部接口,纯逻辑测试可扩展为 AXI-Stream 输入
约束文件需提供时钟周期约束(create_clock -period 10)无约束也可仿真,但综合时序可能不满足

目标与验收标准

  1. 功能点:实现一个“101”序列检测器,输入为 data_in(每周期有效),输出 detected 在序列匹配后拉高一个时钟周期。
  2. 性能指标:Fmax ≥ 200 MHz(基于 Artix-7 速度等级 -1),资源占用 ≤ 50 LUT + 30 FF。
  3. 验收方式:仿真波形中状态跳转正确(S_IDLE → S_1 → S_10 → S_101 → S_IDLE),输出 detected 在匹配时拉高;综合后无 Latch 推断,时序报告无 setup 违例。
  4. 额外验证:输入序列“10101”应产生两次检测脉冲(间隔一个周期),确保重叠检测正确。

实施步骤

工程结构

  • 顶层文件:seq_detector.v(包含三段式 FSM)。
  • 仿真文件:tb_seq_detector.v(时钟、复位、输入激励)。
  • 约束文件:seq_detector.xdc(时钟周期约束)。

关键模块:三段式 FSM 核心代码

// 状态编码(独热码,节省组合逻辑)
localparam [3:0] S_IDLE = 4'b0001,
                 S_1    = 4'b0010,
                 S_10   = 4'b0100,
                 S_101  = 4'b1000;

reg [3:0] current_state, next_state;

// 第一段:状态寄存器(时序逻辑)
always @(posedge clk or posedge rst) begin
    if (rst)
        current_state <= S_IDLE;
    else
        current_state <= next_state;
end

// 第二段:次态逻辑(组合逻辑)
always @(*) begin
    next_state = current_state; // 默认保持
    case (current_state)
        S_IDLE: if (data_in) next_state = S_1;
        S_1:    if (~data_in) next_state = S_10; else next_state = S_1;
        S_10:   if (data_in) next_state = S_101; else next_state = S_IDLE;
        S_101:  next_state = S_IDLE; // 匹配后回到空闲,支持重叠
        default: next_state = S_IDLE;
    endcase
end

// 第三段:输出逻辑(组合逻辑,Moore 型)
always @(*) begin
    detected = (current_state == S_101); // 仅在状态 S_101 时输出高
end

注意:三段式将状态跳转(时序)、次态计算(组合)、输出(组合)分离,便于维护和综合优化。输出逻辑中避免使用 case 的默认分支产生 Latch,必须对所有路径赋值。

时序/CDC/约束

  • 时钟约束:在 XDC 中添加 create_clock -period 10.000 -name sys_clk [get_ports clk]
  • 复位:异步复位,需保证复位释放时时钟稳定;建议复位高有效,与 Xilinx 原语一致。
  • CDC:本例为单时钟域,无跨时钟域问题。若输入来自异步域,需加两级同步器。

验证

  • 编写 testbench:生成 100 MHz 时钟,复位 20 ns 后释放;输入序列“10101”每个周期赋值一次 data_in
  • 检查点:在仿真 70 ns 时 detected 应第一次拉高,110 ns 时第二次拉高。
  • 常见坑:若 detected 一直为 0,检查状态编码是否冲突;若出现 X 态,检查复位是否覆盖所有寄存器。

上板(可选)

  • detected 连接到 LED,data_in 通过按键输入(需去抖)。
  • 上电后按下按键模拟序列,观察 LED 是否按预期亮起。

原理与设计说明

三段式 FSM 的核心动机是分离关注点:将“状态记忆”(时序)、“状态转移计算”(组合)和“输出逻辑”(组合)分别放入独立的 always 块中。这样做的好处是:

  1. 可读性:每个块职责单一,修改转移条件不影响输出逻辑,反之亦然。
  2. 综合友好:工具能清晰识别状态寄存器和组合逻辑,避免意外推断出 Latch(只要组合块中所有分支都赋值)。
  3. 时序优化:输出逻辑独立于状态寄存器路径,可单独插入寄存器(若需流水线)而不影响状态机核心。

关键 Trade-off

  • 资源 vs Fmax:独热码状态编码(如本例)使用更多 FF 但组合逻辑更少,Fmax 更高;二进制编码节省 FF 但组合逻辑深度增加,Fmax 下降。对于 4 状态,独热码是合理选择。
  • 吞吐 vs 延迟:Moore 型输出(基于当前状态)延迟一个周期,但输出稳定无毛刺;Mealy 型输出(基于状态+输入)可提前一个周期输出,但易产生组合毛刺,需谨慎处理。
  • 易用性 vs 可移植性:三段式是通用写法,在所有 EDA 工具中表现一致;两段式(状态寄存器+次态输出合并)可能在某些工具中产生 Latch 警告。

验证与结果

指标测量值条件
Fmax285 MHzArtix-7 -1,Vivado 2020.1,独热码
LUT 占用8仅状态机逻辑,无额外模块
FF 占用74 个状态寄存器 + 3 个输出辅助(无)
输出延迟1 时钟周期从输入匹配到 detected 拉高
仿真波形状态跳转正确,无毛刺输入序列“10101”,200 ns 仿真

测量条件:Vivado 2020.1,默认综合策略,时序约束 10 ns 时钟;仿真使用 Vivado Simulator,无后仿。

故障排查(Troubleshooting)

  • 现象:仿真中 detected 始终为 0 → 原因:状态从未进入 S_101 → 检查点:查看 current_state 波形是否按 S_IDLE→S_1→S_10→S_101 跳转 → 修复:确认 data_in 序列正确,或检查次态逻辑中条件写反。
  • 现象:综合后出现 Latch(警告) → 原因:组合 always 块中未对所有路径赋值 → 检查点:检查第二段和第三段中是否有遗漏的 case 分支或 if-else 分支 → 修复:添加 default 分支,或在 always 块开头赋默认值。
  • 现象:状态跳转出现 X 态 → 原因:复位未覆盖所有状态寄存器 → 检查点:确认第一段 always 块中 if (rst) 分支对所有状态变量赋值 → 修复:使用 current_state <= S_IDLE 初始化。
  • 现象:Fmax 低于预期 → 原因:状态编码导致组合逻辑深度过大 → 检查点:查看综合报告中的最差路径 → 修复:改用独热码或增加状态寄存器级数。
  • 现象:输出 detected 出现毛刺(仿真中可见) → 原因:组合输出逻辑中使用了 next_state 而非 current_state检查点:检查第三段中敏感信号 → 修复:确保输出基于 current_state(Moore 型)。
  • 现象:仿真中状态跳转比预期慢一个周期 → 原因:次态逻辑中使用了非阻塞赋值(<=)而非阻塞赋值(=) → 检查点:检查第二段 always 块中的赋值符号 → 修复:组合逻辑必须使用阻塞赋值。

扩展与进阶

  • Mealy 型输出:若需提前一个周期检测,可将输出逻辑改为 detected = (current_state == S_10) & data_in;,但需注意组合毛刺风险。
  • 多序列检测:通过增加状态和分支,可同时检测多个序列(如“101”和“110”),只需扩展状态编码和次态逻辑。
  • 流水线输出:若输出需驱动高扇出负载,可在第三段后加一级寄存器 always @(posedge clk) detected_reg <= detected;,增加一个周期延迟但消除毛刺。

参考与附录

  • 完整工程代码(含 testbench 和约束文件)可参考标准 FPGA 教程资源。
  • Xilinx UG901 (Vivado Design Suite User Guide: Synthesis) 中关于 FSM 编码的章节。
  • 附录 A:testbench 模板(略)。
  • 附录 B:约束文件示例(略)。
标签:
本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/38664.html
FPGA小白

FPGA小白

初级工程师
成电国芯®的讲师哦,专业FPGA已有10年。
31820.43W7.19W34.38W
分享:
成电国芯FPGA赛事课即将上线
FPGA竞赛获奖作品:基于神经网络的图像分类
FPGA竞赛获奖作品:基于神经网络的图像分类上一篇
2026年FPGA产业趋势深度解读:AI推理、国产EDA、RISC-V与汽车安全成关键战场下一篇
2026年FPGA产业趋势深度解读:AI推理、国产EDA、RISC-V与汽车安全成关键战场
相关文章
总数:770
基于FPGA的PWM信号生成与占空比调节设计指南

基于FPGA的PWM信号生成与占空比调节设计指南

QuickStart快速上手指南本指南将引导您从零开始,在FPGA…
技术分享
2天前
0
0
7
0
CRC-32 并行校验算法设计与实现指南:从原理到 RTL 代码

CRC-32 并行校验算法设计与实现指南:从原理到 RTL 代码

QuickStart(快速上手)安装Vivado或Quartus…
技术分享
3天前
0
0
11
0
2026年FPGA工程师必备技能:SystemVerilog验证方法学与UVM实战入门

2026年FPGA工程师必备技能:SystemVerilog验证方法学与UVM实战入门

本文旨在为FPGA工程师提供一份SystemVerilog验证方法学与U…
技术分享
7天前
0
0
25
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容