Maker.io main logo

System Tasks and Functions in Verilog - Part 28

2025-09-17 | By DWARAKAN RAMANATHAN

Learning System Tasks and Operations in Verilog: $monitor, $display, y $time

In digital design, simulation is the critical step where most bugs are found and removed. But with the wrong tools, even the tiniest mistake can be hidden behind layers of complexity, wasting valuable development time. That's where Verilog's system tasks and functions come in. Of these, $monitor, $display, and $time are useful allies for designers and engineers, being powerful debugging tools that make simulation simple and offer insight into how the circuit changes over time.

Verilog system tasks are predefined procedures beginning with a dollar sign $. They are not synthesizable but are very important during simulation. $display and $monitor, for example, are commonly employed in printing variable values to the console, and $time offers accurate information regarding the simulation timeline.

The Use of $display in Debugging

The $display system task works in a similar manner to the printf statement in C. It displays the values of variables at runtime. This is very convenient if you want to observe some changes or milestones in your design. The output of $display is printed to the console during simulation when invoked, so you can check whether your signals are behaving as they should at some step of the simulation.

For instance, consider the following simple-to-understand example:

Copy Code
module test_display;

reg clk;

reg reset;

initial begin

clk = 0; reset = 1;

#5 reset = 0;

#10 clk = 1;

#10 clk = 0;

conclusion

start

initial begin

$display("Time = %0t : clk = %b, reset = %b", $time, clk, reset);

#5 $display("Time = %0t : clk = %b, reset = %b", $time, clk, reset);

#10 $display("Time = %0t : clk = %b, reset = %b", $time, clk, reset);

#10 $display("Time = %0t : clk = %b, reset = %b", $time, clk, reset);

end

endmodule

Here, $display displays the current simulation time and clk and reset values every time you call it. Observe that you must call $display yourself every time you want to display the values, providing you with control over where and how the information is displayed.

How $monitor Streamlines Continuous Monitoring

Unlike $display, which displays values on explicit invocation, $monitor monitors specified variables and prints new values automatically as soon as there is a change in any one of them. You need to initialize $monitor once, and it will watch for changes during simulation, printing updates without any extra effort on your part.

Let’s look at an example:

Copy Code
module test_monitor;
reg clk;
reg reset;
initial begin
clk = 0;
reset = 1;
$monitor("Time = %0t : clk = %b, reset = %b", $time, clk, reset);
#5 reset = 0;
#10 clk = 1;
#10 clk = 0;
#5 reset = 1;
end
endmodule

Here, the $monitor command is employed to observe clk and reset. Whenever one of them changes, automatically on the console, a message will be printed with their new values and the current simulation time. This is very useful as it prevents any notable change from going unnoticed in the simulation. In a complicated design, $monitor can minimize the usage of multiple display statements and make the testbench cleaner and more efficient.

The Importance of $time in Debugging Timing Problems

Timing is generally as vital as logic in digital circuits. A design is correct but fails because of timing fluctuations like race conditions or setup/hold violations. That is where $time proves useful. $time is a system function that provides the current simulation time in time units so designers can accurately know when an event occurs.

When $time is used with $display or $monitor, it appends a timestamp to the output, making it easy for you to precisely keep track of the order of events. For instance, if you notice that a control signal is 5 units late, you can easily identify and correct the reason. Here's how it fits so well into a debug statement:

$display("At time %0t, signal X changed to %b", $time, X);

This single line logs both the value and simulation time of the change, providing a neat, timestamped record of signal events easy to follow when debugging.

Practical Hints to Work with System Tasks Efficiently

While using $display, $monitor, and $time, formatting has to be applied to produce human-readable outputs. Use formatting specifiers like %b for binary, %d for decimal, and %h for hexadecimal to match your signal types. %t is set aside for showing time units and is most often used with $time.

Also, try to bunch important messages together in your output so you see a snapshot of your system state at important times. Having neat, structured, and timed output is extremely helpful for debugging, especially when simulations are lengthy and complex.

Remember that these system operations and tasks are not synthesizable; they are only for simulation and debugging purposes. Therefore, they should not be used in the final RTL that will be synthesized into hardware.

Conclusion:

It is an important milestone on the path to being a successful digital designer to be able to master system tasks like $monitor, $display, and $time. These utilities provide you with extremely useful information about what your circuits are doing, allowing you to detect errors early and observe the timing and interactions between different signals. Applied wisely, they can save you a great deal of debugging time, improve your simulation routines, and make even the most tedious designs manageable. Rather than treating simulations as a black box, system tasks make them an open book, allowing you to learn more about your digital systems.

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.