You are on page 1of 36

基本后端流程(漂流&雪拧)

----- 2010/7/3---2010/7/8

本教程将通过一个 8*8 的乘法器来进行一个从 verilog 代码到版图的整个流程(当然只是基


本流程,因为真正一个大型的设计不是那么简单就完成的) ,此教程的目的就是为了让大家
尽快了解数字 IC 设计的大概流程,为以后学习建立一个基础。此教程只是本人探索实验的
结果,并不代表内容都是正确的,只是为了说明大概的流程,里面一定还有很多未完善并且
有错误的地方,我在今后的学习当中会对其逐一完善和修正。

此后端流程大致包括一下内容:
1. 逻辑综合(逻辑综合是干吗的就不用解释了把?)
2. 设计的形式验证(工具 formality)
形式验证就是功能验证,主要验证流程中的各个阶段的代码功能是否一致,包括综合前 RTL
代码和综合后网表的验证,因为如今 IC 设计的规模越来越大,如果对门级网表进行动态仿
真的话,会花费较长的时间(规模大的话甚至要数星期),这对于一个对时间要求严格(设
计周期短)的 asic 设计来说是不可容忍的,而形式验证只用几小时即可完成一个大型的验
证。另外,因为版图后做了时钟树综合,时钟树的插入意味着进入布图工具的原来的网表已
经被修改了,所以有必要验证与原来的网表是逻辑等价的。
3. 静态时序分析(STA),某种程度上来说,STA 是 ASIC 设计中最重要的步骤,使用
primetime 对整个设计布图前的静态时序分析,没有时序违规,则进入下一步,否则重
新进行综合。 (PR 后也需作 signoff 的时序分析)
4. 使用 cadence 公司的 SOCencounter 对综合后的网表进行自动布局布线(APR)
5. 自动布局以后得到具体的延时信息(sdf 文件,由寄生 RC 和互联 RC 所组成)反标注到
网表,再做静态时序分析,与综合类似,静态时序分析是一个迭代的过程,它与芯片布
局布线的联系非常紧密,这个操作通常是需要执行许多次才能满足时序需求,如果没违
规,则进入下一步。
6. APR 后的门级功能仿真(如果需要)
7. 进行 DRC 和 LVS,如果通过,则进入下一步。(设计规则检查 DRC (Design Rule Check) ‫ ء‬一致性检查 LVS (Layout
Versus schematic) ‫ ء‬后仿真(Post-Simulation) )

8. 用 abstract 对此 8*8 乘法器进行抽取,产生一个 lef 文件,相当于一个 hard macro。


9. 将此 macro 作为一个模块在另外一个 top 设计中进行调用。
10. 设计一个新的 ASIC,第二次设计,我们需要添加 PAD,因为没有 PAD,就不是一个完整
的芯片,具体操作下面会说。
11. 重复第 4 到 7 步
1. 逻辑综合
1) 设计的 8*8verilog 代码如下
module mux (clk,clr,data1,data2,dataout);
input clk,clr;
input [7:0] data1,data2;
output reg [15:0] dataout;

always @(posedge clk)


begin
if(!clr)
begin
dataout<=0;
end
else
begin
dataout<=data1*data2;
end
end
endmodule
2) 综合之前,我们要选取库,写好约束条件,修改 dc 的启动文件 synopsys_dc.setup,目标
库选择 TSMC(此设计都是用 TSMC18 的库)的 typical.db。(选择 max 库会比较好)
DC 的命令众多,但是最基本的命令差不多,此设计的约束文件命令如下:
create_clock -period 10 [get_ports clk] //用于时钟的创建
set_clock_latency -source -max 0.2 [get_ports clk] //外部时钟到 core 的 clk 连线延时
set_clock_latency -max 0.1 [get_ports clk] //core 的 clk 到寄存器 clk 端的 net 连线延时
set_clock_uncertainty -setup 2 [get_ports clk] //时钟延时的不确定性,求 setup 违规时会被计算
进去
set_clock_uncertainty –hold 1 【all_clocks】
set_input_delay -max 0.5 -clock clk [get_ports [list [remove_from_coll [all_inputs] clk] ] //
输入延时,外部信号到 input 端的连线延时
set_output_delay -max 0.5 -clock clk [all_outputs] //输出延时

set_driving_cell -lib_cell INVX4 [all_inputs] //输入端的驱动强度


set_load -pin_load 0.0659726 [all_outputs] //输出端的驱动力

set_wire_load_model -name tsmc18_wl10 -library typical //内部 net 的连线模型


set_wire_load_mode enclosed //定义建模连线负载相关模式
set_max_area 0
compile
report_timing
report_constraint
change_names -rule verilog –hier
set_fix_multiple_ports_net –all
write -format verilog -hier -output mux.sv //输出网表,自动布局布线需要
write -format ddc -hier -output mux.ddc //输出 ddc
write_sdf mux.sdf //输出延时文件,静态时序分析时需要
write_sdc mux.sdc //输出约束信息,自动布局布线需要
3) 逻辑综合
启动 design_vision。Read->mux.v

