What is the difference between $display, $monitor, and $strobe in Verilog?
1. $display (Immediate Execution)Behavior: It acts like a standard printf statement in C. The moment the simulator encounters $display in an initial or always block, it freezes time, grabs the current values of the variables, and prints them to the console immediately.
The Catch: If you place a $display right after a non-blocking assignment (<=), it will print the old value of the variable, because non-blocking assignments don't update until the end of the time step.
$strobe (End of Time Step Execution)Behavior: It waits and executes at the very end of the current simulation time step (during the Nonblocking Assignment (NBA) or Monitor region), after all wire updates and register assignments have completely settled.
Best Use Case: It is highly useful for debugging race conditions or catching data after non-blocking assignments (<=) have resolved. If you put a $display and a $strobe side-by-side after a non-blocking assignment, $strobe will correctly print the newly updated value, while $display will print the stale value.
$monitor (Value-Change Execution)Behavior: Unlike $display and $strobe, which print every single time they are explicitly called in the code execution path, $monitor is a concurrent process that runs in the background. You usually invoke it just once (typically in an initial block). The simulator then "watches" all the variables listed inside it. At the end of any simulation time step where at least one of those watched variables changes value, $monitor automatically prints out the updated values.