Menu Close

Verilog 仿真中 $timeformat 使用

在Verilog 语言进行仿真中,通常会使用$display, $strobe, $monitor,$write等系统函数向屏幕上输出一些信息, 帮助验证者 跟踪设计流程, 发现错误等。 在Verilog语言进行仿真时,缺省的设置是以`timescale的时间精度 为单位的(通常是 1ps, `timescale 1ns/1ps)。在通常的RTL 设计中,往往仿真单位是以ns 为单位(例如 `timescale 1ns/1ps),当然,一些超高速的设计,也会使用ps为单位。总体来说,使用仿真单位为ns系统打印输出为ps时,阅读起来不是非常方便。

举例:

`timescale 1ns / 1ps

module tb(
    );
    
    
reg a = 0;
reg rst = 1;
initial
begin
    #200;
    rst = 1;
    #10;
    rst = 0;
    $display("==== init a = 0, time = %t  ====", $time);
end

endmodule

 

这时我们会发现$display 输出到屏幕上的信息时间单位都是ps级别的。虽然ps可以换算为ns,但总是和程序中的 #200;   #10; 不一致。阅读起来不是非常方便。Verilog 语言中提供一种改变缺省显示输出的函数,是的屏幕显示函数输出结果和程序代码一致。 使得阅读变得更加方便。

1 $timeformat 任务格式

$timeformat ( units_number, precision_number, suffix_string, minimum_field_width) ;

这个系统任务并不改变程序时间精度(不改变`timescale 的内容),只是更改了$display, $strobe, $monitor, $write, $fdisplay, $fstrobe, $fmonitor, $fwrite 等系统任务中使用  %t 时的缺省时间单位, 方便开发者阅读代码。

参数描述:

  • units_number: 是 0 到-15 之间的整数值,表示格式化输出的时间值的单位:0 表示秒,-3 表示毫秒,-6 表示微秒,-9 表示纳秒;它是以10(units_number)幂秒表示当前输出的时间单位。例如 -3 :代表%t 输出是以ms 为时间单位输出的,即 10-3 s = 1ms。具体数字所代表的含义,见表1

表1

Unit number Time unit Unit number Time unit
0 1 s -8 10 ns
-1 100 ms -9 1 ns
-2 10 ms -10 100 ps
-3 1 ms -11 10 ps
-4 100 us -12  1 ps
-5 10 us -13 100 fs
-6 1 us -14 10 fs
-7 100 ns -15 1 fs
  • precision_number: 是指打印输出时, 小数点后保留多少位10进制数
  • suffix_string: 后缀字符串, 可以增加 打印输出的时间单位。 例如 ” ps”   ” ns”  ” us” ” ms” 等。这样就不需要在 向 $display 等函数中额外添加时间单位了。
  • minimum_field_width: 是指打印输出的时间值字符串+suffix_string 字符串的最小长度,如果时间值字符串+suffix_string 字符串 小于 minimum_field_width,则在时间值字符串+suffix_string字符串之前补空格。注:这个功能只对%t有效, 对于 %0t 无效。 它的作用是格式化输出, 使得上下行输出的结果都在同一列位置上。

 

2 举例说明

例1:时间单位设置: units_number

`timescale 1ns / 1ps
module timeformat_sim();
    
reg a = 0;
reg rst = 1;
initial
begin
    #1;
    $display("==== 1: simulation time = %t  ====", $time);
    $timeformat(-9,5," ns",10);
    $display("==== 2: simulation time = %t  ====", $time);
    #10;
    $timeformat(-6,5," us",10);
    $display("==== 3: simulation time = %t  ====", $time);
    #30;
    $timeformat(-3,5," ms",10);
    $display("==== 4: simulation time = %t  ====", $time);
    
    #400;
    $stop;
end    


endmodule

 

仿真结果:

图1

根据图1 所示:

  • 在没有使用$timeformat 之前打印 1 ,time = 1000 ,缺省的时间单位为 ps。原因: `timescale 1ns / 1ps
  • 在设置$timeformat 时间精度为-9时, 打印2, time = 1.00000 ns 。 即10-9 秒
  • 在设置$timeformat 时间精度为-6时, 打印3, time = 0.01100 us 。 即10-6 秒
  • 在设置$timeformat 时间精度为-3时, 打印4, time = 0.00004 ms 。 即10-3 秒

例2:时间精度设置: precision_number

`timescale 1ns / 1ps
module timeformat_sim();
    
reg a = 0;
reg rst = 1;
initial
begin
    #123456.789012;

    $timeformat(-9,0," ns",10);
    $display("==== 1: simulation time = %t  ====", $time);

    $timeformat(-6,3," us",10);
    $display("==== 2: simulation time = %t  ====", $time);

    $timeformat(-3,6," ms",10);
    $display("==== 3: simulation time = %t  ====", $time);

    $timeformat(-9,6," ns",10);
    $display("==== 4: simulation time = %t  ====", $time);

    $timeformat(-9,6," ns",10);
    $display("==== 5: simulation time = %t  ====", $realtime);
    
    #400;
    $stop;
end    

endmodule

 

仿真结果:

图2

从图2中可以看出:当时间精度为:

  • 0:打印1;只有整数部分被输出。时间单位是ns
  • 3:打印2;整数部分+小数点3位被输出。时间单位是us
  • 6:打印3;小说部分输出6位。时间单位是ms
  • 6:打印4;#123456.789012; 小数部分输出6位,但是小数部分全部为0,时间单位是ns, 使用$time 系统函数输出。
  • 6:打印5;#123456.789012; 小数部分输出6位,但是小数部分全部为.789000,时间单位是ns,使用$realtime 系统函数输出。$realtime 可以根据当前仿真工程中的时间精度输出时间信息。

从打印4,5 可以看出 $time 系统函数只是输出当前仿真程序中的时间单位的整数部分;即:`timescale 1ns / 1ps。 使用系统函数 $realtime 可以输出当前时间单位的小数部分。

为什么打印5只显示123456.789000 而不是 123456.789012 呢? 可以使用新的`timescale 1ns / 1fs试试。主要看程序是否有必要使用更高的时间精度了。

例3:显示后缀设置:suffix_string

`timescale 1ns / 1ps
module timeformat_sim();
    
reg a = 0;
reg rst = 1;
initial
begin
    #10;

    $timeformat(-9,0,"",10);
    $display("==== 1: simulation time = %t  ====", $time);

    $timeformat(-9,0,"abc",10);
    $display("==== 2: simulation time = %t  ====", $time);

    $timeformat(-9,0,"KKK",10);
    $display("==== 3: simulation time = %t  ====", $time);

    $timeformat(-9,0," ns",10);
    $display("==== 4: simulation time = %t  ====", $time);

    #400;
    $stop;
end    
  

endmodule

 

仿真结果:

图3

从图3中可以看出:

  • 打印1:可以没有后缀字符串。
  • 打印2,3:可以是任意添加的字符串。
  • 打印4:添加空格+有意义的字符串。帮助开发者理解当前的程序。

从这个例子,可以看出当使用$timeformat 设置好后缀字符串,就不必为每一个$display , $monitor 等等系统函数 单独添加时间单位后缀了。

例4:最小打印宽度设置minimum_field_width

`timescale 1ns / 1ps
module timeformat_sim();
    
reg a = 0;
reg rst = 1;
initial
begin
    #10;

    $timeformat(-9,3," ns",9);
    $display("==== 1: simulation time = %t  ====", $time);

    $timeformat(-9,3," ns",10);
    $display("==== 2: simulation time = %t  ====", $time);

    $timeformat(-9,3," ns",11);
    $display("==== 3: simulation time = %t  ====", $time);

    $timeformat(-9,3," ns",12);
    $display("==== 4: simulation time = %t  ====", $time);

    #400;
    $stop;
end    

endmodule

 

仿真结果:

图4

从图4中可以看出,当输出结果为10.000 ns 时,字符串一共含有9个字符(10 + . + 000 + 空格 + ns)。当使用minimum_field_width为:

  • 9:$display 函数中 time = %t  等号之后没有额外添加空格。
  • 10:$display 函数中 time = %t  等号之后没有额外添加1个空格。
  • 11:$display 函数中 time = %t  等号之后没有额外添加2个空格。
  • 12:$display 函数中 time = %t  等号之后没有额外添加3个空格。

注意:minimum_field_width这个参数在使用格式化输出为 %0t 时无效。

举例:$display(“==== 1: simulation time = %0t ====”, $time);

总体来说, 最小打印宽度参数主要是用来格式化打印输出的,防止

time = 1.000 ns
time = 1000.000 ns
time = 10.000 ns 
time = 100.000 ns

等数据在纵向上不对齐。使用较大的最小打印宽度设置,可以实现:

time =    1.000 ns
time = 1000.000 ns
time =   10.000 ns
time =  100.000 ns

 

$timeformat 是Verilog 语言仿真中一个比较好用的工具函数, 没有使用这个系统任务, 也能完成相应的打印输出,但是在阅读的时候不是非常方便,使用$timeformat 系统任务,使得打印更加清晰,同时这个系统任务不会更改仿真时间单位时间精度

 

 

Posted in FPGA, FPGA 教材教案, Verilog, 教材与教案, 文章

发表回复

相关链接