Synthesis - 如何快速做一个基本综合?

1、如何快速做一个逻辑综合

在这里需要记住:在设置库的搜索路径、设置工艺库的时候,要使用set_app_var.其他的设置可以使用set了。

读取rtl代码使用read_file,写出网表使用write_file,最后会得到很多报告(.rpt)

在这里我们使用下面的代码作为顶层模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
module my_module
(
input logic clk,
input logic rst_n,
input logic [1:0] sel,
input logic [31:0] wdata,
input logic wr_en,
output logic [31:0] rdata
);

logic [31:0] register_file[3:0];

always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (int i = 0; i < 4; i++) begin
register_file[i] <= 'h0;
end
end else begin
if (wr_en) begin
register_file[sel] <= wdata;
end
end
end

assign rdata = register_file[sel];

endmodule

一个读写共用地址线、支持同步写入与异步读取的 4行 × 32位宽 的微型寄存器堆(Register File)。

.db文件是给DC读取,对应的.lib文件是供人参考。lib compiler工具可将.lib文件转换为.db文件

.lib (Liberty格式) 是明文的文本文件,可以用记事本打开它

Synopsys 的 DC 综合工具它嫌读文本太慢了!所以,Synopsys 把 .lib 编译、加密成了它独家专属的二进制格式——也就是这个 .db (Database) 文件。

所以总结一句话:.lib 是给人看的工艺库,.db 是给 DC 工具高效率使用的工艺库。

只要你在 .v 文件里看到 GTECH 前缀和 SEQGEN 单元,就可以 100% 判定这是一个未经映射(Unmapped)的中间态网表。

  1. 看到 SEQGEN:时序逻辑的毛坯

特征:寄存器不是具体的工艺单元(如 SMIC 的 DFFRQX1M),而是统一标着 SEQGEN
含义:这代表 Design Compiler 已经识别出这里需要“存数据”,但还没决定用哪个电压、哪个尺寸的触发器去存。

  1. 看到 GTECH_ 前缀:组合逻辑的占位符

特征:所有的门电路都叫 GTECH_AND2、GTECH_NOT、GTECH_BUF 等。
含义:这些是 Synopsys 内部的通用逻辑符号。它们没有物理尺寸,没有延迟数据,只是在逻辑上告诉工具“这里有个与门”。

  1. 逻辑块操作符 (MUX_OP, SELECT_OP)

特征:出现这种大写字母结尾且带 _OP 的单元。
含义:这是 DC 把你的 if-else 或 case 语句初步转换成的“功能块”。在最终映射时,它们会被拆解成一大堆细碎的组合门电路。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/////////////////////////////////////////////////////////////
// Created by: Synopsys Design Compiler(R)
// Version : T-2022.03-SP2
// Date : Fri Feb 20 01:43:16 2026
/////////////////////////////////////////////////////////////


