【system verilog】继续探究IC前端仿真中的“时间”,timescale,timeunit/timeprecision设置

前言

仿真中的时间单位/时间精度设置是保证验证环境稳定高效的重要手段,但是很多场景下却常常被忽视。如果没有设置合理的相对统一的时间单位/时间精度,不仅延时、打印等信息会不准确,多模块/环境协同时也会隐藏难以发现的问题。

因此,继续探究仿真中的时间概念,timescale,timeunit/timeprecision等。

timeunit/timeprecision

timeunit/timeprecision即仿真时间单位/时间精度,是仿真时间这个维度上两个重要的概念。

时间单位就是作用域对于相对延迟而言,#1时默认延迟的时间,一般而言timeunit的设置对于绝对延迟(#200ns)没有影响,不过VCS有一个意外情况疑似bug;大部分的仿真器默认的timeunit是1ns。

时间精度就是作用域能够感知的最小延时,当timeprecision=1ps时,#0.4ps会被忽略,#0.5ps会被认为#1ps,。

说起timeunit/timeprecision可能还会有点生疏,但是timescale就很熟悉了,`timescale = 1ns/1ps即timeunit=1ns,timeprecision=1ps,这个我们会在后面做细致探究。

相对时间/绝对时间

相对时间就是相对于timeunit为单位的时间,当timeunit=10ns时,#100就是#100*10ns即1000ns;绝对时间就是不想理会当前域的timeunit/timeprecision配置,延时一个绝对时间值,当然timeprecision精度以下的小数值还是会被四舍五入。

当timeunit/timeprecision=10ns/10ps时,#100ns等价于#10,#100等价于#1000ns。

一般而言为求延时准确,推荐使用绝对时间延时,但是在VCS曾经的版本中(至少2013以前版本),绝对时间延时也会出现问题。当然了,如果环境时间配置合理,所有的问题都可以得到解决。

两个重要函数

如果相对仿真时间进行探究,那么我们需要找到衡量时间的“尺子”和“显示器”,幸好SV中已经为我们内置了这两个函数。

$printtimescale

$printtimescale用来打印当前域内的timeunit/timeprecision,代码示意如下:

【system verilog】继续探究IC前端仿真中的“时间”,timescale,timeunit/timeprecision设置_第1张图片

打印示意如下:

$timeformat

先说明下,$realtime返回64bit real型时间数值,实际上就是real型数值;$time返回64bit 整数型时间数值,小数部分四舍五入;$stime返回32bit无符号整数型,小数四舍五入。直接使用%d,%f进行打印的话,这几个函数的返回值都是相对延时或相对时间的积累值,实事求是的说这个不是我们需要的,我们需要的是绝对时间,于是乎有了$timeformat函数。

$timeformat函数是用于配置%t打印格式,可以说专门为了$realtime而生的。其配置方式如下:

$timeformat(单位,精度,后缀,最小位宽);

【system verilog】继续探究IC前端仿真中的“时间”,timescale,timeunit/timeprecision设置_第2张图片

例如$timeformat(-9,3,"gao_ns",5)代表打印时间为10e-9 s即ns,精度为小数点后3位,后缀字符串为“gao_ns”,显示数值的最小位宽是5位。

示意代码如下:

【system verilog】继续探究IC前端仿真中的“时间”,timescale,timeunit/timeprecision设置_第3张图片

打印效果如下:

分析如下:

时间单位被设置为10ns(具体如何合理设置下文见),因此绝对延时#10即为#100ns,再延时#20.123556ns+#1ps后到打印点总的延时为#120.124556ns,四舍五入为120.125ns。

为什么按照ps来四舍五入的,而不是timeprecision=ns呢?按照SV标准,这里#1ps按道理说应该被四舍五入的,但是我发现modelsim中的四舍五入是按照命令行-t配置精度来进行的,因此这里的#1ps没有被忽略,ps以下的数值会被忽略(-t default = 寻找全局最小的时间精度)。

$timeformat配置为打印以ns为单位,打印小数点后3位,后缀为..ns..,因此%t打印处120.125..ns..。

%f打印的是相对时间也就是12.0125timeunit(10ns),因此打印为12.012500且没有后缀。

好的,那让我们把$timeformat设置好,之后就可以直接用%t了。

$timeformat(-9, 3, "..ns..", 6);

时间配置作用域

验证环境从时间配置作用域的角度,整体可以分为5个维度:module、program、interface、package,其他的归为一个域(比如各种class等)称之为compilation-unit scope。什么含义呢?也就说每一个module/program/interface/package都可以指定自己的timeunit/timeprecision,而所有的class/全局的function/task等归在一起的scope整体只能有一个timeunit/timeprecision。

如何设置timeunit/timeprecision

timeunit/timeprecision

可以使用关键字timeunit/timeprecision来设置,SV规定timeunit/timeprecision能定义在module、program、interface、package、scope中,但是必须设置在最前面。

对于module/program/interface/package很好理解,比如刚刚我就是设置在program最前面的,作用域就是当前的module/program/interface/package:

那么对于compilation-unit scope呢?需要保证timeunit/timeprecision设置的位置是除了module/program/interface/package之外第一个被编译文件的最前面。比如说:

timeunit 10ns;
timeprecision 1ns;
class A;
    .....
endclass

如果这个文件是module/program/interface/package之外第一个被编译文件,那么这个配置会生效compilation-unit scope;否则的话,会报编译问题。

`timescale

