在验证仿真过程中,很多人遇到过timescale的问题,其中典型的场景是这样的:“验证环境里加了一个#200ns的延时,希望通过这样带有明确单位的延时,避免timescale设置不同而导致不同的结果;可是奇妙是就是在设置timescale为1ns/1ps和100ps/1ps时,实际的延迟就成了200ns和2000ns,而把#200ns改为#200后,反而无论怎么改timescale,实际延迟都是200ns。”(此案例使用的是vcs 2013)。
本文将详细分析timescale,复现此案例,同时说明如何正确使用timescale。
目录
3 compilation-unit scope特殊之处(vcs)
3.1 compilation-unit scope中的绝对延时
1 仿真时间的相对性和绝对性
仿真时间是由一系列延时累积起来的。
1.1 延时
没有单位的延时,比如#100,是相对的,实际延时取决于当前时间单位;有单位的延时,比如#100ns,则是绝对的。假设当前时间单位是1ns,则#100ns等价于#100;假设当前时间单位是100ps,则#100ns等价于#1000。
延时除了单位,还需要精度,它们分别对应time_unit和time_precision。对于1ns/1ps的time_unit/time_precision设置,#100.1234会被四舍五入为#100.123。
1.2 仿真时间
我们可以通过波形测量和log打印两种方式得到仿真时间,波形测量相对简单,这里只讨论log打印。
有三个系统函数可以得到当前仿真时间:$realtime返回64bit real类型时间数值,$time返回64bit整数,$stime返回32bt无符号整数。$time和$stime会对小数进行四舍五入,鉴于现在时钟频率越来越高,验证环境中只建议使用$realtime。
这三个函数都会按照当前的时间单位按比例缩放,这句话不好理解。换种说法,它们返回的都是延时相对值的累积。
比如对于下面代码(module、program、packages或interface中):
realtime vr_t
#100;
.….
#20.123ns;
vr_t=$realtime;
如果当前时间单位/精度是1ns/1ps,则vr_t=100+20.123=120.123(单位为ns);
如果当前时间单位/精度是100ps/10ps,则首先根据时间精度10ps将#20.123ns四舍五入为#20.12ns,再根据时间单位100ps换算为相对值#201.2,最后得到vr_t=100+201.2=301.2(单位为100ps)。
这就是仿真时间的相对性。相对仿真时间对我们来说意义不大,因为不同模块/线程的时间单位/精度可能是不一样的。为得到仿真时间的绝对值,就需要$timeformat和%t出场了;$timeformat影响%t和交互式输入的延时单位,我们只讨论使用%t打印时的情况。
SV标准中$timeformat的定义如图:
$timeformat四个参数分别对应%t的打印单位、精度、后缀和打印的最小位宽。
典型设置如:$timeformat(-9, 3, “”, 5)
那么此后的%t打印,将以ns为单位,小数点后3位的精度打印仿真时间。
回到上面的例子,当我们用:
$display(“time=%f”,vr_t);
打印时,会得到120.123(单位/精度是1ns/1ps)和301.200(时间单位/精度是100ps/10ps),这是相对时间,因为它们的单位不同。而当我们用
$display(“time=%t”,vr_t);
打印时,会得到120.123(单位/精度是1ns/1ps)和30.120(时间单位/精度是100ps/10ps),这是绝对时间,它们的单位都已被换算为ns。
用上述的$timeformat设置,再看两个例子(还是在module、program、package或interface中):
代码 | timescale 1ns/1ps | timescale 100ps/1ps |
---|---|---|
#200 $display(“time= |