逻辑综合入门:RTL代码到门级网表的转换
各位同学,今天我们来聊聊逻辑综合。说实话,这是整个RTL到GDS流程里最让我觉得「有魔法感」的一步。你写的那段Verilog代码,经过综合工具一跑,就变成了一个个标准单元、连线、还有一堆时序信息。我第一次看到综合后的门级网表时,心里想的是:这玩意儿真能跑起来吗?
后来做多了才发现,逻辑综合其实没那么玄乎。说白了,就是把你的行为级描述,映射到工艺库提供的标准单元上。你写一个 assign c = a & b;,工具就会去找库里的一个两输入与门,把它放上去。但问题在于——你怎么让工具知道你想要的不是随便一个与门,而是某个特定驱动强度、特定延时、特定面积的与门?这就是约束要干的事。
核心要点:逻辑综合 = RTL翻译 + 逻辑优化 + 工艺映射。三步走,缺一不可。
综合工具介绍:Design Compiler
业界最主流的综合工具,毫无疑问是Synopsys的Design Compiler,简称DC。我入行那会儿用的还是DC 2004版,现在都2024了,工具界面变了不少,但核心命令和流程基本没变。你想想看,一个工具能活二十年还这么坚挺,说明它的设计哲学是对的。
DC的工作流程大致是这样的:
- 读入RTL:支持Verilog、VHDL、SystemVerilog。我个人习惯把所有RTL文件列在一个文件列表里,用
analyze+elaborate命令读入。这样方便管理,也方便增量编译。 - 设定库文件:需要指定目标库(target_library)、链接库(link_library)、符号库(symbol_library)。目标库就是你最终要映射到的那个工艺库,链接库是用于解析实例化模块的库。
- 施加约束:这是最关键的步骤。没有约束,DC就不知道你要什么。后面我会详细讲。
- 编译:运行
compile_ultra或compile命令。我建议用compile_ultra,它做了更多的优化,比如自动插入门控时钟、自动做retiming等。 - 输出网表:生成门级网表(.v)、时序报告(.rpt)、面积报告等。
小技巧:DC的脚本建议用Tcl写。我见过有人用GUI点点点,然后说「为什么每次结果不一样?」——因为GUI操作不可重复啊!写脚本,保存,下次直接跑,这才是工程化的做法。
综合约束:让工具听懂你的需求
约束是综合的灵魂。没有约束,DC会默认把所有路径都设成无限大,结果就是它随便给你一个面积最小、性能最差的实现。嗯,这显然不是我们想要的。
约束主要分几类:
| 约束类型 | 常用命令 | 说明 |
|---|---|---|
| 时钟约束 | create_clock |
定义时钟周期、占空比、波形 |
| 输入延时 | set_input_delay |
外部信号到达芯片内部的时间 |
| 输出延时 | set_output_delay |
内部信号到达外部器件的时间 |
| 时序例外 | set_false_path, set_multicycle_path |
告诉工具哪些路径不需要严格检查 |
| 面积约束 | set_max_area |
限制芯片面积,通常设为0让工具尽量优化 |
| 功耗约束 | set_max_dynamic_power, set_max_leakage_power |
低功耗设计时使用 |
举个例子,假设你的设计跑在100MHz,时钟周期就是10ns。你写:
create_clock -name clk -period 10 [get_ports clk]
set_input_delay -max 2 -clock clk [get_ports data_in]
set_output_delay -max 2 -clock clk [get_ports data_out]
这样DC就知道:输入信号在时钟沿之后2ns才稳定,输出信号需要在时钟沿之前2ns就准备好。留给内部逻辑的时间就是10 - 2 - 2 = 6ns。如果内部逻辑延时超过6ns,就会报时序违例。
注意:我曾经遇到过一个项目,前端工程师给的约束里把输入延时设成了0。结果综合出来的网表时序全绿,但后仿真怎么都过不了。后来发现是输入延时设得太乐观了,实际PCB走线有1.5ns的延时。从那以后,我每次都会跟PCB团队确认IO延时,再也不敢自己拍脑袋了。
综合策略:面积 vs 速度
DC提供了几种综合策略,你可以根据需求选择:
- 面积优先:使用
compile -map_effort low,工具会尽量复用逻辑,减少单元数量。适合成本敏感的设计。 - 速度优先:使用
compile_ultra -no_autoungroup,工具会尽量展平逻辑,减少路径级数。适合高性能设计。 - 平衡策略:默认设置,工具会在面积和速度之间找平衡点。我大部分项目都用这个,除非有特殊要求。
你可能会问:「那我怎么知道该选哪个?」我的经验是:先跑一次默认策略,看看时序和面积报告。如果时序有violation,就切到速度优先;如果面积超标,就切到面积优先。说白了,这是一个迭代调优的过程。
综合后的检查清单
综合跑完后,别急着往后端走。先检查这几项:
- 时序报告:看setup和hold有没有violation。如果有,先确认约束是否正确,再考虑修改RTL。
- 面积报告:看总面积是否在预算内。如果超标,看看是哪个模块占了大头。
- 功耗报告:如果设计有功耗要求,这一步不能省。
- 网表一致性:用formality做形式验证,确保综合后的网表功能跟RTL一致。这一步我从来不敢跳过——有一次综合工具出了bug,把一个加法器优化成了错误逻辑,幸好formality抓出来了。
一句话总结:逻辑综合不是「写完RTL扔给工具就完事」的。约束要写对,策略要选对,结果要查对。这三对做到了,综合这关就算过了。
好了,逻辑综合入门就讲到这里。记住,工具只是工具,真正决定芯片质量的,是你对约束的理解和对结果的把控。多跑几次,多看看报告,慢慢就有感觉了。