3、RTL设计与综合库:可综合的RTL语法风格、标准单元库(Liberty文件)介绍、工艺库(.db文件)的加载
好,咱们进入第三章。这一章我打算聊聊RTL设计里那些「能综合」的语法,以及综合库到底是个什么东西。
说实话,我刚入行那会儿,写RTL的时候经常踩坑。明明仿真跑得好好的,一综合就报错。后来才明白——不是所有Verilog语法都能被综合工具识别。嗯,这里要注意。
3.1 可综合的RTL语法风格
什么叫「可综合」?说白了,就是你的代码能映射到实际的硬件电路上。仿真可以天马行空,但综合必须脚踏实地。
我个人习惯把RTL写法分成三类:
- 肯定能综合的:assign、always@(posedge clk)、case、if-else
- 看情况能综合的:for循环(要固定次数)、function(纯组合逻辑)
- 基本不能综合的:initial、#delay、force、release、fork-join
举个例子,下面这段代码就是典型的可综合风格:
module counter (
input clk,
input rst_n,
input en,
output reg [3:0] count
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
count <= 4'b0;
else if (en)
count <= count + 1'b1;
end
endmodule
这段代码能综合成什么?一个带异步复位的4位加法计数器。工具会把它映射到标准单元库里的D触发器和加法器上。
我曾经在一个项目里看到有人用for循环写了一个很大的移位寄存器。仿真没问题,但综合出来面积大得吓人。为什么?因为for循环会被展开成并行逻辑,循环次数越多,硬件越庞大。
3.2 标准单元库(Liberty文件)介绍
综合工具把RTL变成网表,靠的是什么?靠的就是标准单元库。这个库通常以.lib或.db格式存在。
Liberty文件(.lib)是文本格式的,你可以直接打开看。里面记录了每个标准单元的:
- 功能描述(比如AND2、DFF、MUX2)
- 时序参数(建立时间、保持时间、延迟)
- 功耗信息(动态功耗、静态功耗)
- 面积信息
- 驱动能力(不同驱动强度的版本)
举个例子,一个简单的二输入与非门在Liberty文件里大概长这样:
cell (NAND2_X1) {
area : 1.0;
pin (A) { direction : input; capacitance : 0.01; }
pin (B) { direction : input; capacitance : 0.01; }
pin (ZN) {
direction : output;
function : "(A & B)'";
timing () {
related_pin : "A";
timing_type : "combinational";
cell_rise (delay_template_7x7) {
index_1 ("0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10.0");
index_2 ("0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0");
values ( \
"0.05, 0.08, 0.12, 0.18, 0.25, 0.40, 0.60", \
...
);
}
}
}
}
你想想看,工具拿到这个库,就知道每个门的延迟是多少、面积多大、功耗多高。然后它才能去优化你的设计。
3.3 工艺库(.db文件)的加载
实际项目中,我们很少直接使用.lib文件。因为它是文本格式,解析起来慢。工具厂商通常会把.lib编译成.db格式——这是二进制文件,加载更快。
在Design Compiler里加载工艺库,一般这么写:
set target_library "scc40nm_typ.db"
set link_library "* scc40nm_typ.db"
set symbol_library "scc40nm.sdb"
这里解释一下:
target_library:告诉工具,你只能用这些库里的单元来综合link_library:告诉工具,解析网表时去哪些库里找单元定义。那个*表示先搜内存中已有的库symbol_library:用于图形界面显示,不加载也能综合
我记得有一次,同事把link_library写漏了,结果综合出来的网表里全是GTECH单元——那是工具的通用中间表示,根本不能用于后端。折腾了半天才发现是库没加载对。
target_library和link_library搞混,导致综合出的网表里混入了不同工艺角的单元。后来我养成了一个习惯——每次加载完库,先用list_libs命令检查一下。
另外,工艺库通常会有多个版本:
| 工艺角 | 典型文件 | 使用场景 |
|---|---|---|
| 典型(typical) | scc40nm_typ.db | 常规综合,平衡时序和功耗 |
| 最差(worst) | scc40nm_wc.db | 建立时间检查,最悲观情况 |
| 最好(best) | scc40nm_bc.db | 保持时间检查,最乐观情况 |
实际项目中,我们通常会用最差工艺角来做综合,保证芯片在最恶劣条件下也能工作。等综合完了,再用最好工艺角做保持时间检查。
嗯,这一章的内容差不多就这些。总结一下:
- 写RTL时,脑子里要有电路
- Liberty文件是标准单元的「身份证」
- .db文件是编译后的库,加载时注意
target和link的区别
下一章我会聊聊综合约束——怎么告诉工具你的芯片要跑多快、面积要多大。到时候见。