Unveiling Verilog and SystemVerilog Time Function Secrets

In this tutorial, we will focus on mastering the time functions in Verilog and SystemVerilog. Understanding how to work with simulation time is crucial for designing and debugging digital systems. We will explore key simulation time functions like $time, $stime, and $realtime, as well as timescale system tasks such as $printtimescale and $timeformat. By the end of this tutorial, you will be well-equipped to effectively utilize these functions in your designs.

Introduction to Simulation Time Functions in Verilog and SystemVerilog

Simulation time functions in Verilog and SystemVerilog are essential for accessing and manipulating simulation time during the execution of a digital system. They provide valuable insights into the behavior of a system and allow designers to observe and fine-tune their designs for optimal performance.

Understanding the Key Time Functions

In this section, we will discuss the three primary simulation time functions used in Verilog and SystemVerilog: $time, $stime, and $realtime.

$time: Accessing 64-bit Time Values

The $time function returns a 64-bit integer value representing the current simulation time, scaled to the time unit of the invoking module. Let's consider an example:

`timescale 1ns / 100ps
module TimeExample;
  logic trigger;
  parameter Delay = 5;

  initial begin
    $monitor($time, " trigger=%b", trigger);
    #Delay trigger = 1;
    #Delay trigger = 0;
  end
endmodule

In this example, the $time function reports the simulation time whenever the trigger variable changes. The output would look like this:

0 trigger=x
5 trigger=1
10 trigger=0

$stime: Accessing 32-bit Time Values

The $stime function is similar to $time, but it returns a 32-bit unsigned integer value instead. This function is useful when the 64-bit time value is not necessary, and you want to save resources. Here's an example:

`timescale 1ns / 100ps
module StimeExample;
  logic pulse;
  parameter Interval = 3;
  
  initial begin
    $monitor($stime, " pulse=%b", pulse);
    #Interval pulse = 1;
    #Interval pulse = 0;
  end
endmodule

The output would be:

0 pulse=x
3 pulse=1
6 pulse=0

$realtime: Working with Real Number Time Values

The $realtime function returns a real number value representing the current simulation time, similar to $time, but with a real number instead of an integer. This is useful for more precise time representation in your simulations. Here's an example:

`timescale 1ns / 100ps
module RealtimeExample;
  logic signal;
  real realDelay = 2.5;
  
  initial begin
    $monitor($realtime, " signal=%b", signal);
    #realDelay signal = 1;
    #realDelay signal = 0;
  end
endmodule

The output would be:

0.0000 signal=x
2.5000 signal=1
5.0000 signal=0

Exploring Timescale System Tasks

Timescale system tasks in Verilog and SystemVerilog provide a way to manipulate and display timescale information. In this section, we will discuss $printtimescale and $timeformat.

$printtimescale: Displaying Time Unit and Precision

The $printtimescale task is used to display the time unit and precision for a specific module. By default, it displays the information for the current module scope. However, you can also provide a hierarchical identifier as an argument to display the timescale information for a different module. Here's an example:

`timescale 1us / 10ns
module PrintTimescaleA;
  initial $printtimescale;
endmodule

`timescale 10ns / 1ns
module PrintTimescaleB;
  initial $printtimescale(PrintTimescaleA);
endmodule

The output would be:

Time scale of (PrintTimescaleA) is 1us / 10ns
Time scale of (PrintTimescaleB) is 10ns / 1ns

$timeformat: Customizing Time Representation

The $timeformat task is a powerful tool for customizing the representation of time values in your simulation. You can specify the time unit, precision, suffix, and minimum field width for the %t format used with system tasks like $write, $display, $monitor, and others.

The $timeformat function takes four arguments:

  1. units_number: This argument sets the time unit scaling for the %t format specifier. The value should be an integer in the range from 0 to -15, where 0 represents 1 second, -1 represents 100 milliseconds (10^-1 seconds), -2 represents 10 milliseconds (10^-2 seconds), and so on.
  2. precision_number: This argument determines the number of decimal places to be displayed in the time value. A non-negative integer value should be provided.
  3. suffix_string: This optional argument is a string that defines the suffix for the time value. The string can be any desired text, such as "ns" for nanoseconds or "us" for microseconds.
  4. minimum_field_width: This optional argument is a positive integer that defines the minimum field width for the time value. If the time value is shorter than the specified minimum width, it will be padded with leading spaces.

Here's an example that demonstrates the usage of $timeformat:

`timescale 1ns / 100ps
module TimeFormatExample;
  logic clk;
  parameter cycleTime = 5;

  initial begin
    $timeformat(-9, 2, " ns", 6);
    $monitor($realtime, " clk=%b", clk);
    forever begin
      #cycleTime clk = ~clk;
    end
  end
endmodule

The output would look like this:

0.00 ns clk=x
5.00 ns clk=1
10.00 ns clk=0
15.00 ns clk=1

In this example, the %t format specification displays time values as multiples of 1ns, with two decimal places, a "ns" suffix, and a minimum field width of six characters.


In conclusion, understanding and using Verilog and SystemVerilog time functions can be incredibly valuable when designing and simulating digital systems. These time functions offer a way to retrieve current simulation times, customize time representation, and explore time-related properties of modules. With these tools, you can effectively manage and control the display and processing of time values in your projects, allowing for more efficient simulations and streamlined debugging.