Multiple $monitor system task execution

Hi,

I am facing the following issue : While executing two $monitor tasks simultaneously(with different signals) either inside single initial block or in separate initial block, it always displays the last one $monitor during simulation. Following is the example :

////////////////////////////////////////////////

module top();
  
  reg sig_1;
  reg sig_2;

  initial begin : INI_1
    sig_1 = 1'b0;
    sig_2 = 1'b0;

    fork 
      begin
        repeat(10) begin
          #5 sig_1 <= ~sig_1;
        end
      end
      begin
        repeat(10) begin
          #5 sig_2 <= ~sig_2;
        end
      end
    join_none
  end : INI_1

  initial begin : INI_2
    $monitor($time,":: INI_2 | SIG_1 = %0b ::",sig_1);
  end : INI_2

  initial begin : INI_3
    $monitor($time,":: INI_3 | SIG_2 = %0b ::",sig_2);
  end : INI_3

endmodule

//////////////////////////////////////////////////////////////

Please, assist me why is it happening and how can I use multiple $monitor tasks during simulation ?

$monitor only uses the last invocation - it is a very primitive form of output that should only be used for the simplest debugging. It was actually designed for use before tools had waveform displays.

You could replace your initial blocks with

always_comb begin : INI_2
    $display($time,":: INI_2 | SIG_1 = %0b ::",sig_1);
  end : INI_2

BTW, a couple of comments about your clock generators.

  • You should be using 2-state bit types instead of reg types for variables that will be driven into your test
  • Always use blocking assignments except when assigning variables triggered by a clock edge.
  • Don;t use fork/join_none unless you really need it - it is usually more expensive to simulate.

In reply to dave_59:

Hi Dave,

Thanks for your acknowledgement.

We are currently referring SV LRM 1800 - 2012. In that it has been mentioned the following statement :

“Only one $monitor display list can be active at any one time; however, a new $monitor task with a new
display list can be issued any number of times during simulation.”

So, tell me what exactly it means and how can we use $monitor task any number of times during simulation as per the above give statement?

It means like Dave said.
You can use $monitor any number of times during a simulation.
However, one the last is active.
Each replaces the previous one.

Shalom

In reply to psp127143:

When you call $monitor, it sets a background process that effectively works like the always_comb block I showed you above, except that it only prints the values at the end of the time slot.
When you call $monitor again, it kills the background process, and starts a new process that prints using the new format.

Your two initial blocks, ini_2 and ini_3 are in a race condition and only the last call executed will execute. In your simulator, it happens to choose the block that appears last in the source code).

$monitor was only useful with Verilog-XL, which was an interpreted simulator. You could run the simulator for some period of time, execute a $monitor, run for some more time, and then issue another $monitor statement with new values to print out.

I do not recommend using $monitor anymore.