In SystemVerilog, simulation time units and precision are crucial aspects that determine how time is modeled and controlled during simulation. They help define the scale and accuracy of time-related operations within the simulation environment.
Simulator is used to imitate the operation of a real-world process of the system description or model being simulated. Maintaining system run time is a crucial task and the simulator uses the term ‘simulation time’ to represent the time used by the system model.
Here we will cover below points.
1. compiler directive `timescale – used to specify default time unit and precision values
2. $time, $stime and $realtime – system functions return the current time
3. $timeformat – to change default reporting format
4. $printtimescale – system task to display time unit and precision
5. Keywords timeunit and timeprecision
6. Timescale Scope- Precedence of timeunit, timeprecision, and `timescale,
7. Global time precision and #1step delay
Table of Contents
Compiler directive `timescale
It is used to specify default time unit and precision values.
Syntax: `timescale time_unit/time_precision
time_unit
is the measurement of delays and simulation time.- What #1 means in terms of time?
time_precision
specifies how delay values are rounded before being used in the simulation and specifies the degree of accuracy for delays.- What will be the round off value for #1.23456 for a given time unit?
For example : `timescale 1ns/1ps
- 1ns (time unit): This defines the base time unit for simulation as 1 nanosecond. All time values in your Verilog code will be interpreted in nanoseconds.
- 1ps (time precision): This indicates the precision for rounding time values to the nearest picosecond.
Rounding Explanation
- The formula
time_unit/time_precision
(1ns/1ps) gives you a scaling factor of 1000 (since 1 ns = 1000 ps). - This means that your simulation will consider time values with a resolution of 1 picosecond, but all values will be expressed in nanoseconds.
Example Conversions(1ns/1ps)
#1
: This is a delay of 1 time unit, which translates to 1 nanosecond.#1.23442
: This represents a delay of 1.23442 nanoseconds, which stays the same because it has sufficient precision.#1.23451
: This value is rounded to 1.235 nanoseconds because it is closer to 1.235 than to 1.234.
Example Code:
module test;
bit [7:0] d;
bit clk;
always #10 clk = ~clk;
initial begin
$monitor($realtime,": %0d", d);
fork
#1.23442 d = 8'h4;
#2.23451 d = 8'h5;
join
end
endmodule
Execute on EdaPlayground
Output: Simulation result with different time_precision
`timescale 1ns/1ps: degree of accuracy=3 (1ns/1ps=10^3)
0: 0
1.234: 4
2.235: 5
`timescale 1ns/10ps : degree of accuracy=2 (1ns/10ps=10^2)
0: 0
1.23: 4
2.23: 5
`timescale 1ns/100ps : degree of accuracy=1 (1ns/100ps=10^1)
0: 0
1.2: 4
2.2: 5
`timescale 1ns/1ns : degree of accuracy=0 (1ns/1ns=10^0)
0: 0
1: 4
2: 5
As the
time_precision
decreases, the detail in timing representation is lost. This can lead to significant differences in simulation behavior, especially for designs where timing is critical.
Both the time units and time precision are represented using one of the character strings: s, ms, us, ns, ps, and fs. The definition of these character strings is given in below table.
Character — Unit
s————-Seconds
ms————milliseconds
us————-microseconds
ns————-nanoseconds
ps————-picoseconds
fs————–femtoseconds
$time, $stime and $realtime
The $time system function returns an integer that is a 64-bit time, scaled to the time unit of the module that invoked it.
The $stime system function returns an unsigned integer that is a 32-bit time, scaled to the time unit of the module that invoked it. If the actual simulation time is larger than 32 bits, the low order 32 bits of the current simulation time are returned.
The $realtime system function returns a real number time that, like $time, is scaled to the time unit of the module that invoked it.
$timeformat
The $timeformat
system task is used to control the display format of time values during simulation. It allows you to specify how time is represented in output messages, making it easier to read and understand timing information.
Syntax:
$timeformat(<unit_number>, <precision>, <suffix_string>, <minimum field width>);
Unit_number represents the time unit as shown in table
precision represents the number of fractional digits for the current timescale.
suffix_string is an option to display the scale alongside real time values.
Example:
module test;
int i, n;
initial begin
#1.123456;
for (int i=0; i<6; i++) begin
$timeformat(-9, i, " ns");
#1 n = i+1;
$display("realtime [", $realtime
,"] : precision=%0d -> formatted time [%0t]"
, i, $realtime);
end
end
endmodule
Execute on EdaPlayground
Output:
realtime [2.123] : precision=0 -> formatted time [2 ns]
realtime [3.123] : precision=1 -> formatted time [3.1 ns]
realtime [4.123] : precision=2 -> formatted time [4.12 ns]
realtime [5.123] : precision=3 -> formatted time [5.123 ns]
realtime [6.123] : precision=4 -> formatted time [6.1230 ns]
realtime [7.123] : precision=5 -> formatted time [7.12300 ns]
$printtimescale
The $printtimescale
system task in Verilog is a useful tool for displaying the current timescale settings of a module. Here’s a detailed explanation of how it works:
- It outputs the time unit and precision used in the current module or a specified module. It helps in debugging, especially in large designs with multiple modules having different timescales.
- No Arguments: When called without any arguments,
$printtimescale
displays the timescale settings of the module that is currently in scope. - With Arguments: When you specify a module as an argument,
$printtimescale
will display the timescale for that particular module, regardless of the current scope.
Example:
`timescale 1ns / 1ps
module top;
M1 m1();
M2 m2();
initial begin
$printtimescale;//$printtimescale(top);
$printtimescale(top.m2);
end
endmodule
//======== M1 ==========
module M1;
timeunit 1ns;
timeprecision 10ps;
initial begin
$printtimescale;
end
endmodule
//======== M2 ==========
module M2;
timeunit 10ns;
timeprecision 1ns;
endmodule
Execute on EdaPlayground
Output:
TimeScale of top is 1 ns / 1 ps
TimeScale of ( top.m2 ) is 10 ns / 1 ns
TimeScale of M1 is 1 ns / 10 ps
Keywords timeunit and timeprecision
In SystemVerilog, the timeunit
and timeprecision
keywords are used to define the time units and precision for time-related operations within a module.
Defining these constructs at the module level allows for more granular control over timing characteristics. Different modules can have different timescales without interfering with each other.
Using timeunit
and timeprecision
provides a clear and organized way to manage timing specifications in Verilog designs. It helps in avoiding compilation issues related to the order of definitions and allows designers to have precise control over time representations in their simulations, ultimately leading to more reliable and understandable designs.
Timescale Scope, Global time precision or simulation time unit and #1step delay
A timescale directive placed in a file is applied to all modules that follow the directive until the definition of another timescale directive. The global time precision is the minimum of all the time precision statements. This is the smallest unit of time for which the simulator will schedule an event. #1step is equal to global time precision and provides the ability to sample data immediately before entering the current time slot.
Example: Result shows the #1step is the smallest resolution.
`timescale 1ns / 1ps
module top;
M1 m1();
M2 m2();
M3 m3();
initial begin
$timeformat(-15, 0, " fs");
#1step;
$printtimescale;
$display("[TOP#1] realtime=%0t", $realtime);
end
endmodule
//======== M1 ==========
module M1;
timeunit 1ns;
timeprecision 10ps;
initial begin
//$printtimescale;
#1step;
$printtimescale;
$display("[M1#1] realtime=%0t", $realtime);
end
endmodule
//======== M2 ==========
module M2;
initial begin
//$printtimescale;
#1step;
$printtimescale;
$display("[M2#1] realtime=%0t", $realtime);
end
endmodule
//======== M3 ==========
module M3;
timeunit 1ns;
timeprecision 1fs;
initial begin
//$printtimescale;
#1step;
$printtimescale;
$display("[M3#1] realtime=%0t", $realtime);
end
endmodule
Execute on EdaPlayground
Output:
TimeScale of top is 1 ns / 1 ps
[TOP#1] realtime=1 fs
TimeScale of M1 is 1 ns / 10 ps
[M1#1] realtime=1 fs
TimeScale of M2 is 1 ns / 1 ps
[M2#1] realtime=1 fs
TimeScale of M3 is 1 ns / 1 fs
[M3#1] realtime=1 fs