2、RTL综合基础:从代码到网表的旅程
各位同学,今天我们聊聊RTL综合。说白了,就是把我们写的Verilog代码,变成芯片能用的门级网表。这个过程听起来简单,但里面的门道可不少。我做了十几年芯片,见过太多因为综合没做好而翻车的项目。
嗯,先给大家一个整体框架。RTL综合就像把建筑设计图变成实际施工图。你写的代码是设计图,综合工具就是施工队,工艺库就是建材市场。这三者缺一不可。
2.1 RTL代码到网表的映射过程
综合工具拿到你的Verilog代码后,会做三件事:读代码、做优化、出网表。我习惯把这三步比作「翻译-润色-定稿」。
举个例子,你写了个 assign y = a & b | c & d;。工具先把它翻译成内部的数据结构,然后看看能不能化简,最后从工艺库里挑出最合适的门来实现。
核心要点:映射过程不是简单的「代码转门」,而是带着约束条件做优化。面积、速度、功耗,这三者你得告诉工具哪个更重要。
我在项目中遇到过一件事:有个同事写了个很复杂的组合逻辑,综合出来面积特别大。后来我让他改成两级流水线,面积直接砍了一半。你想想看,同样的功能,不同的写法,综合结果天差地别。
2.2 逻辑综合的三大阶段
阶段一:转换(Translation)
这个阶段,工具把你的RTL代码转成内部通用的中间表示。我管它叫「GTECH网表」——就是跟工艺无关的、由基本逻辑门组成的网表。
举个例子:
// 你写的RTL
always @(posedge clk) begin
if (rst)
q <= 0;
else if (en)
q <= d;
end
工具会把它转成:一个D触发器 + 一个二选一MUX + 一些控制逻辑。这时候还没考虑用哪个工艺库的单元,只是逻辑上的等价转换。
我的经验:转换阶段基本不会出问题,除非你的代码有语法错误或者不可综合的结构。我建议在写RTL时就养成好习惯——只用可综合的语法子集。
阶段二:逻辑优化(Logic Optimization)
这是综合最核心的阶段。说白了,就是让电路更小、更快、更省电。
优化分两种:
- 与工艺无关的优化:布尔代数化简、资源共享、常数传播。比如
a & a直接变成a,a & 1变成a。 - 与工艺相关的优化:根据工艺库的单元特性,调整逻辑结构。比如某些工艺库有专门的AOI(与或非)门,工具会优先用。
我记得有一次,一个模块的时序总是不满足。我打开综合报告一看,发现工具把一条关键路径优化成了5级逻辑。后来我加了 // synthesis keep 注释,强制工具保留某些结构,时序才过了。
避坑指南:我曾经因为过度依赖工具的自动优化,导致一个模块的功耗超标。后来发现工具为了追求速度,把很多信号都复制了。记住:工具不是万能的,你得学会看综合报告。
阶段三:门级映射(Gate-Level Mapping)
这个阶段,工具从工艺库里挑出具体的门单元,来实现优化后的逻辑。每个工艺库都有几百甚至上千种单元:不同驱动能力的反相器、不同扇入的与门、各种复杂的复合门...
工具会算一笔账:用大驱动单元,速度快但面积大、功耗高;用小驱动单元,面积小但速度慢。怎么选?看你的约束。
| 约束优先级 | 工具行为 | 典型场景 |
|---|---|---|
| 速度优先 | 选大驱动单元,逻辑深度浅 | 关键路径、高频模块 |
| 面积优先 | 选小驱动单元,共享逻辑 | 低成本芯片、非关键路径 |
| 功耗优先 | 选低功耗单元,关断时钟 | 物联网、可穿戴设备 |
2.3 综合库的概念
综合库,就是工艺厂提供的「零件手册」。里面记录了每个标准单元的:
- 逻辑功能(比如这是个2输入与非门)
- 时序参数(上升时间、下降时间、传播延迟)
- 功耗参数(静态功耗、动态功耗)
- 面积信息
- 输入负载、输出驱动能力
嗯,这里要注意:不同工艺厂的库差别很大。我用过台积电的库,也用过中芯国际的库,同样的RTL代码,综合出来的网表大小能差30%。
关键点:综合库的准确性直接决定了综合结果的可信度。我建议在项目初期就拿到最终版的库文件,别用beta版凑合。否则后期时序收敛会让你欲哭无泪。
举个例子,一个简单的反相器在库里的描述大概长这样:
cell (INVX1) {
area : 1.0;
pin (A) { direction : input; capacitance : 0.5; }
pin (Y) {
direction : output;
function : "(!A)";
timing () {
related_pin : "A";
rise_delay (template) { values (0.1, 0.2, 0.3); }
fall_delay (template) { values (0.1, 0.2, 0.3); }
}
}
}
你看,每个单元的延迟不是固定值,而是跟输入转换时间和输出负载相关的表格。工具在映射时会查这个表,算出最精确的延迟。
我个人习惯在综合前先看一眼库的摘要:最快的单元是什么?最慢的单元是什么?驱动能力范围是多少?心里有个底,后面看综合报告才不会懵。
好了,RTL综合的基础就聊到这儿。记住:写代码时想着综合,综合时想着物理实现。这三者是一体的,别割裂开来看。
最后分享一个技巧:每次综合完,一定要看 report_timing 和 report_area。别只看有没有报错,要分析为什么某些路径慢了,为什么面积比预期大。这些信息会告诉你下一版代码该怎么改。
可可精品资料库