输入约束文件。File->excute script->verti.con
之后会产生 mux.sv,mux.sdc,mux.sdf,mux.ddc 等文件
4) 时序分析
综合以后我们需要分析一下时序,看时序是否符合我们的要求,综合实际上是一个 setup
时间的满足过程,但是我们综合的时候,连线的负载只是库提供的(即上面的 wire_load) ,
并不是实际的延时,所以一般做完综合以后,时间余量(slack)应该为时钟的 30%(经验
值) ,以便为后面实际布局布线留下充足的延时空间。因为如果 slack 太小,甚至接近于 0,
虽然我们看起来是没有时序违规的,但是实际布局以后,时序肯定无法满足。
使用 report_timing 命令,可以查看时序分析报告:
****************************************
Report : timing
-path full
-delay max
-max_paths 1
-sort_by group
Design : mux
Version: D-2010.03-SP1
Date : Fri Jul 2 12:29:44 2010
****************************************

Operating Conditions: typical Library: typical(模型库)


Wire Load Model Mode: enclosed

Startpoint: data2[4] (input port clocked by clk)


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

Des/Clust/Port Wire Load Model Library


------------------------------------------------
mux tsmc18_wl10 typical (线载模型及库)

Point Incr Path

--------------------------------------------------------------------------
clock clk (rise edge) 0.00 0.00
clock network delay (ideal) 0.00 0.00
input external delay 0.50 0.50 f
data2[4] (in) 0.01 0.51 f
mult_14/b[4] (mux_DW_mult_uns_0) 0.00 0.51 f
mult_14/U131/Y (INVX1) 0.54 1.05 r
mult_14/U161/Y (NOR2X1) 0.14 1.18 f
mult_14/U39/S (CMPR42X1) 0.68 1.87 f
mult_14/U12/CO (ADDFX2) 0.32 2.19 f
mult_14/U11/CO (ADDFX2) 0.23 2.42 f
mult_14/U10/CO (ADDFX2) 0.23 2.65 f
mult_14/U9/CO (ADDFX2) 0.23 2.88 f
mult_14/U8/CO (ADDFX2) 0.23 3.10 f
mult_14/U7/CO (ADDFX2) 0.23 3.33 f
mult_14/U6/CO (ADDFX2) 0.23 3.56 f
mult_14/U5/CO (ADDFX2) 0.23 3.79 f
mult_14/U4/CO (ADDFX2) 0.23 4.02 f
mult_14/U3/CO (ADDFX2) 0.23 4.25 f
mult_14/U2/CO (ADDFX2) 0.22 4.47 f
mult_14/product[15] (mux_DW_mult_uns_0) 0.00 4.47 f
dataout_reg_15_/RN (DFFTRXL) 0.00 4.47 f
data arrival time 4.47

clock clk (rise edge) 10.00 10.00


clock network delay (ideal) 0.30 10.30
clock uncertainty -0.10 10.20
dataout_reg_15_/CK (DFFTRXL) 0.00 10.20 r
library setup time -0.19 10.01
data required time 10.01

--------------------------------------------------------------------------
data required time 10.01
data arrival time -4.47
--------------------------------------------------------------------------
slack (MET) 5.55
我们来看以上报告,dc 报告的时候会显示出关键路径,即延时最大的路径,时序分析
包括两段,前面一段是信号的延迟时间,即 data arrival time 为 4.47,下面是计算要
求时间,也即相对于时钟,设计所能忍受的最大延时,由于到达寄存器 clk 端延时,即
clock network delay,所以设计增加了 0.30 的余量,同样由于时钟的不确定度(可能
提前也可能延后 0.1),我们取最坏情况,就是时钟超前 0.1,则时间余量减去 0.1,最
后一个是门的建立时间要求,是 0.19,最后得到数据的要求时间。
Slack 是要求时间减去到达时间的差值,slack 越大越好。越大说明留给布局布线
的时序越宽松。从报告中我们看出,时序余量为 5.55,说明时序达到了要求,足够满足
我们以后布局布线的时序要求。
当然,我们有专门的时序分析工具,primetime,下面会稍微介绍。

