从 HDL 到裸片
一次把 Verilog 模块塞进 7 nm SoC 的真实翻车笔记
背景
去年 Q3,我们给可穿戴手环做一颗定制 SoC——双核 Cortex-M33 + ISP + BLE 基带,全部包进 42 mm² 的裸片。RTL 阶段用 Verilog 写 IP,后端用 TSMC 7 nm。看似人畜无害,结果在 FPGA bring-up 时因为 一条没命名的寄存器 把整个时钟树推翻了三次。今天把过程拆成四段:HDL 建模、SoC 集成、时钟树闭合、封装测试。所有数字都是实验室示波器 + PrimeTime 报的,表格我自己手打,放心抄。
1. HDL:先把 Verilog 写成“人话”
1.1 代码风格硬指标
检查项 | 我们最初 | 失败后修正 |
---|---|---|
寄存器命名 | reg_42 | cfg_isp_gamma_lut_en |
端口方向标记 | 缺省 | input wire logic ... |
行尾注释率 | 5 % | 100 % |
教训:“一周后你自己都不知道 reg_42 是干什么的。”
1.2 参数化位宽
ISP 的 gamma 查找表需要 2⁸ 条目 × 10 bit,最初手敲 reg [9:0] lut [255:0]
。后来把位宽参数化:
parameter LUT_DW = 10;
parameter LUT_DEPTH = 256;
logic [LUT_DW-1:0] lut [0:LUT_DEPTH-1];
这样后端做 ECC 冗余时可以直接 +2
一位校验,不改 RTL。
2. SoC 集成:IP 拼积木,但积木得有棱有角
2.1 总线矩阵
AXI4-Lite 配 128-bit AXI4,交叉矩阵用 Synopsys NIC-400。
主端口 | 从端口 | 带宽需求 | 实际分配 |
---|---|---|---|
M33_0 | SRAM | 2 GB/s | 2 GB/s |
ISP | DDR | 5 GB/s | 8 GB/s |
DMA | FLASH | 600 MB/s | 1 GB/s |
分配裕度 1.6×,防止 DDR 时钟抖动。
2.2 寄存器映射
自定义外设统一挂到 64 kB 地址窗口 0x5000_0000–0x5000_FFFF
。
- 每个寄存器 4 字节对齐,名字直接映射到 C header:
#define ISP_GAMMA_EN (*(volatile uint32_t *)0x50001234)
- 地址位[31:16] 当片选,[15:2] 当偏移,省一根译码器。
3. 时钟树闭合:一条没命名的寄存器毁三代
3.1 时钟需求
模块 | 频率 | 是否需门控 |
---|---|---|
M33 | 160 MHz | 是 |
DSP | 320 MHz | 是 |
BLE | 32 kHz RC | 否 |
3.2 翻车现场
ISP 里有一条时钟门控寄存器没被后端工具识别,原因是 Verilog 里写成了:
reg en; // 没加时钟域前缀
综合工具把它合成到 clk_isp
路径,结果时钟树长度差 180 ps,hold violation 1.2 ns。改了命名:
reg clk_isp_gate_en;
再跑一次 CTS,hold 清 0,timing 收敛时间从 72 h 降到 12 h。
4. 封装与测试:42 mm² 里塞不下一条飞线
4.1 封装选择
- WLCSP 0.4 mm pitch,6×7 ball map
- 电源 ball 对称放置,地弹 < 20 mV
4.2 量产 ATE
测试项 | 目标良率 | 实测良率 |
---|---|---|
逻辑 BIST | 99 % | 99.3 % |
存储器 MBIST | 98 % | 98.7 % |
模拟 PLL | 97 % | 97.8 % |
5. 血泪清单(现场手抄)
坑 | 触发点 | 补救 |
---|---|---|
寄存器无名 | 时钟树找不到门控 | 统一前缀 + 注释 |
AXI ID 冲突 | 两个 IP 都用 ID=0 | 脚本自动递增 |
电源地弹 | WLCSP ball 不对称 | 重新打样基板 |
封装翘曲 | 0.8 mm 超薄 | 加厚 0.2 mm 背板 |
一句话总结
HDL 写得好,SoC 集成少掉一把头发;寄存器起好名,时钟树不会半夜打电话让你回公司。
- 点赞
- 收藏
- 关注作者
评论(0)