Interface modport values inconsistent under the same interface

Hi,

Can someone help me understand why the signals values are different even though under the same interface?
Also 3 vendors give all different results.

VCS Compile Error
Incisive Waveform
Aldec Waveform

Snoposis: compile error
Incisive: compile pass. Comparing 2 modport signals, two rst are identical, one cnt4 is lagging the other one clk.
Aldec : compile pass. Comparing 2 modport signals, two rst are slightly different, one cnt4 is lagging the other one clk.

Three questions:
1.how to mapping rst, cnt4 to corresponding modport if it shows in the same waveform?
2.which simulation result is more reliable among those 3 simulator for this specific case?
3.is it possible to modify the code so that 3 simulator can get the same result, especially for VCS taking it without compilation error?

interface bus(input bit clk);
  logic rst;
  logic [1:0] cnt4;
  
  clocking master_cb @(posedge clk);
    //only specify the direction
    default input #1step output #1ns;
    output rst;
    input cnt4;
  endclocking
   
  //async modport for DUT connection
  modport dut_async_mp(input clk, input rst, output cnt4);
  //sync modport containing clocking block for TB
  modport master_mp(clocking master_cb);
endinterface
    
module tb();
  bit clk;
  bus busA(clk);
  /* VCS compilation issue version
  cnt dut(busA.dut_async_mp);
  */
  cnt dut(busA.clk, busA.rst, busA.cnt4);
  tc tc(busA);
  
  always
    #5 clk = ~clk; //10ns
   
  initial begin
    //$monitor($time,, busA.dut_async_mp.clk,, busA.dut_async_mp.rst,, busA.dut_async_mp.cnt4);
    $monitor($time,, busA.clk,, busA.rst,, busA.cnt4);
  end
  
  initial begin
    $dumpfile("dump.vcd"); 
    $dumpvars(0,tb);
  end
endmodule
    
program tc(bus.master_mp mp);
  class driver;
    virtual bus.master_mp mp;
    
    function new(virtual bus.master_mp mp);
      this.mp = mp;
    endfunction
    
    //assign value to the modport-mp
    task assign_mp();
      **//why 0ns ~ 6ns, rst get 'X?**
      mp.master_cb.rst <= 1;
      @mp.master_cb;
      mp.master_cb.rst <= 0;
      repeat(8) @mp.master_cb;
    endtask
    
    task run();
      assign_mp();
      assign_mp();
    endtask    
  endclass
  
  initial begin
    driver drv=new(mp);
    drv.run();
  end
endprogram

/* VCS compilation issue version
module cnt(bus.dut_async_mp mp);
  always@(posedge mp.clk)
    if(mp.rst)
      mp.cnt4 <= 0;
    else
      mp.cnt4 <= mp.cnt4 + 1;
endmodule
*/
module cnt(input clk, rst, output reg[1:0] cnt4);
  always@(posedge clk)
    if(rst)
      cnt4 <= 0;
    else
      cnt4 <= cnt4 + 1;
endmodule

In reply to mlsxdx:

You have discovered how poorly specified modports are and implemented. I suggest only using them for synthesis which requires the directional information.

To address your issues, a modport is not a scope, it is an access group. You cannot use it in a hierarchical reference. Get rid of the modport name anywhere you have intf.mp.signal. It should be intf.signal.

Another way to put it, it doesn’t make any sense to use a modport in your module tb. It already has access to all the signals inside the busA instance. A modport could not restrict any access.

In reply to dave_59:
Thanks for your reply, Dave.
1.“only using them for synthesis which requires the directional information”, can you elaborate a
little bit on this?
2.after changing intf.mp.signal to intf.signal in module cnt4, there is no compilation issue now.
3.why during 0~6ns, it shows 'X on the waveform? Is there a better way to drive synchronized signal so that it gets initial value?

In reply to mlsxdx:

  1. I don’t remember the reason why the direction is required for synthesis - just that it is. When you synthesis hierarchical modules, most of the intermediate levels get removed and the ports disappear, but the top level, and when you synthesize blocks, a module without interface ports would have directions for all the signal ports. But as soon as you introduce an interface port in a module, the interface signals have no direction unless you add a modport.

  2. The first posedge clk is at 5ns, and there is 1ns output delay, so it takes 6ns for the first drive to appear. You could use a bit instead of logic, or you could write ‘logic rst=0;’