2. 形式验证
1) 怎么保证综合前和综合后的网表逻辑功能是一致的呢,对门级网表进行动态仿真,又太
浪费时间,于是,一款强大的验证工具 formality,给了我们很好的帮助。
2) 形式验证数据准备:综合前 RTL 代码,综合后的网表,综合所用到的库。
3) 验证过程如下:
1. 首先我们打开 formality,命令为 fm_shell(命令行界面) ,formality(图形界面)。初学
者一般使用图形界面,使用图形界面的时候,工具会自动产生一个 log 文件,记录命令,
我们可以将这个文件内容做一个 fms 格式,这样在下次验证的时候可以使用命令界面。
2. 打开 formality 如下
第一步:首先我们加入原 RTL 代码,reference->read_design file->verilog->mux.v,选择好以
后 load file

第二步:然后选择库,没加库之前,FM 会自动加载与工艺无关的库,所以我们要自己把自
己的目标库加上去,reference->read DB libarary->DB,选择 typical.db
第三步:设置 top 名 reference->set top design 我们选择 mux 为 top 名
同样的方法对网表进行设置(第二个菜单栏 implementation)

然后转到第四栏,点击 run matching

最后转到第五栏,verify,如果网表无错,会显示验证通过。
3 静态时序分析
静态时序分析主要针对大型 ASIC 设计,

4 自动布局布线
1)数据准备
第一:需要综合后的网表以及时序约束文件 mux.sv,mux.sdc
第 二 : 需 要 自 动 布 局 布 线 的 物 理 库 ( lef 文 件 , 这 里 用 到 tsmc18_6lm_cic.lef,
tsmc18_6lm_antenna_cic.lef)
为了能够了解 lef 文档的作用,这里对 lef 做简单的介绍,lef 一般分为两种:
一种是技术物理库,主要包含工艺信息,设计规则信息,金属通孔信息等。下例是对金属一
层的定义,TYPE 指明 METAL1 是可布线层,WIDTH 定义的是 METAL1 的默认布线宽度,
SPACING 用于设定 METAL1 布线间距。DIRECTION HORIZONTAL 指明 METAL1 是用于
水平走线,当然这并不意味着它不能垂直走线,在一些布线资源较少的区域,还是可以选择
垂直布线的。具体介绍,可以参考相关技术文档。
LAYER METAL1
TYPE ROUTING ;
WIDTH 0.230 ;
MAXWIDTH 9.9 ;
AREA 0.202 ;
SPACING 0.230 ;
SPACING 0.6 RANGE 10.0 100000.0 ;
PITCH 0.560 ;
DIRECTION HORIZONTAL ;
EDGECAPACITANCE 9.1090e-05 ;
END METAL1
另外一种就是单元物理库,定义了单元库中各单元的信息,文件又有两部分一种是 SITE 语
句对布局(placement)最小单位的定义,另一部分是采用 MACRO 语句对单元属性及几何
形状的描述,下例是对一个与门为例来看看 lef 是如何描述它的。MACRO 是单元定义的关
键字,每一个 MACRO 代表一个单元。CLASS core 说明该单元是用于芯片的核心区,SIZE
确定了单元的面积大小,比如 5.04 是代表该单元的高度,后面我们做单元供电 route 的时候,
可以看到它们的宽度就是这个数值。再后面就是定义引脚 A,B,Y,VDD,VSS 等。
MACRO AND2X1
CLASS CORE ;
FOREIGN AND2X1 0.000 0.000 ;
ORIGIN 0.000 0.000 ;
LEQ AND2XL ;
SIZE 2.640 BY 5.040 ;
SYMMETRY x y ;
SITE tsm3site ;
PIN Y
DIRECTION OUTPUT ;
PORT
LAYER METAL1 ;
RECT 2.355 2.380 2.500 2.660 ;
END
END Y
PIN B
DIRECTION INPUT ;
PORT
LAYER METAL1 ;
RECT 0.800 2.315 1.215 2.895 ;
END
END B
PIN A
DIRECTION INPUT ;
PORT
LAYER METAL1 ;
RECT 0.150 1.820 0.565 2.315 ;
END
END A
PIN VSS
DIRECTION INOUT ;
USE ground ;
SHAPE ABUTMENT ;
PORT
LAYER METAL1 ;
RECT 1.790 -0.400 2.640 0.400 ;
RECT 1.450 -0.400 1.790 0.575 ;
RECT 0.000 -0.400 1.450 0.400 ;
END
END VSS
PIN VDD
DIRECTION INOUT ;
USE power ;
SHAPE ABUTMENT ;
PORT
LAYER METAL1 ;
RECT 1.755 4.640 2.640 5.440
END
END VDD
OBS
LAYER METAL1 ;
RECT 1.835 1.935 1.885 2.355 ;
END
END AND2X1