module my_module ( clk, rst_n, sel, wdata, wr_en, rdata );
input [1:0] sel;
input [31:0] wdata;
output [31:0] rdata;
input clk, rst_n, wr_en;
\**SEQGEN** \register_file_reg[1][0] ( .clear(N8), .preset(1'b0),
.next_state(wdata[0]), .clocked_on(clk), .data_in(1'b0), .enable(1'b0),
.Q(\register_file[1][0] ), .synch_clear(1'b0), .synch_preset(1'b0),
.synch_toggle(1'b0), .synch_enable(N15) );
\**SEQGEN** \register_file_reg[0][31] ( .clear(N8), .preset(1'b0),
.next_state(wdata[31]), .clocked_on(clk), .data_in(1'b0), .enable(1'b0), .Q(\register_file[0][31] ), .synch_clear(1'b0), .synch_preset(1'b0),
.synch_toggle(1'b0), .synch_enable(N14) );
\**SEQGEN** \register_file_reg[0][30] ( .clear(N8), .preset(1'b0),
.next_state(wdata[30]), .clocked_on(clk), .data_in(1'b0), .enable(1'b0), .Q(\register_file[0][30] ), .synch_clear(1'b0), .synch_preset(1'b0),
.synch_toggle(1'b0), .synch_enable(N14) );
GTECH_AND2 C529 ( .A(sel[0]), .B(sel[1]), .Z(N13) );
GTECH_AND2 C530 ( .A(N0), .B(sel[1]), .Z(N12) );
GTECH_NOT I_0 ( .A(sel[0]), .Z(N0) );
GTECH_AND2 C531 ( .A(sel[0]), .B(N1), .Z(N11) );

GTECH_BUF B_2 ( .A(sel[0]), .Z(N6) );
GTECH_BUF B_3 ( .A(sel[1]), .Z(N7) );
GTECH_NOT I_4 ( .A(rst_n), .Z(N8) );
GTECH_NOT I_5 ( .A(wr_en), .Z(N9) );
endmodule

起点 (RTL):你写的 .sv 源代码。

第一站 (Elaborate):执行 read_file 后,DC 把代码翻译成 GTECH 网表。你现在看的就是这一站的产物。

第二站 (Compile):执行 compile_ultra 后,DC 会把 GTECH 替换为具体的工艺单元。

终点 (Mapped):产生包含 DFFRQX1M 或 OA22XLM 等真实单元的 Mapped 网表。

postcompile.v 是给 Design Compiler 自己看的,而 change_names 后的网表是给全世界看的。

🔍 区别一:逃逸字符 vs. 规范命名 (Escaped Names)

这是最容易看出来的区别。

postcompile.v (带有“反斜杠”):
你看它的连线名和实例名:\register_file[3][31]。
原理:在 Verilog 语法中,如果名字里带中括号 [],编译器会觉得那是数组。DC 为了保留你 RTL 里的层级美感,强行加了反斜杠 \ 作为转义。
毒点:这种格式虽然合法,但到了后端工具(比如 Innovus)或者仿真器里,经常会报错或识别混乱。
change_names 后 (干净清爽):
名字变成了:register_file_reg_3__31_。
原理:DC 把所有的 [ 和 ] 全都换成了下划线 _。
优点:这叫“合法化(Legalization)”,所有 EDA 工具都能无压力识别,这是大厂流片网表的标配格式。

📊 区别二:零散连线 vs. 总线合并 (Bus Reconstruction)

这一部分体现了 change_names 的强大整理能力。

postcompile.v:
声明了一大堆密密麻麻的单根 wire,比如 wire \register_file[3][31] , \register_file[3][30] …。
这就像是一捆乱麻,每一根线都有一个极其古怪的长名字。
change_names 后:
直接合并成了:wire [127:0] register_file;。
原理:工具识别出这些分散的线其实是同一个寄存器组,于是重新打包成了一个 128 位的向量(Vector)。
赢在哪里:代码行数瞬间缩减,可读性提升了 100 倍!

🏗️ 区别三:实例引脚的引用方式

postcompile.v:
引脚连接:.Q(\register_file[3][31] )。
change_names 后:
引脚连接:.Q(register_file[127])。
含义:所有的引用都从“奇奇怪怪的字符串”回归到了正常的“数组索引”。

举一个下面的例子:

综合工具把这些寄存器,直接chang_name优化成下面的了:

下面的这些寄存器:

更换名字:

使用下划线等进行命名:

2、逻辑综合脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 1. 基础环境定义
set TOP_MODULE my_module
set VERSION v1_ss_run

set_host_options -max_cores 8
define_design_lib WORK -path ./WORK

set OUTPUT_DIR ./results/${VERSION}/outputs
set REPORT_DIR ./results/${VERSION}/reports

if {![file exists $OUTPUT_DIR]} {file mkdir -p $OUTPUT_DIR}
if {![file exists $REPORT_DIR]} {file mkdir -p $REPORT_DIR}

# 2. 工艺库配置
set_app_var search_path ". ./library"
set_app_var target_library "ss_1v62_125c.db"
set_app_var link_path "* ss_1v62_125c.db"

# 3. 读入设计与转换
read_file -format sverilog "./sources/${TOP_MODULE}.sv"
current_design ${TOP_MODULE}
link

# 输出 GTECH 中间态网表
write_file -hierarchy -format ddc -output ${OUTPUT_DIR}/${TOP_MODULE}.precompile.ddc
write_file -hierarchy -format verilog -output ${OUTPUT_DIR}/${TOP_MODULE}.precompile.v

# 4. 施加约束
create_clock -period 10.0 [get_ports clk]

# 5. 核心综合阶段
compile_ultra

# 输出映射后网表
write_file -format verilog -hierarchy -output ${OUTPUT_DIR}/${TOP_MODULE}.postcompile.v
write_file -format ddc -hierarchy -output ${OUTPUT_DIR}/${TOP_MODULE}.postcompile.ddc

# 6. 网表合法化 (去除反斜杠, 合并总线)
change_names -rules verilog -hierarchy

# 输出最终交付级网表
write_file -format verilog -hierarchy -output ${OUTPUT_DIR}/${TOP_MODULE}.mapped.v
write_file -format ddc -hierarchy -output ${OUTPUT_DIR}/${TOP_MODULE}.mapped.ddc

# 7. 生成体检报告
report_timing > ${REPORT_DIR}/${TOP_MODULE}.timing.rpt
report_area > ${REPORT_DIR}/${TOP_MODULE}.area.rpt
report_power > ${REPORT_DIR}/${TOP_MODULE}.power.rpt

echo "Synthesis Finished! Results are in ${VERSION} folder."
exit

3、查看area.rpt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
****************************************
Report : area
Design : my_module
Version: O-2018.06-SP1
Date : Thu Feb 26 19:54:00 2026
****************************************

Library(s) Used:

slow (File: /tools/Lib/digit_lib/smic180/std/synopsys/slow.db)

Number of ports: 69
Number of nets: 403
Number of cells: 366
Number of combinational cells: 238
Number of sequential cells: 128
Number of macros/black boxes: 0
Number of buf/inv: 6
Number of references: 5

Combinational area: 3632.428809
Buf/Inv area: 39.916800
Noncombinational area: 8089.804688
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (No wire load specified)

Total cell area: 11722.233497
Total area: undefined
1

我们来看一下其中的这个报告做了什么:

  • Number of ports (69):芯片对外的引脚总数。你的输入信号 + 输出信号加起来一共有 69 根线。

  • Number of nets (403):芯片内部的“血管”数量。门电路和门电路之间有 403 根导线连着

  • Number of cells (366):你的总砖头数! 整个设计一共用了 366 个标准单元。

    • Number of combinational cells (238):干活的员工(组合逻辑)。这就是与非门、或非门、加法器等,一共 238 个,负责疯狂算数。

    • Number of sequential cells (128):记事本(时序逻辑)。这就是 D 触发器 (Flip-flops) 或者锁存器,一共 128 个,负责把每一拍算好的数据存下来。

  • Number of macros/black boxes (0):你没有用到 SRAM 内存块或者第三方大 IP。

  • Number of buf/inv: 6 (缓冲器与反相器的数量)

    • 专业全称:Buffer (缓冲器) / Inverter (反相器 或 非门)。

    • 军师通俗解释:这俩兄弟是芯片里的**“后勤运输队长”和“信号翻转员”**。

    • Inverter (非门):负责把 0 变成 1,把 1 变成 0。

    • Buffer (缓冲器):逻辑上它什么都不干(输入 1,输出还是 1)。它的真实物理作用是**“信号放大中继站”**!当你的一个引脚要同时驱动几十个门电路(Fanout 扇出太大),或者要跑一段很长的金属线时,信号会衰减。工具就会强行在中间插一个 Buffer,给信号“打鸡血”续航。

  • Number of references: 5 (引用的“乐高积木”种类)
    Total cells 是 366 个(你一共用了 366 块乐高积木盖房子)。
    但这行 references: 5 告诉你:这 366 块积木,其实翻来覆去只用了 5 种不同的型号!
    DC 工具精确且唯一地使用了以下 5 种标准单元:

    DFFSXL (带有置位功能的 D触发器):这是你的记忆体。

    INVXL (反相器 / 非门):信号翻转员。

    NOR2XL (两输入或非门):基础逻辑单元。

    NAND2XL (两输入与非门):基础逻辑单元。

    🔥 AOI22XL (AND-OR-Invert 2-2 复合门):全场真正的 MVP!

下面这堆内容是啥呢:

1
2
3
4
5
Combinational area:               3632.428809
Buf/Inv area: 39.916800
Noncombinational area: 8089.804688
Macro/Black Box area: 0.000000
Net Interconnect area: undefined (No wire load specified)
  1. Combinational area: 3632.42 (组合逻辑占地)

    它是啥:这就是你用来做“4选1多路选择器 (MUX)”和“写地址译码器 (Decoder)”的那些砖头——满屏的 AOI22XL、NAND、NOR。

    军师点评:它们负责纯粹的逻辑计算,一共花了 3600 多平方微米。

  2. Buf/Inv area: 39.91 (后勤跑腿占地)

    它是啥:包含在上面那个组合逻辑面积里的一小部分。这就是咱们之前抓出来的仅仅 6 个的反相器(INV)和缓冲器(BUF)。

    军师点评:你看,面积才区区 39.9!跟总面积比起来简直就是九牛一毛。这再次证明了你代码的数据通路极其通畅,没怎么动用“信号中继站”。

  3. Noncombinational area: 8089.80 (非组合逻辑 / 时序逻辑占地)它是啥:这就是你那 $4 \times 32 = 128$ 个极其金贵的 DFFSXL(D触发器)!🔥 架构师的极度坦诚:兄弟,看到这个极其悬殊的对比了吗?你 238 个组合门才占 3600,而 128 个触发器居然占了 8000 多!工业界铁律:触发器(寄存器)是芯片里最占面积、最吃功耗的“吞金兽”! 所以为什么现在复杂的 CPU 缓存都要用定制的 SRAM,而不敢直接用触发器去拼(Register File 一般只做小容量的寄存器堆),这就是血淋淋的物理成本!

  4. Macro/Black Box area: 0.00 (宏单元/黑盒占地)

    它是啥:如果你在代码里调用了现成的、别人画好的大黑盒(比如从内存编译器里生成的 SRAM 模块,或者买来的 PLL 锁相环 IP)。

    军师点评:你是纯手写的 RTL 代码,全是用标准单元(细碎的乐高积木)拼的,所以大模块面积是 0。

  5. Net Interconnect area: undefined (导线互连占地)

    它是啥:门电路之间那些金属连线所占的面积。

    军师点评:为什么是 undefined(未知)?因为它后面跟着一句大实话——(No wire load specified)(未指定线负载模型)。DC 综合工具现在只是在脑子里把你建好了,根本没把这些模块真正放在一块二维板子上,所以连线有多长它完全不知道!除非你强制给它一个预估模型(Wire Load Model),否则它拒绝对导线面积负责。

  6. Total cell area: 11722.23 (总净使用面积)

    它是啥:把组合逻辑 (3632) + 触发器 (8089) 加起来的纯室内使用面积。

  7. Total area: undefined (带公摊的总建筑面积)

    它是啥:单元使用面积 + 走线面积。

    军师点评:既然连线面积是未知的,总面积当然也是未知的。你想知道真正的带走线总面积,只有等到了 Innovus 布局布线之后,看真实的版图数据!

4、timing.rpt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Information: Updating design information... (UID-85)

****************************************
Report : timing
-path full
-delay max
-max_paths 1
Design : my_module
Version: O-2018.06-SP1
Date : Thu Feb 26 19:54:00 2026
****************************************

Operating Conditions: slow Library: slow
Wire Load Model Mode: top

Startpoint: register_file_reg_2__1_
(rising edge-triggered flip-flop clocked by clk)
Endpoint: register_file_reg_2__1_
(rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max

Point Incr Path
-----------------------------------------------------------
clock clk (rise edge) 0.00 0.00
clock network delay (ideal) 0.00 0.00
register_file_reg_2__1_/CK (DFFSXL) 0.00 0.00 r
register_file_reg_2__1_/QN (DFFSXL) 0.57 0.57 f
U460/Y (AOI22XL) 0.21 0.78 r
register_file_reg_2__1_/D (DFFSXL) 0.00 0.78 r
data arrival time 0.78

clock clk (rise edge) 10.00 10.00
clock network delay (ideal) 0.00 10.00
register_file_reg_2__1_/CK (DFFSXL) 0.00 10.00 r
library setup time -0.09 9.91
data required time 9.91
-----------------------------------------------------------
data required time 9.91
data arrival time -0.78
-----------------------------------------------------------
slack (MET) 9.12


1

我们先注释一下这个时序报告:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Operating Conditions: slow   Library: slow 
## 军师批注:【环境侦测】当前处于 180nm 的炼狱模式(高温低压),此时晶体管跑得最慢,用来查 Setup 违例最准。
Wire Load Model Mode: top
## 军师批注:【连线预估】因为还没进行物理连线,工具在此使用顶层线负载模型(瞎猜导线延迟)。

Startpoint: register_file_reg_2__1_
(rising edge-triggered flip-flop clocked by clk)
## 军师批注:【起跑线】数据的发射源。这是一个由 clk 上升沿触发的 D 触发器。

Endpoint: register_file_reg_2__1_
(rising edge-triggered flip-flop clocked by clk)
## 军师批注:【终点线】数据的接收端。你看,起点和终点是同一个触发器!说明这是一个“自己反馈给自己”的路径(寄存器保持原值)。

Path Group: clk
Path Type: max
## 军师批注:再次确认,这是 clk 时钟域下的 Setup (max) 检查。

Point Incr Path
-----------------------------------------------------------
## ========== 第一幕:计算数据实际到达时间 (Data Arrival Time) ========== ##
clock clk (rise edge) 0.00 0.00
## 军师批注:【发令枪响】在 0.00ns 时刻,时钟上升沿到来。

clock network delay (ideal) 0.00 0.00
## 军师批注:因为这是前端综合,还没做时钟树综合(CTS),所以工具假设时钟网是“完美的(ideal)”,延迟为0。

register_file_reg_2__1_/CK (DFFSXL) 0.00 0.00 r
## 军师批注:时钟信号瞬间到达了发射端触发器的 CK (Clock) 引脚。末尾的 'r' 代表上升沿 (rise)。

register_file_reg_2__1_/QN (DFFSXL) 0.57 0.57 f
## 军师批注:【触发器出翻转延迟】时钟敲击后,触发器把数据从 QN 引脚吐出来,花了 0.57ns。末尾的 'f' 代表数据是个下降沿 (fall,从1变0)。

U460/Y (AOI22XL) 0.21 0.78 r
## 军师批注:【组合逻辑延迟】数据跑在走廊上,穿过了 U460 这个复合逻辑门,花了 0.21ns。此时总耗时累加为 0.78ns。数据变成上升沿 'r'。

register_file_reg_2__1_/D (DFFSXL) 0.00 0.78 r
## 军师批注:数据终于抵达了接收端触发器的 D 引脚。路上导线延迟为 0.00 (综合阶段忽略不计)。

data arrival time 0.78
## 军师批注:【总结算 1】数据实际跑到终点,总共花了 0.78ns。


## ========== 第二幕:计算系统死线 (Data Required Time) ========== ##
clock clk (rise edge) 10.00 10.00
## 军师批注:【下一次发令枪响】因为你在脚本里约束了周期是 10.00ns,所以下一个时钟沿在 10.00ns 时刻到来。

clock network delay (ideal) 0.00 10.00
## 军师批注:接收端的时钟树延迟,依然假设是完美的 0.00ns。

register_file_reg_2__1_/CK (DFFSXL) 0.00 10.00 r
## 军师批注:10.00ns 时刻,时钟准确敲击接收端触发器。

library setup time -0.09 9.91
## 军师批注:【傲娇的建立时间】查阅 slow.db 发现,这个 DFFSXL 触发器要求数据必须“提前 0.09ns”到达并保持稳定。所以 10.00 减去 0.09。

data required time 9.91
## 军师批注:【总结算 2】工具下达最后通牒:数据必须在 9.91ns 之前到达!(这就是死线)
-----------------------------------------------------------


## ========== 第三幕:最终审判 (Slack Calculation) ========== ##
data required time 9.91
## 军师批注:这是要求的死线。

data arrival time -0.78
## 军师批注:这是实际到达时间。公式是 Required 减去 Arrival。
-----------------------------------------------------------
slack (MET) 9.12
## 军师批注:【宣判结果】9.91 - 0.78 = 9.12ns。
## 因为是正数,所以是 MET(满足要求)!你不仅没迟到,还提前了 9.12ns 抵达终点,时序极其宽裕!
## 如果这里是负数,就会显示 VIOLATED(违例),那就得回去改代码或者降频了。

1

5、power.rpt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Information: Propagating switching activity (low effort zero delay simulation). (PWR-6)
Warning: Design has unannotated primary inputs. (PWR-414)
Warning: Design has unannotated sequential cell outputs. (PWR-415)

****************************************
Report : power
-analysis_effort low
Design : my_module
Version: O-2018.06-SP1
Date : Thu Feb 26 19:54:00 2026
****************************************


Library(s) Used:

slow (File: /tools/Lib/digit_lib/smic180/std/synopsys/slow.db)


Operating Conditions: slow Library: slow
Wire Load Model Mode: top


Global Operating Voltage = 1.62

#架构师洞察:咱们之前说 180nm 的标准电压是 1.8V。但在 slow.db(炼狱模式)下,
#代工厂假设电源供电极度不稳,直接把电压拉低到了 1.62V(也就是 1.8V 跌了 10%)!
#在吃不饱饭的情况下,工具开始计算它的能耗。

Power-specific unit information :
Voltage Units = 1V
Capacitance Units = 1.000000pf
Time Units = 1ns
Dynamic Power Units = 1mW (derived from V,C,T units)
Leakage Power Units = 1pW


Cell Internal Power = 689.8427 uW (97%)
Net Switching Power = 20.8919 uW (3%)
---------
Total Dynamic Power = 710.7345 uW (100%)

Cell Leakage Power = 304.1248 nW


Internal Switching Leakage Total
Power Group Power Power Power Power ( % ) Attrs
--------------------------------------------------------------------------------------------------
io_pad 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
memory 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
black_box 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
clock_network 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
register 0.6746 2.5900e-03 2.0173e+05 0.6774 ( 95.27%)
sequential 0.0000 0.0000 0.0000 0.0000 ( 0.00%)
combinational 1.5198e-02 1.8302e-02 1.0239e+05 3.3602e-02 ( 4.73%)
--------------------------------------------------------------------------------------------------
Total 0.6898 mW 2.0892e-02 mW 3.0412e+05 pW 0.7110 mW
1
  1. Cell Internal Power (内部功耗) = 689.84 uW (97%)

    这是逻辑门内部晶体管在 0 和 1 切换时,瞬间短路产生的功耗,以及充放电内部电容的功耗。它占了绝对的大头。

  2. Net Switching Power (翻转功耗) = 20.89 uW (3%)

    这是给外部“导线”充放电产生的功耗。

    为什么只有 3% 这么惨? 因为你现在在综合阶段!咱们在看面积报告时就说过,连线还没画出来,导线长度是 undefined,所以给导线充电的功耗自然被工具严重低估了。

  3. Cell Leakage Power (漏电流功耗) = 304.12 nW (极其微小)

    这是芯片只要通上电,哪怕什么都不干,像水龙头漏水一样偷偷溜走的功耗。

    在 180nm 这种远古工艺里,漏电小到只有几百纳瓦(nW),可以忽略不计。但如果你以后做 28nm 甚至 7nm,漏电功耗会大到让你怀疑人生,甚至能占到总功耗的 30% 以上!

这里重点强调一下register、sequential、combinational的区别:

Latch是什么:在广义学术上,寄存器也算 Sequential;但在咱们这份综合功耗报告里,sequential 这一行被工具专门用来统计“锁存器 (Latch)”!

为什么它很危险? 假设时钟的高电平占了半个周期(比如 5ns)。在这漫长的 5ns 里,Latch 的大门是完全敞开的!如果这期间外面的输入信号因为干扰抖动了一下,这个错误数据会立刻冲进 Latch 里被记住,进而引发整个芯片的崩溃。这叫“时序不可控”。

在硬件层面,Latch 是一种**电平敏感(Level-sensitive)**的存储单元。

它的特性:想象一扇门。

当“使能信号”(通常是时钟 clk)是高电平时,这扇门是完全敞开的。外面发生什么,里面就跟着变什么(这叫透明模式,Transparent)。

只有当“使能信号”变为低电平时,门才砰地关上,锁住最后那一刻的数据。

对比 DFF(寄存器):DFF 只在时钟上升沿那一瞬间(比如从 0 变 1 的那 0.1 纳秒)开门看一眼数据,然后迅速关门。其余时间雷打不动。

6、-hierarchy含义

在 Synopsys Design Compiler (DC) 或相关工具中,write_file命令的 -hierarchy​ 选项用于在输出的网表文件中保留原始设计的层次结构。

作用详解
保留模块边界:

  • 有 -hierarchy:输出的网表文件会保持你在RTL代码中定义的模块层次。顶层模块会包含对子模块的实例化,子模块本身也会被定义。
  • 无 -hierarchy:工具会进行扁平化处理。所有底层子模块(通常是标准单元)都会被展开并直接连接到顶层模块中,原始的模块名和边界会消失,网表变成一个巨大的、只有最底层单元的平面网络。

输出结果对比:
保留层次​ (-hierarchy):

1
2
3
4
5
6
7
8
9
10
// 顶层模块 TOP
module TOP (input clk, input d, output q);
// 实例化了一个子模块 SUB
SUB u_sub (.clk(clk), .d(d), .q(q));
endmodule

// 子模块 SUB 的定义依然存在
module SUB (input clk, input d, output q);
DFFX1 u_dff (.CLK(clk), .D(d), .Q(q)); // 实例化了底层寄存器
endmodule

扁平化​ (无 -hierarchy):

1
2
3
4
5
6
// 所有层次被打平,只剩下顶层和底层标准单元
module TOP (input clk, input d, output q);
// 直接实例化最终的标准单元,子模块 SUB 消失了
DFFX1 u_dff (.CLK(clk), .D(d), .Q(q));
endmodule
// 模块 SUB 的定义不存在了

为什么需要使用 -hierarchy?

  • 便于调试与分析:保留层次结构与你的RTL设计一一对应,在排查时序违例、功耗问题或进行后仿真时,你可以清晰地定位到是哪个功能模块出了问题。
  • 满足后端流程需求:很多布局布线工具可以进行层次化设计或模块化布局。保留层次信息有助于后端工具更好地理解设计结构,可能对优化布局、缩短运行时间有好处。
  • 数据重用与接口清晰:.ddc格式是Synopsys的数据库格式,能保存约束、属性等更多信息。保留层次的DDC文件可以更方便地在不同工具(如Formality形式验证工具)或不同阶段(综合与布局布线后)之间传递和复用设计数据。
ESC 关闭 | 导航 | Enter 打开
输入关键词开始搜索