后仿知识总结
后仿介绍
参考链接:https://www.cnblogs.com/xh13dream/p/8576343.html
一:什么是后仿
前仿不包括时序信息,即当作理想的器件看待,仅仅验证代码的功能;后仿,在有时序信息,有延迟情况下(器件自身的延迟,传输线上的延时等,与工艺器件有关)的仿真;后仿主要关注Toggle覆盖率,因为门级网表里面没有RTL级代码,没有if,case等,都是与或非门等。
RTL级通过DC综合得到门级网表,布局布线得到门级网表,将两个门级网表加起来才是真正的网表文件;在本文中,我们只关注DC吐出来的网表以说明后仿。
+rad可以对仿真进行优化。
DC后不仅生成门级网表(也是.v文件),还产生.sdf文件(standard delay format,记录单元的时序的信息)。
二:后仿流程
三:SDF文件主要内容
Delays(module,device,interconnect,port)
Timing checks(setup,hold,setuphold,recovery,removal,recrem)
Timing constrains(pathconstraint,skewconstraint,sum,diff)
Timing environment(arrival,departure,slack,waveform)
包括design,时间,工艺,版本,电压,温度,延时信息,基本单元延时信息等。
四:综合后在vcs后仿具体步骤
1: 将综合后的网表文件.v拷贝到rtl代码文件夹里(即源文件夹里),并将原源文件(也是.v)改成.v.bak文件,防止make找不到正确的.v文件;
将综合后的SDF文件拷贝到tb文件夹(即testbench文件夹里);
2: 在top层文件里(即testbench文件夹)反标添加SDF;
例如:
3: 在makefile里添加说明(compile里)
#vcs dut_gate.v -v sim_lib.v //.v是网表文件,工艺库-v
4: make com->make sim->make dve->在dve文件上观察波形,发现后仿波形不纯净
五:其他
1: 若SDF文件很大,可以进行预编译,dut.sdf文件变为dut.sdf_c
2: 选中delay方式:在compile开关选项上加+mindelays/+typedelays/+maxdelays
或者在compile开关选项上加+allmtm,在simulate在加+mindelays/+typedelays/+maxdelays
3: 惯性延迟(器件自带),传输延迟
4: 若使用预编译方式,则+rad失效
后仿时序检查
参考链接:https://www.cnblogs.com/tshell/archive/2013/03/13/2957447.html
解决了后仿时序检查出错
第一次做后仿,就出现了问题,发现如果不加SDF,波形也会有延时:
后来发现,这些延时都是仿真库中定义的,而且加载SDF后的延时就是实际的延时了,而不是库中定义的延时,但出现了好多违例,modelsim波形如下:
箭头处出现了hold time违例,原来是仿真库中含有时序检查函数:
KaTeX parse error: Expected 'EOF', got '&' at position 22: …old(posedge CK &̲&& (SandR == 1)…J
C
K
,
t
h
o
l
d
CK, thold
CK,tholdJ$CK, NOTIFIER);
KaTeX parse error: Expected 'EOF', got '&' at position 22: …old(posedge CK &̲&& (SandR == 1)…J
C
K
,
t
h
o
l
d
CK, thold
CK,tholdJ$CK, NOTIFIER);
KaTeX parse error: Expected 'EOF', got '&' at position 22: …old(posedge CK &̲&& (SandR == 1)…K
C
K
,
t
h
o
l
d
CK, thold
CK,tholdK$CK, NOTIFIER);
KaTeX parse error: Expected 'EOF', got '&' at position 22: …old(posedge CK &̲&& (SandR == 1)…K
C
K
,
t
h
o
l
d
CK, thold
CK,tholdK$CK, NOTIFIER);
而我有几条路径不满足仿真库中定义的hold time(500ps),但我奇怪:SDF中不是也有时序检查函数吗?为什么仿真库中也有,不是多此一举吗,不会覆盖SDF中的函数吗,后来发现SDF中并没有检查hold time:
(TIMINGCHECK
(WIDTH (posedge CK) (0.211::0.211))
(WIDTH (negedge CK) (0.386::0.386))
(SETUPHOLD (posedge D) (posedge CK) (0.258::0.258) ())
(SETUPHOLD (negedge D) (posedge CK) (0.494::0.494) ())
(SETUPHOLD (posedge RN) (posedge CK) (0.243::0.243) ())
(SETUPHOLD (negedge RN) (posedge CK) (0.501::0.501) ())
后来我针对违例的cell在SDF中手动加入了保持时间的定义 : (SETUPHOLD (posedge D) (posedge CK) (0.258::0.258) (0.123::0.123)),然后再仿真,modelsim没有报错了,可见如果SDF和仿真库中都有时序检查函数,那么SDF具有高的优先级。
但是不明白encounter为什么生成的SDF中没有检查hold time,只好先修改布局布线,将encounter的hold time的threshold设置为仿真库中的500ps(options——set mode——mode setup),如下图:
,生成新的版图和SDF,网表,再仿真,modelsim就没有报错了
Standard Cell的仿真模型
参考链接:https://blog.csdn.net/verybing/article/details/7265954
Standard Cell的仿真模型:首先我们先看一个stand cell的仿真模型
一般情况下,仿真模型包括两个部分,一个部分是功能部分也就是这个standcell的功能,可以用udp元件或者逻辑功能做表述,第二个部分是时序反标和时序检查部分,这部分主要是提供sdf反标时序,和timingcheck的类型,并且通过系统函数告知仿真者和改变输出值。
`timescale 1ns/1ps
`celldefine
module DFFXL (Q, QN, D, CK);
output Q, QN;
input D, CK;
reg NOTIFIER;//时序检查系统函数和udp功能真值表之间的联系寄存器
supply1 xSN,xRN;
//下面是这个时序cell的功能描述,由元件,udp,逻辑操作组成。
buf IC (clk, CK);
udp_dff I0 (n0, D, clk, xRN, xSN, NOTIFIER);
and I4 (flag, xRN, xSN);
buf I1 (Q, n0);
not I2 (QN, n0);
//specify….endspecify是对基本门级元件输入输出端口的时延描述,称为延时说明块。延时说明块是module中一个独立结构。
specify
specparam//对一些代表时量的延时参数进行定义
tplh$CK$Q = 1.0,
tphl$CK$Q = 1.0,
tplh$CK$QN = 1.0,
tphl$CK$QN = 1.0,
tsetup$D$CK = 1.0,
thold$D$CK = 0.5,
tminpwl$CK = 1.0,
tminpwh$CK = 1.0,
tperiod$CK = 1.0;
//对模块输入输出端口之间的路径延时进行说明
if (flag)
(posedge CK *> (Q +: D)) = (tplh$CK$Q, tphl$CK$Q);
//前半部分时指定路径,后半部分是指定路径延时,若存在多条路径到达一个口在仿真中会选取延时最大的一条路径
if (flag)
(posedge CK *> (QN -: D)) = (tplh$CK$QN, tphl$CK$QN);
//借助时序检验系统任务对模块输入输出时序进行时序检验,一旦发现时序违规,仿真程序就会对违规触发标志位NOTIFIER //反转一次(如果是第一次违规报警,NOTIFIER其被之为1),这会通知udp使输出为X
$setuphold(posedge CK &&& (flag == 1), posedge D, tsetup$D$CK, thold$D$CK, NOTIFIER);
$setuphold(posedge CK &&& (flag == 1), negedge D, tsetup$D$CK, thold$D$CK, NOTIFIER);
$width(negedge CK &&& (flag == 1), tminpwl$CK, 0, NOTIFIER);
$width(posedge CK &&& (flag == 1), tminpwh$CK, 0, NOTIFIER);
$period(posedge CK &&& (flag == 1), tperiod$CK, NOTIFIER);
endspecify
endmodule // DFFXL
`endcelldefine
下面我们接着看一个udp是如何构成的,输入产生输出的,如何和时序检验系统函数进行联系的,其中udp(User Defined Primitives)元件的定义是通过真值表的形式来进行的,可以用真值表来描述组合逻辑UDP和时序逻辑的UDP的逻辑功能。该模块主要由primitive … endprimitive界定。如下:
primitive udp_dff (out, in, clk, clr_, set_, NOTIFIER);
output out;
input in, clk, clr_, set_, NOTIFIER;//NOTIFIER来自时序检验系统函数,注意UDP定义的端口只能是一位宽度的标量类型
reg out;
//真值表的格式:
table
// in clk clr_ set_ NOT : Qt : Qt+1
//
0 r ? 1 ? : ? : 0 ; // clock in 0
1 r 1 ? ? : ? : 1 ; // clock in 1
1 * 1 ? ? : 1 : 1 ; // reduce pessimism
0 * ? 1 ? : 0 : 0 ; // reduce pessimism
? f ? ? ? : ? : - ; // no changes on negedge clk
* b ? ? ? : ? : - ; // no changes when in switches
? ? ? 0 ? : ? : 1 ; // set output
? b 1 * ? : 1 : 1 ; // cover all transistions on set_
1 x 1 * ? : 1 : 1 ; // cover all transistions on set_
? ? 0 1 ? : ? : 0 ; // reset output
? b * 1 ? : 0 : 0 ; // cover all transistions on clr_
0 x * 1 ? : 0 : 0 ; // cover all transistions on clr_
? ? ? ? * : ? : x ; // any notifier changed
//注意-表示输出状态保持不变,?表示输入任意状态,b表示输入端任意状态(不包括X),*表示输入端的任意变化
//从最后一行我们可以看出一旦NOTIFIER发生了任意变化输出端将会输出X!!
endtable
endprimitive // udp_dff
参考文档
https://www.cnblogs.com/xh13dream/p/8576343.html
https://www.cnblogs.com/tshell/archive/2013/03/13/2957447.html
https://blog.csdn.net/verybing/article/details/7265954