第三:时序库文件,typical.lib,也就是时序文件,定义了门的各种时序信息,某种意义来讲,
这个和综合使用的 db 库是等价的。
2)布局布线过程:
第一步:打开 encounter 把数据输入,另外在 advanced 栏的 Power 相应位置填上 VDD,和
VSS。如下图,设置完以后,记得把设置的配置文件做一个 save 以便于下次使用
第二步:打开以后,我们可以看到芯片区域,左边粉红色的就是标准单元,中间那个就是我
们要设计的区域,64%是指 cell 面积的占有率,一般来说控制在 70%左右,布线的时候不会
引起拥塞。

另外我们需要对芯片进行稍微的更改,Floorplan->specify floorplan.,将 core to IO 那些项都


填上 45,留给电源环的放置。

第三步:添加电源环

设置如下图,
NET 填写 VDD 和 VSS,layer 选择顶层的两层金属,宽度设置为 20(这个不定,可以根据
实际设计来定) ,offset 选择 center in channel,则电源环会被设置在 IO 与 core 之间。
之后电源环就加进去了,当然这是一个小电路,电源规划比较简单,对于一个复杂的电路,
还需要横竖添加 stripes,降低 IRdrop。
第四步:自动布局以及布置标准单元,因为此设计较小,并没有 block,所以可以直接进行
标准单元的放置。Place->standard cells and blocaks->OK

然后我们发现标准单元已经被加进去了:

第五步:布置好了以后,我们需要将电源,地,等接口先连接起来,首先我们在 floorplan
中选择 global net connection,分别将 VDD,VSS 等都连接起来。
然后我们需要 specify route 将电源和地线先连接起来,选择 route->specify route

因为我们这个设计只有标准单元,所以我们只要选择标准单元的布线即可:

完成以后,点击 OK,会得到下面的图:每行的 row 都有线连接到外面的电源环

第六步:时钟树综合(CTS),这是一个 APR 设计中最重要的一环,为什么要进行时钟树综


合呢,简单地说,因为信号传输的延时,我们需要让相应路径的时钟路径的也具有同样的延
时,通过添加时钟缓冲器的方法,来消除各路径的建立时间,具体请参考相关书籍和资料。
添加好时钟树以后的版图如下:加了时钟树以后的版图密集了很多,因为加了很多 buf。
时钟树的脚本:
AutoCTSRootPin clk
Period 10ns
MaxDelay 500ps # set_clock_latency
MinDelay 0ps # set_clock_latency
MaxSkew 100ps
SinkMaxTran 400ps
BufMaxTran 400ps
Obstruction NO
DetailReport YES
PadBufAfterGate NO
RouteClkNet NO
PostOpt YES
OptAddBuffer YES
OptAddBufferLimit 100
NoGating NO
Buffer CLKBUFX1 CLKBUFXL CLKBUFX2 CLKBUFX3 CLKBUFX4 CLKBUFX8
CLKBUFX12 CLKBUFX16 CLKBUFX20 CLKINVXL CLKINVX1 CLKINVX2 CLKINVX3
CLKINVX4 CLKINVX8 CLKINVX12 CLKINVX16 CLKINVX20
END
然后将脚本选中,并进行时钟树综合。
第七步:优化设计,命令 optDesign –postCTS,然后 report_timing 查看时序报告,确定无
违规,再进行完全布线。

第八步:完全布线,route ->nanoroute->route

之后得到的版图如下所示:
第九步:保存设计,提取需要的数据。
这里特别注意提取 gds 文件的时候,需要指定库文件中的 streamOut.map 文件,和 merge gds
(tsmc18_core.gds)文件,如图所示
保存网表,并将此版图提取的网表做一次 formality,与原代码匹配成功。

再提取 def 文件,保存为 mux.def

5 第二次静态时序分析
用版图实际提取的延时文件进行
6 APR 后仿真
用 modelsim 对版图提取的网表和 sdf 文件进行仿真。

7 用 calibre 对版图进行 DRC 及其 LVS 验证


