在Verilog 语言进行仿真中,通常会使用$display, $strobe, $monitor,$write等系统函数向屏幕上输出一些信息, 帮助验证者 跟踪设计流程, 发现错误等。 在Verilog语言进行仿真时,缺省的设置是以timescale的时间精度 为单位的(通常是 1ps, timescale 1ns/1ps)。在通常的RTL 设计中,往往仿真单位是以ns 为单位(例如 timescale 1ns/1ps),当然,一些超高速的设计,也会使用ps为单位。总体来说,使用仿真单位为ns系统打印输出为ps时,阅读起来不是非常方便。
举例:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
`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 任务格式
|
1 |
$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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
`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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
`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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
`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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
`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);
总体来说, 最小打印宽度参数主要是用来格式化打印输出的,防止
|
1 2 3 4 |
time = 1.000 ns time = 1000.000 ns time = 10.000 ns time = 100.000 ns |
等数据在纵向上不对齐。使用较大的最小打印宽度设置,可以实现:
|
1 2 3 4 |
time = 1.000 ns time = 1000.000 ns time = 10.000 ns time = 100.000 ns |
$timeformat 是Verilog 语言仿真中一个比较好用的工具函数, 没有使用这个系统任务, 也能完成相应的打印输出,但是在阅读的时候不是非常方便,使用$timeformat 系统任务,使得打印更加清晰,同时这个系统任务不会更改仿真时间单位和时间精度