验证语言系列:timeunit和timeprecision
前面曾写过《Verilog系列:timescale去哪儿了》,其中讲述了timescale的用法,在使用时如果timescale顺序设置不合适,往往导致指定的延迟与期望不一致.随着搭建平台时对于验证平台要求的提高,有时需要使模块、接口或程序块与时间单位和精度信息直接绑定,有时需要指定class中的时间单位等,面对这样的问题,SystemVerilog中增加了两个新的特性: timeunit和timeprecision,本文将示例两者的用法和注意事项.
timeunit和timeprecision可以使用在module、program、package、interface等结构中,但是不能使用在class中,而timescale可以使用在任何地方,这也导致了其独立性不够,容易因为文件编译顺序等原因导致期望的时间延迟不对的情况出现。timeunit和timeprecision的含义主要如下:
timeunit:用于指定时间单位,也可以同时指定时间精度;
timeprecision:用于指定时间精度;
在不指定timescale的情况下,可以通过timeunit和timeprecision指定当前模块的时间单位和时间精度,此时模块外部和内部指定的timescale不起任何作用,即timeunit和timeprecision有更高的优先级;
【示例】
指定timeunit时可以像timescale那样,同时指定时间单位和时间精度,其后仍然可以继续使用timeprecision,但是timeprecision指定的时间精度必须与timeunit中指定的时间精度一致.但是需要注意的是,这种方式指定时间单位和精度后,其后是不能再次使用timeunit;
【示例】
综上所述,timeunit和timeprecision摆脱了timescale对于编译顺序的束缚,对于任何模块、程序、包或接口,或者在任意编译单元作用域内,都可以定义一个时间单位和一个时间精度,此时就会定义一个时间作用域.并且timeunit和timeprecision相对于timescale有更高的优先级和灵活性.但是在具体使用时,还是应该明确显式的制定确定的时间单位和时间精度,以免影响代码的可读性.
timeunit和timeprecision可以使用在module、program、package、interface等结构中,但是不能使用在class中,而timescale可以使用在任何地方,这也导致了其独立性不够,容易因为文件编译顺序等原因导致期望的时间延迟不对的情况出现。timeunit和timeprecision的含义主要如下:
timeunit:用于指定时间单位,也可以同时指定时间精度;
timeprecision:用于指定时间精度;
【示例】
`timescale 1 ns / 1 ns module dut_time(clk); timeunit 1ns; timeprecision 10ps; `timescale 10 ns / 1 ns output clk; reg clk; initial begin clk = 1'b0; forever #1.125 clk = ~clk; end endmodule `timescale 10 ns / 1 ns module top_tb; reg clk; wire clkt; dut_time dut_t(clkt); initial begin $printtimescale(top_tb); $printtimescale(top_tb.dut_t); clk = 1'b0; forever #1.55 clk = ~clk; end endmodule【仿真结果】
# Time scale of (top_tb) is 10ns / 1ns # Time scale of (top_tb.dut_t) is 1ns / 10ps
【示例】
module dut_time(clk); timeunit 1ns / 1ps; // timeprecision 10ps; illegal format! timeprecision 1ps; output clk; reg clk; initial begin clk = 1'b0; forever #1.125 clk = ~clk; end endmodule `timescale 10 ns / 1 ns module top_tb; reg clk; wire clkt; dut_time dut_t(clkt); initial begin $printtimescale(top_tb); $printtimescale(top_tb.dut_t); clk = 1'b0; forever #1.55 clk = ~clk; end endmodule【仿真结果】
# Time scale of (top_tb) is 10ns / 1ns # Time scale of (top_tb.dut_t) is 1ns / 1ps
【示例】
module dut_time(clk); timeunit 10ns; output clk; reg clk; initial begin clk = 1'b0; forever #1.125 clk = ~clk; end endmodule module top_tb; reg clk; wire clkt; dut_time dut_t(clkt); initial begin $printtimescale(top_tb); $printtimescale(top_tb.dut_t); clk = 1'b0; forever #1.55 clk = ~clk; end endmodule【仿真结果】
# Time scale of (top_tb) is 1ns / 1ns # Time scale of (top_tb.dut_t) is 10ns / 1ns如果仅使用timeunit,且timeunit中仅指定了时间单位,那么当其他模块没有指定时间精度时,编译可以通过,但是此时精度由仿真器默认值决定(此处为1ns),模块内时间单位由timeunit决定;这里注意,timeprecision不能单独使用,但是timeunit可以;
综上所述,timeunit和timeprecision摆脱了timescale对于编译顺序的束缚,对于任何模块、程序、包或接口,或者在任意编译单元作用域内,都可以定义一个时间单位和一个时间精度,此时就会定义一个时间作用域.并且timeunit和timeprecision相对于timescale有更高的优先级和灵活性.但是在具体使用时,还是应该明确显式的制定确定的时间单位和时间精度,以免影响代码的可读性.