在做这步之前,我们需要把相关的文档拷贝到 icfb 的工作目录下
Encounter 导出的 gds 文档:这里是 mux8.gds(注意 merge 库的 map 文件)
技术文档如:0.18um_Virtuoso4.4.tf,可以在厂家提供的库中去找
显示文件:display.drf
Caliber 验证文件:drc,lvs 文档
第一步:将 encounter 的版图数据导入 virtuoso,打开 icfb&,选择 file->import->stream

然后将版图信息和技术文件填入:
导入成功以后会出现我们所做的库,mux 就是我们 encounter 中所画的版图。

我们把版图打开:
这就是我们所画的版图然后在此进行 drc,和 lvs,通过以后再进行下面的工作。
第二步:drc 检查
此处有错,并不是逻辑有问题,是因为密度不够的问题,需要在 encounter 阶段加 FILLER,
FILLER 是与逻辑无关的,因为代工厂的流片加工要求,需要加的,密度不够,加工容易引
起问题。所以如果 DRC 报类似错误,如果是需要流片的版图,除非代工厂同意,否则必须
清除这些错误。
第三步:lvs 检查
1)Lvs 检查之前,我们需要把综合后的 verilog 文件转换成网表文件,用于 lvs,方法如下:
终端下执行:v2lvs -v mux.v -l tsmc18_lvs.v -o CHIP.spi -s tsmc18_lvs.spi -c cic_ -n
calibre -lvs -spice layout.spi -hier -auto Calibre-lvs-cur_soce,之后会得到一个 CHIP.spi 的网表
文件。 (此处的 verilog 的转换是用库中的 lvs.cmd 产生)
2)用来 lvs 的网表我们选择之前导出 CHIP.spi:
然后 run lvs,匹配成功!

8 用 abstract 对模块进行抽取
我们把 8*8 乘法器模块用 abstract 工具导出 lef,作为硬核,用于后面自动布局布线的调用,
我们可以从此试验中找到模数混合自动版图的设计思想。
Abstract Def=>Lef
第一步:创建一个新的 library,并关联一个 tf 文件。
第二步:导入 standcell.gds

注:(1)不需要输入 streamOut.map 也不用点上(no merge) 不需


要更改。
Top Cell Name 为空

第三步:导入 standcell.lef

第四步:导入 mux.def

第五步:打开 library manager 在 mux 库里打开 mux 的 layout,并选择 tools=>layout。


第六步:选择 Edit=>Search ,点击 Add Criteria ,如下设置,选择 aplly ,在选择 Replace All。

第七步:保存退出

第八步:打开 abstract,并打开 mux 库。然后把 mux 模块从 core 导入到 block 当中,方法:
点击 mux,然后 cell=>move=>block=>OK。

第九步:点击 GDS 图中 label,然后点击 Q 查看 Properity。看看是什么层,然后看看下面的


net 的 Properity 是什么层,以及是什么 purpose。 层:METAL3,Purpose:

pin。具体含义主要看 abstract UG。

<1> 点击 ,输入 Map text labels to pins

Map text labels to pins 的书写格式及含义参考 abstract UG。

<2>点击

<3>点击

<4> Export lef

<5>查看 abstract.lef 里面有没有 VDD 和 VSS


之后我们得到一个该模块的 lef 文件,下面我们就用这个模块做一次调用。

9 将此 macro 作为一个模块在另外一个 top 设计中进行调用。


第一步:首先我们还是回到综合,我们重新设计一个 top,这个 top 将包含新的逻辑功能,
之前的 mux 模块,还有 PAD 模块。这个设计的大概框图如下:

PDIDGZ 为数字输入 IO 口
PDO04CDG 为数字输出 IO 口
PVDD1DGZ 为供电 PAD 高电端
PVSS1DGZ 为供电 PAD 的地电端
Multiple 为之前做的宏模块
Mux 为新加逻辑
第二步,代码的改写:
我们重新编写过 verilog 代码(带 PAD),带 PAD 做综合有个好处,可以不用设置输入输出
端口的驱动,因为 PAD 的驱动已经很大了,这样综合出的结果更接近实际。
新的 verilog 代码如下:
module mux_1 (clk,clr,a,b,y);//(这里我们引用了新的逻辑,注意这个 mux_1 和之前的
没半点关系,只是为了体现调用关系随便加的一个而已)
input clk,clr;
input [7:0] a,b;
output [15:0] y;
reg [15:0] y;
always @(posedge clk)
begin
if(!clr)
begin
y<=0;
end
else
begin
y<=a*b;
end
end
endmodule
module
PAD(clk_pcb,clk_core,clr_pcb,clr_core,data1_pcb,data1_core,data2_pcb,data2_core
,dataout_core,dataout_pcb);(这是 PAD 模块,注意结合前面的框图是想想是如何加的)
input clk_pcb,clr_pcb;
output clk_core ,clr_core;
input [7:0] data1_pcb,data2_pcb;
output [7:0] data1_core,data2_core;
input [15:0] dataout_core;
output [15:0] dataout_pcb;

