🏭 第5课:从 Verilog 代码到 GDS 版图——芯片是怎么"造"出来的
写完 RTL 代码只是第一步——真正的挑战是把代码变成能在硅片上"刻"出来的物理版图。rv_control 完成了从 RTL 到 20MB GDS 文件的完整流程。
理解 ASIC 物理设计的 6 个阶段:综合→布图→布局→时钟树→布线→收尾。知道每一阶段是做什么的,理解 200MHz 是怎么达到的。
一、从代码到硅片:全流程概览
RTL-to-GDS 六阶段流水线
Verilog代码
~2400行"] -->|Yosys| SYN["🔧 综合 Synthesis
代码→门级网表
8,215个逻辑门"] SYN -->|OpenROAD| FP["📐 布图 Floorplan
确定芯片大小
520×520μm"] FP -->|OpenROAD| PLACE["📍 布局 Placement
摆放23,559个单元
密度0.58"] PLACE -->|OpenROAD| CTS["🕐 时钟树 CTS
插入422个时钟Buffer
skew=0.18ns"] CTS -->|OpenROAD| ROUTE["🔗 布线 Route
连接292mm金属线
151,281个通孔
DRC=0"] ROUTE -->|OpenROAD| FINAL["✅ 收尾 Finish
GDSII(20MB)+SPEF(24MB)
Setup/Hold clean"] style RTL fill:#3987e5,color:#fff style SYN fill:#199e70,color:#fff style FP fill:#c98500,color:#000 style PLACE fill:#e66767,color:#fff style CTS fill:#9085e9,color:#fff style ROUTE fill:#d55181,color:#fff style FINAL fill:#0ca30c,color:#fff
二、第1步:综合(Synthesis)—— "翻译"
Verilog 代码是给人看的(`always @(posedge clk)`),芯片需要的是逻辑门(AND、OR、NOT、Flip-Flop)。综合就是做这个翻译工作:
if (a & b) out = 1; else out = 0; → 翻译成 → 一个 AND 门 + 一个 MUX
rv_control 用了 Yosys(开源综合工具)做这件事,结果:8,215 个标准单元(6,485 个组合逻辑 + 1,727 个触发器)。
三、第2步:布图(Floorplan)—— "划地盘"
综合完后你有一堆逻辑门,但它们堆在一起,没有物理位置。布图就是给芯片划地盘:
- 芯片总面积:520×520 µm(约 0.27 mm²)
- 核心区域:510×510 µm
- 外围留给 I/O 焊盘(35 个引脚)
- SRAM 宏单元放在中间偏左
rv_control 初始设计用了 1500×1500µm 的大片区域,后来缩小到 520×520µm——因为 23K 单元根本用不了那么大地方。小面积意味着更短的走线、更低的功耗。
四、第3步:布局(Placement)—— "摆家具"
有了地盘,现在要把 23,559 个标准单元一个一个摆到正确的位置。目标:让有关联的门尽量靠近,减少走线长度。
这就像搬新家摆家具——沙发和茶几应该放一起(经常同时用),书柜可以放远一点。
rv_control 用了 density=0.58 的密度(58% 的面积放标准单元,42% 留给走线),最终实际利用率 16.47%——故意留了很多空余空间给布线。
五、第4步:时钟树综合(CTS)—— "同步心跳"
这是最关键也最容易出错的一步。
芯片里 23,559 个单元中,1,727 个是触发器——它们都需要在同一个时钟边沿同时更新。但时钟信号从芯片一角传到另一角需要时间(物理延迟不可避免),如果不对齐,就会出现"有的触发器先收到时钟、有的后收到"——这就是时钟偏移(clock skew)。
时钟树 —— 像树枝一样分发时钟
CTS 插入 422 个时钟 Buffer + 93 个时钟反相器,确保时钟信号到达所有触发器的时间差控制在 0.18ns 以内。
六、第5步:布线(Route)—— "铺路"
单元都摆好了,现在要用金属线把它们连起来。芯片有多层金属(像多层高架桥),低层走短线,高层走长线。
rv_control 的布线结果:
DRC(Design Rule Check)是制造规则检查——金属线不能太近(会短路)、不能太细(会断)。rv_control 的 DRC=0 说明所有线都符合 45nm 工艺的制造规则。
七、第6步:收尾(Finish)—— "交卷"
布线完成后还要做几件事才能"交卷":
- 寄生参数提取(SPEF):计算每根线的电阻和电容(线越长电阻越大)
- 静态时序分析(STA):用提取的参数重新算一遍时序
- 金属填充:在空区域填充虚拟金属(保证制造均匀性)
- 导出 GDSII:最终版图文件,送给代工厂制造
八、200MHz 怎么做到的?—— 工程实战技巧
从最初的 50MHz 目标到最终实现 200MHz,中间做了大量工程优化:
频率提升的关键技巧
1500→520μm
缩短走线=减少延迟"] A --> C["2. Hold margin后置
CTS不加Hold margin
Route阶段加5ps
避免过量Buffer"] A --> D["3. 异步False Path
uart_rx/gpio设为false path
不需要收敛时序"] A --> E["4. SRAM mock/shrink
避免黑盒阻塞流程
让PD全流程跑通"] A --> F["5. Max cap放宽
set_max_cap 20.0
364 violations剩余"] B & C & D & E & F --> G["✅ 200MHz闭合!
Setup/Hold/DRC=0"] style A fill:#3987e5,color:#fff style G fill:#0ca30c,color:#fff
不到 1 皮秒(1ps = 万亿分之一秒)——这非常临界。换一个 OpenROAD 版本、换一个随机种子,可能 hold 就会失败。真正的 tapeout 前需要留更大余量(至少 10-20ps)。
九、交付物:可以真实验证的 GDS
最终交付包含完整的 SHA256 校验,任何人都可以验证:
| 文件 | 大小 | 用途 |
|---|---|---|
6_final.gds | 20.5 MB | GDSII版图(KLayout可打开) |
6_final.def | 21.2 MB | 设计交换格式(单元位置+连线) |
6_final.v | 2.4 MB | 门级网表(综合后的Verilog) |
6_final.spef | 24.2 MB | 寄生参数(电阻+电容) |