`timescale是timeunit/timeprecision的补充,用来指定按照编译顺序,当前`timescale之后,下一个`timescale之前,不含有关键字timeunit/timeprecision的所有module/program/interface/package的时间单位和精度。从module/program/interface/package的角度来说,就是当其本身内部没有timeunit/timeprecision时,使用他之前、离其最近的`timescale。

举两个例子,例子1:

`timescale 1ns/10ps
module AA;
    timeunit 10ns;
    timeprecision 1ps;
    .....
endmodule

module BB;
    .....
endmodule

`timescale 1ns/1ps
module CC;
    .....
endmodule

AA的timeunit/timeprecision=10s/1ps,BB的timeunit/timeprecision=1ns/10s,CC的timeunit/timeprecision=1ns/1ps。

例子2:

`timescale 1ns/10ps
module AA;
    timeunit 10ns;
    timeprecision 1ps;
    .....
endmodule

module BB;
    `timescale 1ns/1ps
    .....
endmodule

module CC;
    .....
endmodule

同样,AA的timeunit/timeprecision=10s/1ps,BB的timeunit/timeprecision=1ns/10s,CC的timeunit/timeprecision=1ns/1ps。因为`timescale没有作用域的概念,只看编译顺序。从module/program/interface/package的角度来说,就是当其本身内部没有timeunit/timeprecision时,使用他之前、离其最近的`timescale。

-timescale

VCS提供了编译选项-timescale=timeunit/timeprecision作为`timescale的补充,其作用是等价于整个编译环境的第一个`timescale,因此作用的文件就是编译开始到第一个`timescale之前,不含有关键字timeunit/timeprecision的所有module/program/interface/package。

SV不允许有的模块有`timescale,有的没有,因此当用VCS进行仿真时,应该使用-timescale作为全局第一个`timescale来避免这一问题。

-unit_timescale

明确一下,SV标准中要求compilation-unit scope只受到关键字timeunit/timeprecision控制,不受`timescale影响,没有timeunit/timeprecision时采用默认时间单位/精度。但是这样处理的话,timeunit/timeprecision还必须在编译的最前面,因此对文件的编译顺序要求很大,稍微有变动或者集成的话就会引入问题。

VCS的处理方式是引入了-unit_timescale命令行,来指定compilation-unit scope的时间单位/精度,具体规则是:

  •  -unit_timescale和compilation-unit scope的timeunit/timeprecision同时存在,以timeunit/timeprecision为准;
  •  -unit_timescale存在,compilation-unit scope的timeunit/timeprecision不存在,以-unit_timescale为准;
  •  -unit_timescale不存在,无论compilation-unit scope的timeunit/timeprecision是否存在,以最后一个生效的`timescale为准(这一条与SV标准不符),注意一定要是最后一个作用于module/program/interface/package且生效的`timescale;

举个例子:

`timescale 10ns/1ns;

class A;
endcalss

`timescale 1ns/10ps;
module B;
endmodule

`timescale 1ns/10ps;

如果这个是最后一个编译文件了,或者module B之后没有其他的module/program/interface/package使用`timescale 1ns/10ps了,那么class A的时间单位/精度=1ns/10ps。

-override_timescale

VCS命令行,强制覆盖所有timescale,强烈不推荐使用。

-t(modelsim)

-t指令,modelsim命令行,替换所有timeprecision,强烈不推荐使用。

这个-t会把全局的精度修改,从延时角度看,-t ns时候ns以下的延时会做四舍五入,但是奇怪的是直接打印timescale并未显示,此处未作深入探究。

VCS的怪现象

VCS旧版本中,对于compilation-unit scope中的绝对延时有一个bug处理,他会先把绝对延时根据离他最近的timescale转换成相对时延,然后再根据本模块timescale转成真正的时延。举个例子例如下面的代码:

编译选项-timescale=10ns/1ps

class A;
    task xx;
        #100ns;
    endtask
endclass

`timescale 1ns/1ps
module B;
    .....
endmodule

更具上面的处理原则,class A的timescale是1ns/1ps。但是VCS在处理时,却先把#100ns根据-timescale=10ns/1ps把#100ns转换成了#1000,然后根据compilation-unit scope的设置,转化成了#1000ns,然后就与我们预期情况不符了。。。

不知道现在的VCS版本是不是纠正过来了,我也没有试过。

构造绝对精准的延时

做一个标准延时模块

前面说了,module/program/interface/package本身最高优先级是关键字timeunit/timeprecision,利用这一特性,我们可以构造一个专门为仿真准备的标准时延模块。

module delay_ns;
    timeunit 1ns;
    timeprecision 1ps;
    task delay(real_time delay_time);
        #delay_time;
    endtask
endmodule

class A;
    task aaa;
        delay_ns.delay(5);
    endtask
endclass

因为module delay_ns的时延是绝对准确的,因此compilation-unit scope中使用时候时延也是绝对准确的。

合理配置各种“时间”

例如在使用VCS进行仿真时,如无特殊需求,-unit_timescale、-timescale设置为一致,避免class中的怪异延迟。

harness前的`timescale如无特殊需求,也和前两者保持一致!

你可能感兴趣的:(SV)