PDIDGZ PAD_CLK (.PAD(clk_pcb),.C(clk_core));


PDIDGZ PAD_CLR (.PAD(clr_pcb),.C(clr_core));
PDIDGZ PAD_DATA1_0 (.PAD(data1_pcb[0]),.C(data1_core[0]));
PDIDGZ PAD_DATA1_1 (.PAD(data1_pcb[1]),.C(data1_core[1]));
PDIDGZ PAD_DATA1_2 (.PAD(data1_pcb[2]),.C(data1_core[2]));
PDIDGZ PAD_DATA1_3 (.PAD(data1_pcb[3]),.C(data1_core[3]));
PDIDGZ PAD_DATA1_4 (.PAD(data1_pcb[4]),.C(data1_core[4]));
PDIDGZ PAD_DATA1_5 (.PAD(data1_pcb[5]),.C(data1_core[5]));
PDIDGZ PAD_DATA1_6 (.PAD(data1_pcb[6]),.C(data1_core[6]));
PDIDGZ PAD_DATA1_7 (.PAD(data1_pcb[7]),.C(data1_core[7]));
PDIDGZ PAD_DATA2_0 (.PAD(data2_pcb[0]),.C(data2_core[0]));
PDIDGZ PAD_DATA2_1 (.PAD(data2_pcb[1]),.C(data2_core[1]));
PDIDGZ PAD_DATA2_2 (.PAD(data2_pcb[2]),.C(data2_core[2]));
PDIDGZ PAD_DATA2_3 (.PAD(data2_pcb[3]),.C(data2_core[3]));
PDIDGZ PAD_DATA2_4 (.PAD(data2_pcb[4]),.C(data2_core[4]));
PDIDGZ PAD_DATA2_5 (.PAD(data2_pcb[5]),.C(data2_core[5]));
PDIDGZ PAD_DATA2_6 (.PAD(data2_pcb[6]),.C(data2_core[6]));
PDIDGZ PAD_DATA2_7 (.PAD(data2_pcb[7]),.C(data2_core[7]));
PDO04CDG PAD_DATAOUT_0 (.I(dataout_core[0]),.PAD(dataout_pcb[0]));
PDO04CDG PAD_DATAOUT_1 (.I(dataout_core[1]),.PAD(dataout_pcb[1]));
PDO04CDG PAD_DATAOUT_2 (.I(dataout_core[2]),.PAD(dataout_pcb[2]));
PDO04CDG PAD_DATAOUT_3 (.I(dataout_core[3]),.PAD(dataout_pcb[3]));
PDO04CDG PAD_DATAOUT_4 (.I(dataout_core[4]),.PAD(dataout_pcb[4]));
PDO04CDG PAD_DATAOUT_5 (.I(dataout_core[5]),.PAD(dataout_pcb[5]));
PDO04CDG PAD_DATAOUT_6 (.I(dataout_core[6]),.PAD(dataout_pcb[6]));
PDO04CDG PAD_DATAOUT_7 (.I(dataout_core[7]),.PAD(dataout_pcb[7]));
PDO04CDG PAD_DATAOUT_8 (.I(dataout_core[8]),.PAD(dataout_pcb[8]));
PDO04CDG PAD_DATAOUT_9 (.I(dataout_core[9]),.PAD(dataout_pcb[9]));
PDO04CDG PAD_DATAOUT_10 (.I(dataout_core[10]),.PAD(dataout_pcb[10]));
PDO04CDG PAD_DATAOUT_11 (.I(dataout_core[11]),.PAD(dataout_pcb[11]));
PDO04CDG PAD_DATAOUT_12 (.I(dataout_core[12]),.PAD(dataout_pcb[12]));
PDO04CDG PAD_DATAOUT_13 (.I(dataout_core[13]),.PAD(dataout_pcb[13]));
PDO04CDG PAD_DATAOUT_14 (.I(dataout_core[14]),.PAD(dataout_pcb[14]));
PDO04CDG PAD_DATAOUT_15 (.I(dataout_core[15]),.PAD(dataout_pcb[15]));
PVDD1DGZ vdd1 (); (现在不用加的)
PVDD1DGZ vdd2 ();
PVDD1DGZ vdd3 ();
PVDD1DGZ vdd4 ();
PVSS1DGZ vss1 ();
PVSS1DGZ vss2 ();
PVSS1DGZ vss3 ();
PVSS1DGZ vss4 ();
PCORNERDG c1 ();
PCORNERDG c2 ();
PCORNERDG c3 ();
PCORNERDG c4 ();
endmodule
#############################顶层模块#########################
module top(clock,clear,da1,da2,dataout_out);
input clock,clear;
input [7:0] da1,da2;
output [15:0] dataout_out;
wire clk_core,clr_core;
wire [7:0] data1_core,data2_core;
wire [15:0] dataout_core;
wire [15:0] y;
PAD
PAD_TOP(.clk_pcb(clock),.clk_core(clk_core),.clr_pcb(clear),.clr_core(clr_core)
,.data1_pcb(da1),.data1_core(data1_core),.data2_pcb(da2),.data2_core(data2_core
),.dataout_core(dataout_core),.dataout_pcb(dataout_out));

