Issue with package and parameter of type realtime

Hello all
I have an issue with the following construct (array of structures with realtime type members)


package i2c_bfm_pkg;
  typedef enum bit unsigned [2:0] {
    STANDARD   = 0, FAST = 1, HIGHSPEED = 2, CUSTOM = 3, FASTP = 4} t_mode; 

  parameter  realtime cstScl_h   = 2.5us;
  typedef struct packed{
    realtime tBUF;      // Bus Free Time between STOP and START
    realtime tHD_STA;   // Hold time, (Repeated) START condition
    realtime tLOW;      // Low Period of the SCL Clock
    realtime tHIGH;     // High Period of the SCL Clock
    realtime tHD_DAT;   // SDA hold
    realtime tSU_DAT;   // SDA setup
    realtime tSU_STA;   // Start condition setup
    realtime tSU_ST0;   // Stop condition setup
  } t_timings;
  parameter t_timings p_timings[] = '{
                     /* tBUF     tHD_STA,        tLOW,      tHIGH,    tHD_DAT,    tSU_DAT,    tSU_STA,    tSU_ST0 */
  /* 0 STD   */  '{    4.7us,        4us,       4.7us,       4us,       0.1us,     0.25us,      4.7us,        4us},
  /* 1 FAST  */  '{    1.3us,      0.6us,       1.6us,     0.6us,       0.3us,      0.1us,      0.6us,      0.6us},
  /* 2 HS    */  '{   0.15us,     0.16us,      0.16us,    0.06us,      0.07us,     0.01us,     0.16us,     0.16us},
  /* 3 CST   */  '{cstScl_h*4, cstScl_h*2, cstScl_h*2, cstScl_h*2,  cstScl_h*0, cstScl_h*2, cstScl_h*2, cstScl_h*2},
  /* 4 FASTP */  '{     0.5us,     0.26us,      0.5us,     0.26us,      0.3us,     0.05us,     0.26us,     0.66us}
  };
endpackage : i2c_bfm_pkg

and the package is used as following


module i2c_bfm
(
    input logic     VDD,
    inout logic     SDAH,
    inout logic     SCLH,
    input t_mode    speed_mode,
    input bit       stop_on_err
);
...
t_timings _timings;
assign _timings = i2c_bfm_pkg::p_timings[int'(speed_mode)];
...

task i2c_start;
    scl_out = 1;
    sda_out = 0;
    #_timings.tHD_STA;
    scl_out = 0;
    #(_timings.tLOW-_timings.tHD_DAT - _timings.tSU_DAT);
endtask: i2c_start

The issue is that delays are not applied properly, and si mulation shows they are always zero. All of this works perfectly using cadence IRUN simulator so I wonder what I am missing
I tried writing this differently - e.g. using variables, static variables, const in place of parameters but no joy …
Modelsim version is v6.6

Thanks much

In reply to stanzani:

The first thing that comes to mind is to check your timescale/timeprecision. By default, IUS might have a finer setting than Questa (e.g. fs instead of ns). I see your delays are pretty big (us - so a timescale of ns would still be ok), but it’s worth a shot.

Thanks much tudor
I had in mind that settin a constant on 3us will produce a 3us anyway, whatever the timescale is (BTW I use timeunit and timeprecisio: the way verilog handle time had always been combersome to me)

In reply to stanzani:
This is a common Verilog gotcha. Each design unit(Module/Package/Interface) scales times based on a local time unit. When you pass values between units, you need to ensure they are using the same time units, or normalize the values to a common time scale.

parameter t_timings p_timings[] = '{
                     /* tBUF     tHD_STA,        tLOW,      tHIGH,    tHD_DAT,    tSU_DAT,    tSU_STA,    tSU_ST0 */
  /* 0 STD   */  '{    4.7us/1us,    4us/1us,   4.7us/1us,   4us/1us,   0.1us/1us, 0.25us/1us,  4.7us/1us    4us/1us},


task i2c_start;
    scl_out = 1;
    sda_out = 0;
    #(_timings.tHD_STA*1us);
    scl_out = 0;
    #((_timings.tLOW-_timings.tHD_DAT - _timings.tSU_DAT)*1us);
endtask: i2c_start

In reply to dave_59:
Does this means that the timeunit is just an indication, i.e. it does not enforce anything?
what does it means writing 1.5 rather than 1.5 us?
in VHDL aif I stata a<=1, 2 after 1ms; ais 1 at time o and then go to 2 after 1ms :(

In reply to stanzani:
Unlike VHDL, Verilog does not have a physical time type. The type realtime is identical to the type real.

When you write
1.5us
, that literal constant get scaled to the current time unit, and it becomes just a value.

package A;
timeunit 1ns;
parameter realtime P1 = 1.5; //P1 has the value 1.5
parameter realtime P2 = 1.5us; //P2 has the value 1500.0
endpackage
package B;
timeunit 1ms;
parameter realtime P1 = 1.5; //P1 has the value 1.5
parameter realtime P2 = 1.5us; //P2 has the value 0.0015
endpackage
module M;
// does not matter what the time unit is here for the $displays
initial begin
       $display(A::P1);// displays 1.5
       $display(A::P2);// displays 1500.0
       $display(B::P1);// displays 1.5
       $display(B::P2);// displays 0.0015
end
endmodule

If you don’t define a time unit in the package, you are at the mercy of the tool’s default tune unit. (which I think should have been an error if not specified, but people are too lazy)

In reply to dave_59:

Got it!
I find this just crazy … why not enforcing the time to just 1.5ns?
so the safest way to generate a delay of N us is as following

timeunit 1ns;

task _del (shortint unsigned N)
realtime _del ;
_del = N*1000;
#_del;
end task: _del

rather than

timeunit 1ns;

task _del (shortint unsigned N)
#N*1us;
end task: _del

right?
so adding ‘us’ is pointless …

Dammitt …