逻辑综合入门:RTL代码到门级网表的魔法

各位同学,欢迎来到第二章。上一章我们聊了芯片设计的整体流程,今天咱们来点实在的——逻辑综合。

说实话,我刚入行那会儿,觉得逻辑综合就是个黑盒子。RTL代码写进去,门级网表吐出来,中间发生了什么?完全不知道。后来踩了不少坑才明白,这玩意儿其实没那么玄乎。

逻辑综合,说白了就是把我们写的硬件描述语言(Verilog/VHDL)翻译成芯片厂能用的标准单元库里的门级电路。你想想看,我们写的是 if (a & b) c = 1;,但芯片里没有if语句,只有与门、或门、非门、触发器这些东西。综合工具就是做这个翻译工作的。

综合的三个阶段

综合工具(比如Synopsys的Design Compiler,简称DC)做这件事,一般分三步走:

  1. 转译(Translation):把RTL代码读进来,转成工具内部通用的布尔表达式。这一步很快,基本不花时间。
  2. 逻辑优化(Logic Optimization):对布尔表达式做化简。比如 a + a*b 可以化简成 a,这一步能省不少面积。
  3. 映射(Mapping):把优化后的逻辑表达式,映射到目标工艺库里的标准单元上。比如用两输入的与非门实现某个逻辑。

核心要点:综合不是简单的翻译,而是带着约束条件的优化过程。你给工具的约束越清晰,它产出的网表质量就越高。

我画了一张图,帮你理解这个过程:

转译 RTL → 布尔表达式 读入代码,生成内部表示 逻辑优化 布尔化简 + 重定时 面积/速度权衡 映射 布尔式 → 标准单元 匹配工艺库 输入:RTL代码 输出:门级网表 约束条件驱动 时序约束 · 面积约束 · 功耗约束

DC的基本用法

Design Compiler是Synopsys家的旗舰产品,也是业界用得最多的综合工具。我个人的习惯是,先用脚本跑一遍,再打开GUI看看关键路径的时序报告。

一个典型的DC综合脚本长这样:

# 读入设计
read_verilog {top.v sub_module.v}
current_design top

# 链接工艺库
link

# 设置约束
create_clock -period 10 [get_ports clk]
set_input_delay 2 -clock clk [all_inputs]
set_output_delay 2 -clock clk [all_outputs]

# 综合
compile_ultra

# 输出结果
write -format verilog -output top_synth.v
write_sdc top_synth.sdc
report_timing > timing.rpt
report_area > area.rpt

这段脚本看着简单,但每个命令背后都有讲究。我挑几个重点说说:

  • create_clock -period 10:时钟周期设10ns,意味着目标频率是100MHz。设多少合适?得看你的设计复杂度和工艺节点。
  • compile_ultra:这是DC的优化命令,比老版的compile效果更好。我在项目中遇到过,同样的RTL,用compile_ultra比compile时序能好10%~20%。
  • write_sdc:输出时序约束文件,给后端布局布线用。这一步很多人会忘,但忘了的话后端同事会来找你喝茶的。

小技巧:跑综合之前,先跑一下check_design。这个命令能检查出RTL里的一些低级错误,比如悬空端口、多驱动之类的问题。我每次跑综合前必做这一步,能省不少debug时间。

时序约束初探

时序约束,说白了就是告诉综合工具:我的芯片要在多快的频率下工作,输入信号什么时候到,输出信号什么时候要准备好。

最基本的几个约束:

约束类型 命令示例 说明
时钟定义 create_clock -period 10 [get_ports clk] 定义时钟周期和端口
输入延迟 set_input_delay 2 -clock clk [all_inputs] 外部信号到达芯片输入端的延迟
输出延迟 set_output_delay 2 -clock clk [all_outputs] 芯片输出到外部器件需要的建立时间
伪路径 set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b] 告诉工具某些路径不需要分析时序

这里有个容易踩的坑——输入延迟和输出延迟。我曾经在一个项目里,把输入延迟设得太小,结果综合出来的网表面积特别大。后来才发现,输入延迟设小了,工具以为留给内部逻辑的时间很多,就拼命优化速度,结果面积爆了。

避坑指南:我曾经因为忘了设set_clock_uncertainty,导致芯片流片回来跑不到目标频率。时钟不确定性(clock uncertainty)是用来模拟时钟抖动和时钟偏斜的,一般设周期5%~10%。这个值设太小,时序可能hold不住;设太大,又过度约束导致面积变大。

综合后的检查

综合跑完,别急着下班。先看看报告:

  • 时序报告:看最差路径的slack是多少。正数说明时序满足,负数说明有问题。
  • 面积报告:看看用了多少门,有没有超出预算。
  • 扇出报告:高扇出的信号(比如复位信号)可能导致时序问题。

嗯,这里要注意,综合后的时序报告只是预估,实际走线后的时序可能会有变化。所以一般会留10%~20%的余量。

好了,这一章的内容就到这儿。逻辑综合是连接前端设计和后端实现的桥梁,掌握了它,你就能理解为什么同样的RTL代码,换了个工艺库或者改了个约束,结果会差那么多。

下一章我们会聊到布局规划,看看门级网表是怎么变成芯片上的物理位置的。

可可精品资料库