一直做 FPGA,综合对我来说就是"点一下 Run Synthesis 然后等"。最近想把数字前端这条流程过一遍,这是第一版笔记。

整体认识

我一直以为综合就是把 Verilog 翻译成门电路,一次性的动作。实际上它是一次三级降维加一连串取舍:源码先变成唯一确定的实例层级树,再抬升成与工艺无关的算子级网表,最后压进具体库里的标准单元或查找表。速度换面积、面积换速度的决策贯穿全程,而我能影响它的手段只有两个——RTL 怎么写,约束怎么写。

三个层次长什么样

RTL:      always @(posedge clk) sum <= a + b + cin;
通用网表:  REG4( ADD4(a, b, cin) )             // 算子级,与工艺无关
工艺网表:  ASIC 的 4 个 FA 标准单元 / FPGA 的 LUT6 加专用进位单元

同一个功能,只有最后一行可实现。综合器要保证这个降维过程功能等价,所以输出的网表得过一遍逻辑等价性检查(LEC),这是标准动作。

七个环节

1. 读入与解析

把源码读成语法树,同时判断写法是否落在可综合子集内。这步只看语法和基本语义,不关心电路长什么样,所以出的错基本都是写法问题:用了不可综合的构造、宏展开出错、filelist 顺序不对。

2. 精化展开

把参数化的设计变成唯一确定的实例层级树,parameter、generate、for、宏都在这一步求值。因为是按具体参数展开的,位宽截断、有符号混算、只在某个参数下才错的分支,往往到这一步才暴露。

3. 推断

把 always 和赋值语句翻译成算子:寄存器、算术单元、多路选择器、存储器、状态机。它不做意图理解,只做模式匹配,所以结果完全由写法决定——意外锁存器来自组合分支没写全,几行短 RTL 也可能推出一大块内存。

4. 逻辑优化

在与工艺无关的层面化简逻辑,顺手做架构级决策:布尔化简、删死逻辑、资源共享、状态机重编码、算术结构选型。它定下了面积和速度的基调,也是综合时间暴涨的主要来源。

5. 约束与库读入

把设计意图翻译成优化目标,时序图、时钟、例外路径、目标库都在这里建立。核心就一句话:没有约束的综合只在做面积最小化,时序完全不管;约束写松会假装通过,写紧就白白付出面积和功耗。

6. 工艺映射

把算子落到具体库单元上,算术尽量映射到专用硬核(进位链、DSP、块 RAM)。匹配是结构化搜索,能不能用上硬核既取决于库,也取决于 RTL 写法。

7. 时序驱动优化与输出

按约束对关键路径做重定时、信号复制、驱动能力调整,最后输出网表和三份报告。报告才是这一步真正的产物——读得懂 WNS、TNS 和关键路径,才知道自己的 RTL 贵在哪里。

FPGA 和 ASIC 的差异

维度FPGAASIC
目标资源固定的 LUT、FF、DSP、BRAM可选任意标准单元
综合边界综合、映射、打包常被串成一步综合与布局布线严格分离
约束来源器件和时钟基本自动必须手写完整 SDC
时序可见性实现后基本就是最终结果综合仅估算,后端才收敛

从 FPGA 转过来,要重新练的其实就是两件事:显式表达时序意图,以及在写 RTL 时就能预判最终结构。

待补

  • 用一个模块走完整流程,看每一步的中间产物长什么样
  • 写一份完整 SDC,验证删掉某条约束会怎样
  • 从关键路径报告追回到具体那几行 RTL