Understanding $monitor System Task in Verilog and SystemVerilog

Hey there! Welcome back to another installment of our SystemVerilog tutorial. Today, we're diving into a very useful feature in SystemVerilog — the $monitor system task. If you've ever wondered how you can continuously keep an eye on your variables during simulation, then this is the tutorial for you. Let's jump right in!

What is the $monitor System Task?

The $monitor system task is akin to having an ever-vigilant watchdog over your variables. It keeps tabs on changes in the specified variables and prints out messages whenever those changes occur. It operates at the end of the simulation time step, similar to $strobe. If you're curious about $strobe, we've got a detailed explanation over here.

Key Points to Remember

  • Continuous Monitoring: $monitor keeps track of changes in specified variables and prints a message whenever there's a change.
  • End of Simulation Time: It runs in the postponed events region, the last region in the simulation time, so it prints out the final value after all the blocking/non-blocking updates.
  • Single Active Monitor: Only one $monitor can be active at a time. If you invoke a new $monitor during the simulation, it will replace the previous one.
  • Control Tasks: You can control the monitoring using $monitoron and $monitoroff tasks. By default, monitoring is turned on at the start of the simulation.
  • Monitor List Exception: Changes in $time, $stime, or $realtime will not trigger a monitor event.

Simple Testbench Example

Let's take a closer look at how the $monitor system task works with a straightforward testbench.

`timescale 1ns/1ns

module MonitorTB;
  logic       clk;
  logic [3:0] count;

  // Initialize the variables
  initial begin
    clk = 0;
    count = 0;
  end

  // Generate clock signal
  always #5 clk = ~clk;

  // Increment count on the positive edge of the clock
  always @(posedge clk) begin
    count <= count + 1;
  end

  // Monitor changes in count and clk
  initial begin
    $monitor("At time %0t, count = %0d", $time, count);
    #30 $monitoroff; // Disable monitoring after 30 time units
    #40 $monitoron;  // Re-enable monitoring after 70 time units
  end

  // Stop the simulation after a certain time
  initial begin
    #100 $finish;
  end
endmodule

Explanation

  1. Initialization: The $monitor task prints the value of count and the current simulation time whenever count changes.
  2. Monitor Control: $monitoroff is called after 30 time units to stop monitoring.
  3. Resuming Monitoring: $monitoron is called after 70 time units to resume monitoring.

Result

Here’s what the output looks like during the simulation:

At time 0, count = 0
At time 5000, count = 1
At time 15000, count = 2
At time 25000, count = 3
At time 70000, count = 7
At time 75000, count = 8
At time 85000, count = 9
At time 95000, count = 10

The $monitor task tracks changes in count, printing its value each time it updates. Monitoring is turned off at 30 time units and back on at 70 time units.


And there you have it! The $monitor system task is an essential tool in your SystemVerilog toolkit for continuous monitoring of variable changes. Whether you're debugging or just keeping an eye on things, $monitor makes it easy to get the information you need, right when you need it.