Return type of $realtime

I am trying to understand the return type of $realtime via the following example from LRM Section 20.3.3 :


`timescale 10 ns / 1 ps
 module  top ;

   logic set;
   parameter p = 1.54345 ;  //  Value  different  than  mentioned  in  LRM  

   initial begin
    #p set = 0;
    $display($realtime,,"set = 0");
    #p set = 1;
    $display($realtime,," set = 1");

   end 
 endmodule

I have the following understanding :
(1) First simulation time corresponding to individual delays is calculated .
p corresponds to 1.54345 x 10ns i.e 15.4345ns

There is No need to round-off as there are already 4 decimal places after the decimal point

 1st  assignment  occurs  at  15.4345ns  ,  
 2nd  assignment  occurs  at  15.4345ns + 15.4345ns  i.e  30.8690ns

(2) Value returned by $realtime is a real number scaled to the time unit of the module i.e 10ns .
i.e The value returned by $realtime when multiplied by time unit of 10ns would give us the same simulation time of 15.4345ns and 30.8690ns.

Therefore the expected output was :
1.5434 set = 0
3.0869 set = 1

However the output I observe is :
1.5435 set = 0
3.087 set = 1

It seems that the value returned by $realtime is being rounded-off from 1.54345 to 1.5435

Since we already rounded-off to 4 decimal places in step 2 , why is it that it’s being rounded-off again in the output ?

Any pointers / suggestions would be helpful .

Thanks

In reply to MICRO_91:

The first assignment occurs 15435ps. The local as well as global precision is 1ps. You cannot have fractions of ps.

This example might help to see better what is going on.

module top ;
 
   logic set;
   parameter p = 1.54345 ;  //  Value  different  than  mentioned  in  LRM  
 
   initial begin
    #p set = 0;
    $display($realtime,,"set = 0");
    #p set = 1;
    $display($realtime,," set = 1");
 
   end 
  bot b();
 endmodule
module bot;
  timeunit 1ps/1ps;
  always @* $display($time,,$realtime,,top.set);
endmodule

In reply to dave_59:

Hi Dave ,

Would like your thoughts on how the simulation time calculated for delays ?

There are 2 possibilities :

(1) Delays are first scaled to time unit and then rounded-off based on precision

(a) Due to p , the delays are first scaled to time units ( 10ns )
i.e 1.54345 x 10ns i.e 15.4345ns

(b) Then the scaled result is rounded-off based on precision :


     Ratio  of  time_unit  /  time_precision  is  10 ns / 1 ps  i.e   1 ns / 0.1 ps . 
 
As  0.10ps == 0.0001ns ( time_precision changed to time_unit ) , delays  are  rounded  to  4  decimal  places

 Hence  **15.4345ns  would  be  scaled  to  154345ps**  

An alternate way would be :

(2) Delays are first rounded-off based on precision and then scaled to time unit .

(a) Due to p , the delays are first scaled rounded-off to 4 decimal places


     Ratio  of  time_unit  /  time_precision  is  10 ns / 1 ps  i.e   1 ns / 0.1 ps . 
 
As  0.10ps == 0.0001ns ( time_precision changed to time_unit ) , delays  are  rounded  to  4  decimal  places

 **i.e  1.54345  is  rounded-off  to  1.5435**

(b) Then the rounded-off value is scaled to time unit of 10ns
i.e 1.5435 x 10ns i.e 15.435ns ( which is equivalent to 15435ps )

For the above code the resultant simulation time is different between the 2 ways

If I were to declare :


`timescale 10 ns / 1 ns  
 module  top ;
   logic set;
   parameter p = 1.55;
 ..........

The simulation time for p would be 16ns in both cases , so it doesn’t make a difference in this case .

In reply to MICRO_91:

I think you were making this out to be harder than it really is. But if it helps you, than (1) matches my understanding. This is mostly explained in section 3.14 Simulation time units and precision in the LRM.

In reply to dave_59:

I think you were making this out to be harder than it really is

I do agree on this . Although it’s a basic concept I might have complicated it by overthinking .

However after searching the LRM and a few blogs , I believe the answer to my question is (2)

LRM Section 22.7 has an example :


`timescale 10 ns / 1 ns
module test;
logic set;
parameter d = 1.55;
initial begin
#d set = 0;
#d set = 1;
end
endmodule

It then provides an explanation :


Parameter d retains its value no matter what timescale is in effect.
These simulation times are determined as follows:
a) The value of parameter d is rounded from 1.55 to 1.6 according to the time precision.
b) The time unit of the module is 10 ns, and the precision is 1 ns; therefore, the delay of parameter d is scaled from 1.6 to 16.
c) The assignment of 0 to variable set is scheduled at simulation time 16 ns, and the assignment of 1 at simulation time 32 ns. 
The time values are not rounded when the assignments are scheduled.

The same can be confirmed by using %t with $realtime ( to observe Simulation time ) : edalink

Also LRM Syntax 22.6 says :

The time_precision argument specifies how delay values are rounded before being used in simulation.

Therefore to answer my question from yesterday

  1. First delays are rounded-off based on precision
  2. Then the rounded-off delays are scaled to time units

Applying the same to the topmost question :

(1) #p i.e #1.54345 is first rounded to 4 decimal places

 Hence  **#1.54345 is rounded-off to #1.5435**

(2) Then #1.5435 is scaled to time units of 10ns i.e 1.5435 x 10ns == 15.435ns

(3) Value returned by $realtime is a real number scaled to time units .

 Hence  we  observe  1.5435  and  3.087  ( #1.5435 + #1.5435 ) 

The only part which wasn’t totally clear to me was following line from (c) :
The time values are not rounded when the assignments are scheduled.