mux_1 mux_1 (.clk(clk_core),.clr(clr_core),.a(data1_core),.b(data2_core),.y(y));


mux mutiple
(.clk(clk_core),.clr(clr_core),.data1(y[15:8]),.data2(y[7:0]),.dataout(dataout_
core));(这里是对硬核的调用)
endmodule

第三步:逻辑综合
注意的是,我们在逻辑综合之前,需要加如 mux 的 db 库文件,此文件由 encounter 布局布
线以后产生的延时文件再经过 pt 静态时序分析以后产生。
我们给顶层模块加如约束:
Current_design top
link
create_clock -period 10 [get_ports clock]
set_clock_latency -source -max 0.2 [get_ports clock]
set_clock_latency -max 0.1 [get_ports clock]
set_clock_uncertainty -setup 0.01 [get_ports clock]

set_input_delay -max 0.5 -clock clock [all_inputs]


set_output_delay -max 0.5 -clock clock [all_outputs]

#set_driving_cell -lib_cell INVX4 [all_inputs]


#set_load -pin_load 0.0659726 [all_outputs]

set_wire_load_model -name tsmc18_wl10 -library typical


set_wire_load_mode enclosed
set_dont_touch mux (注意此处,就是综合的时候不针对 mux 进行综合,综合工具会自动
跨越边界对其他逻辑进行综合)

set_dont_touch_network [all_clocks]

compile -boundary
change_names -rule verilog -hier
write -format verilog -hier -output top.sv
write -format ddc -hier -output top.ddc
write_sdf top.sdf
write_sdc top.sdc
第四步:布局布线
用综合得到的网表(top.sv)和约束文件(sdc) 。并将之前的 mux 模块的 lef 文档准备好。
这里碰到了一个问题,在逻辑综合之前的代码我已经加如了 PAD 的 VDD ,VSS 和 corner,
但是综合完以后就不见了,原因不明,这时在布局之前就要手动添加上去。
数据准备:
顶层模块网表文件:mux.sv
物理库文件:tsmc18_6lm_cic.lef(tech 以及 std 的 lef),mux_block.lef 和 PAD 的 lef
时序文件:对应于上面的 lib 文件,typical.lib,block 的 lib(由 PT 产生),PAD 的 lib
Io 文件:可以自己定义顶层端口的位置(下面会介如何做 io 文件)
Sdc 文件:综合后产生的约束文件。
Io 文件的设置,主要由四个方向决定,N,W,S,E 就和我们英文里的四个方向的首字母一样,
当然还有 NW,WS,SE,NE,四个角,是用与 corner 的摆放,该设计有 34 个口,外加 8 个供
电 PAD,加上四个 CORNER 总共有 46 个 PAD,主要的是 42 个 PAD,我们可以将这 42 个
PAD 放到自己想设置的位置,对于一个真正的设计,要考虑以后连线的长度,内部模块摆
放位置等,来合理安排 io 的位置。
如图所示为该设计的 PAD 布局图:

DATA_OUT_13
DATA_OUT_14
DATA_OUT_15
DATA_OUT_12

PAD_CLK

