FPGA 进阶 42:FPGA RTL 质量检查——lint、警告治理与评审门禁
本文是
fpga/进阶层第 46 篇。检查对象来自:CDC 多时钟、复位策略、时序例外纪律;工程化落地依赖版本管理和 CI(专家层)。
本文要回答的问题
- 综合 warning 哪些必修、怎么治?
- CDC 静态检查怎么看、怎么算过?
- check_timing 看什么?
- 怎么把检查固化成团队门禁?
一、四道质量门禁

二、常见警告处理表
| 警告/问题 | 风险 | 处理 |
|---|---|---|
| Critical Warning(任意) | 未约束/IP/时序缺失 | 全部清零或逐条确认 |
| 位宽不匹配/截断 | 高位被斩、数据错 | 改位宽或显式 [n-1:0] 截位 |
| inferring latch | 锁存器、时序不可控 | if 补 else、case 补 default、变量全分支赋值 |
| multi-driven | 多驱动冲突 | 单一 always 驱动 |
| implicit net/悬空 | 拼错名导致信号丢失 | `default_nettype none、显式声明 |
| 敏感列表不全(仿真) | 仿真综合不一致 | @(*) 或 always_ff/always_comb |
| initial/# 延迟 | 不可综合行为 | testbench 专用,RTL 用复位 |
开源门禁:Verilator(verilator --lint-only -Wall)秒级反馈,适合 pre-commit。
三、CDC 检查
report_cdc(Vivado)或 SpyGlass/Questa CDC,每条跨域路径必须归类:
- 单 bit → 双 FF 同步器(工具识别为 safe);
- 多 bit → 异步 FIFO / Gray 指针 / 握手;
- 静态配置/测试 → 对应
set_clock_groups/set_false_path且注释。
不允许存在"未解释"项。跨域全部走标准 CDC 模块,报告自然干净。
四、check_timing 与时序完整性
- 无 unconstrained clock(对照时钟拓扑表);
- IO 端口 delay 约束完整或明确异步;
report_clock_interaction无意外 async/未约束;- 时序例外每条例外有依据(见时序例外篇)。
check_timing 不干净时,时序报告的"绿勾"可能只是漏查。
五、人工评审清单(节选)
- [ ] 复位统一:异步断言同步释放、每域独立;
- [ ] 跨域只走标准同步器/FIFO/握手,命名标注时钟域;
- [ ] 无组合环路、无寄存器分频(用 CE/MMCM);
- [ ] 状态机有 default 态、死态可恢复;
- [ ] FIFO 深度有计算依据;
- [ ] 参数化、无魔数(见复用篇);
- [ ] 新接口有自检 TB(见高级 TB)。
常见坑对照
| 坑 | 后果 | 正确做法 |
|---|---|---|
| warning 习惯了忽略 | 截断/悬空导致上板错 | 每警告必修或书面豁免 |
| critical warning 放过 | 时序/约束假象 | 零 critical |
| CDC 只靠仿真 | 随机亚稳 | report_cdc 清零 |
| check_timing 不看 | 漏分析的绿勾 | 时钟/IO 约束完整 |
| 质量靠人记得 | 时好时坏 | 脚本化进 CI |
相关与延伸
一句话总结
FPGA 质量四道门禁:lint(Verilator/工具,秒级拦语法和坏味道)→ 综合警告治理(critical warning 零容忍,位宽截断/锁存器推断/多驱动/隐式线网逐条修或书面豁免)→ CDC 静态检查(report_cdc/SpyGlass,每条跨域路径必须归到同步器/异步 FIFO/握手/静态豁免,零未解释项)→ check_timing(无未约束时钟/端口,否则时序绿勾是漏查)。原则:warning 要么修要么注释为什么可忽略,"一直有"不是理由;CDC 是结构问题仿真抓不到,静态检查是主力。固化方式:lint/综合/cdc/回归 TB 脚本化进 CI(critical>0、WNS<0、自检失败即拦提交),合并前过人工评审清单(复位/CDC/状态机/FIFO 深度/参数化)。