2. SoC设计流程:从需求分析到流片
各位同学,今天我们来聊聊SoC设计的完整流程。说实话,很多刚入行的工程师容易把设计流程看成一条流水线——需求来了,架构定好,RTL写完,验证通过,然后丢给后端就完事了。但我在实际项目中踩过不少坑,发现每个环节之间都有很多「隐形的工作」。
我个人习惯把SoC设计流程分成八个阶段。你想想看,这就像盖一栋楼,从画图纸到打地基,再到装修入住,每一步都马虎不得。
核心流程速览:
需求分析 → 架构设计 → RTL编码 → 验证 → 综合 → 布局布线 → 流片 → 测试
下面我逐一展开讲,每个阶段我都会结合自己的项目经验,告诉你哪些地方容易翻车。
2.1 需求分析:别急着写代码
很多团队一上来就开干,结果做到一半发现需求变了。嗯,这很常见。
需求分析阶段,说白了就是搞清楚三件事:
- 功能需求:芯片要做什么?支持哪些协议?跑什么操作系统?
- 性能指标:主频多少?功耗限制?面积预算?
- 接口定义:外部要接DDR吗?PCIe几代?USB是3.0还是2.0?
我在一个AI芯片项目里遇到过,客户说「要支持4K视频编解码」,结果我们按H.265做了,最后发现他们用的是VP9。这一改,架构全推倒重来。所以我的建议是:需求文档一定要签字确认,而且最好写清楚「不支持什么」。
小技巧:需求分析阶段可以画一个简单的功能框图,把芯片的输入输出、主要模块、数据流向画出来。这张图后面会变成架构设计的起点。
2.2 架构设计:搭骨架
架构设计是SoC设计中最考验经验的一步。你需要决定:
- 总线拓扑:用AXI还是NoC?多主多从怎么仲裁?
- 存储层次:Cache多大?SRAM分布在哪?DDR控制器怎么接?
- 时钟复位:多少个时钟域?异步处理怎么做?
- 功耗策略:哪些模块可以关掉?DVFS怎么实现?
我记得有一次做车规级芯片,架构评审时大家吵了三天,就为了决定「CPU cluster用big.LITTLE还是DSU」。最后我们选了DSU,因为功耗更可控。你看,架构设计没有标准答案,只有「最适合当前需求」的方案。
这里我画了一张SoC架构的简化框图,你可以看看各个模块之间的关系:
2.3 RTL编码:把想法变成代码
架构定好了,接下来就是写RTL。这一步看似简单,其实最容易出问题。
我建议你养成几个好习惯:
- 代码风格统一:命名规范、注释清晰、模块化设计
- 同步设计原则:所有触发器都用时钟沿触发,避免组合逻辑环路
- 异步处理:跨时钟域信号一定要做同步处理,用双锁存器或者异步FIFO
举个例子,一个简单的AXI从机接口,代码大概长这样:
module axi_slave #(
parameter DATA_WIDTH = 32,
parameter ADDR_WIDTH = 16
)(
input logic clk,
input logic rst_n,
// AXI写地址通道
input logic [ADDR_WIDTH-1:0] awaddr,
input logic awvalid,
output logic awready,
// AXI写数据通道
input logic [DATA_WIDTH-1:0] wdata,
input logic wvalid,
output logic wready,
// AXI写响应通道
output logic [1:0] bresp,
output logic bvalid,
input logic bready
);
// 内部寄存器
logic [ADDR_WIDTH-1:0] awaddr_reg;
logic awvalid_reg;
// 写地址通道处理
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
awaddr_reg <= '0;
awvalid_reg <= '0;
end else begin
if (awvalid && awready) begin
awaddr_reg <= awaddr;
awvalid_reg <= 1'b1;
end else if (bvalid && bready) begin
awvalid_reg <= 1'b0;
end
end
end
// 握手信号
assign awready = !awvalid_reg || (bvalid && bready);
endmodule
注意:写RTL时最容易犯的错误是「组合逻辑环路」。我曾经在一个项目中,因为一个assign语句写成了组合反馈,导致仿真时信号一直震荡。后来花了三天才定位到问题。所以,写完代码一定要做 lint 检查。
2.4 验证:花的时间比写代码多
验证是SoC设计中最耗时的环节。一般来说,验证时间占整个项目周期的60%以上。
验证策略通常包括:
- 模块级验证:每个IP单独测,用UVM搭建testbench
- 子系统验证:把几个相关模块连起来测,比如CPU+Cache+DDR
- 系统级验证:整个SoC跑起来,跑操作系统、跑应用
- 后仿验证:综合后、布局布线后,带上时序信息再仿一遍
我个人习惯在验证阶段做三件事:
- 写测试计划:把功能点列出来,每个点对应一个测试用例
- 做覆盖率分析:代码覆盖率、功能覆盖率、翻转覆盖率,缺一不可
- 随机测试:用约束随机生成测试向量,往往能发现意想不到的bug
避坑指南:我曾经在一个项目中,模块级验证都过了,系统级验证也跑了三天三夜没报错。结果流片回来,发现DDR控制器在特定温度下会丢数据。后来查出来是后仿没做全,有个时序路径没覆盖到。所以,后仿一定不能省。
2.5 综合:把RTL变成门级网表
综合就是把RTL代码映射到标准单元库上。这一步会决定你的芯片能不能跑到目标频率。
综合的关键参数:
| 参数 | 说明 | 我的建议 |
|---|---|---|
| 时钟周期 | 目标工作频率 | 留10%-20%余量 |
| 输入延迟 | 外部信号到达时间 | 按接口协议严格约束 |
| 输出延迟 | 信号到达外部的时间 | 同样按协议约束 |
| 面积约束 | 芯片面积上限 | 不要压太紧,留布线空间 |
| 功耗约束 | 动态/静态功耗上限 | 多电压域设计更灵活 |
综合完成后,一定要做静态时序分析(STA)。说白了就是检查所有路径的建立时间和保持时间是否满足。我刚开始做设计时总觉得这步可有可无,直到有一次流片回来芯片死活上不了高频...嗯,从那以后我再也不敢跳过STA了。
2.6 布局布线:把网表变成版图
布局布线是后端工程师的活,但作为架构师,你也要了解基本流程:
- 布局:把标准单元放到芯片的物理位置上
- 时钟树综合:把时钟信号均匀分布到所有触发器
- 布线:用金属层把单元连起来
- 物理验证:DRC检查、LVS检查
这里有个坑:布局布线阶段往往会发现时序不满足。为什么?因为综合时用的是线负载模型,而实际布线后的延迟可能更大。所以,后仿真的重要性怎么强调都不为过。
2.7 流片:把设计交给工厂
流片就是把最终的GDSII文件交给晶圆厂。这一步其实没什么技术含量,但流程非常繁琐。
流片前需要确认:
- 所有验证都通过了
- 时序收敛了
- 物理验证没有DRC/LVS错误
- 功耗分析满足要求
- IR drop分析通过
我记得第一次流片时,光签核文件就签了二十多页。每一页都要确认签字,少签一个工厂就不收。所以,流片前的检查清单一定要逐项打勾。
2.8 测试:芯片回来了,是骡子是马牵出来遛遛
芯片回来后,第一件事就是上电测试。测试通常分几步:
- 功能测试:跑基本的读写操作,看芯片能不能正常工作
- 性能测试:跑benchmark,看能不能达到设计指标
- 压力测试:高温、低温、高电压、低电压,看芯片的鲁棒性
- 量产测试:用ATE自动测试设备批量测试
经验之谈:芯片测试时,一定要先测电源和时钟。如果电源短路或者时钟没起振,后面的测试都不用做了。我见过一个团队,芯片回来后直接跑功能测试,结果发现所有寄存器都读不到值。查了两天才发现是PLL没锁定,时钟根本没出来。
好了,以上就是SoC设计流程的八个阶段。每个阶段都有它的难点和坑,但只要你按部就班、步步为营,最终一定能拿到一颗能工作的芯片。
公众号:蓝海资料掘金营,微信deep3321