DATA1_0
DATA1_1
DATA1_2
DATA1_3
vss2
vdd2
DATA_OUT_11 DATA1_4
DATA_OUT_10 DATA1_5
DATA_OUT_9 DATA1_6
DATA_OUT_8 DATA1_7
vss1 vss3
vdd1 TOP vdd3
DATA_OUT_7 DATA2_0
DATA_OUT_6 DATA2_1
DATA_OUT_5 DATA2_2
DATA_OUT_4 DATA2_3
DATA_OUT_3
DATA_OUT_2
DATA_OUT_1
DATA_OUT_0

PAD_CLR

DATA2_7
DATA2_6
DATA2_5
DATA2_4
vss4
vdd4

根据此布局图,我们对此设计的 io 文件编辑如下,io 文件对应实际布局中的规则是,N 是


由 io 文件列表的顺序从左到右的放置,W 方向是由下到上的放置,S 同 N,E 同 W。
Pad: PAD_TOP/PAD_DATAOUT_12 N
Pad: PAD_TOP/PAD_DATAOUT_13 N
Pad: PAD_TOP/PAD_DATAOUT_14 N
Pad: PAD_TOP/PAD_DATAOUT_15 N
Pad: PAD_TOP/PAD_CLK N
Pad: PAD_TOP/vss2 N
Pad: PAD_TOP/vdd2 N
Pad: PAD_TOP/PAD_DATA1_0 N
Pad: PAD_TOP/PAD_DATA1_1 N
Pad: PAD_TOP/PAD_DATA1_2 N
Pad: PAD_TOP/PAD_DATA1_3 N
Pad: PAD_TOP/c1 NE
Orient: R0
Pad: PAD_TOP/c2 SW
Pad: PAD_TOP/PAD_DATAOUT_4 W
Pad: PAD_TOP/PAD_DATAOUT_5 W
Pad: PAD_TOP/PAD_DATAOUT_6 W
Pad: PAD_TOP/PAD_DATAOUT_7 W

Pad: PAD_TOP/vdd1 W
Pad: PAD_TOP/vss1 W
Pad: PAD_TOP/PAD_DATAOUT_8 W
Pad: PAD_TOP/PAD_DATAOUT_9 W
Pad: PAD_TOP/PAD_DATAOUT_10 W
Pad: PAD_TOP/PAD_DATAOUT_11 W
Pad: PAD_TOP/c3 NW
Pad: PAD_TOP/PAD_DATAOUT_0 S
Pad: PAD_TOP/PAD_DATAOUT_1 S
Pad: PAD_TOP/PAD_DATAOUT_2 S
Pad: PAD_TOP/PAD_DATAOUT_3 W
Pad: PAD_TOP/PAD_CLR S
Pad: PAD_TOP/vdd3 S
Pad: PAD_TOP/vss3 S
Pad: PAD_TOP/PAD_DATA2_7 S
Pad: PAD_TOP/PAD_DATA2_6 S
Pad: PAD_TOP/PAD_DATA2_5 S
Pad: PAD_TOP/PAD_DATA2_4 S

Pad: PAD_TOP/PAD_DATA2_3 E
Pad: PAD_TOP/PAD_DATA2_2 E
Pad: PAD_TOP/PAD_DATA2_1 E
Pad: PAD_TOP/PAD_DATA2_0 E
Pad: PAD_TOP/vdd4 E
Pad: PAD_TOP/vss4 E
Pad: PAD_TOP/PAD_DATA1_7 E
Pad: PAD_TOP/PAD_DATA1_6 E
Pad: PAD_TOP/PAD_DATA1_5 E
Pad: PAD_TOP/PAD_DATA1_4 E
一切准备好以后,我们导入所有的准备数据会看到一个有 PAD 和宏模块的的芯片图
因为 PAD 的面积较大,所以其他单元和模块看起来就比较小了。
第五步:布局
由于 PAD 的存在,die 的尺寸会有个最小值,这样的话,标准单元就显得很小了,所以利用
率也很低,我们可以稍微调整下整个芯片区的布局,提高利用率,当然这个是会根据你设置
的 core 区大小等都有关系,只有自己亲自使用时会感受到这个区别。

之后我们布置可以选择自动布局
然后添加电源环

添加完电源环,我们要先把 PAD 的电源和地端连接到电源环上,然后 sroute,我们会看到,


VDD 和 VSS 这 8 个的 PAD 就连接到了电源环上,这就是以后从外部给内部供电的接口。

然后是标准单元放置
添加标准单元的 rail,即给标准单元供电的线,然后是时钟树综合再全局布线,。最后得到
版图如下:

之后就是做类似的 drc,lvs 验证,这里就不再重复。

You might also like