In reply to Paul McKechnie:
Communicating time values across multiple timescale domains has been a gotcha in Verilog since day one. There is no physical time data type, so it is best if you use real numbers and $realtime to avoid truncation, and then normalize your real time values using a mutually agreed upon time literal. For example, the expression
$realtime / 1ps
always results in value where 1.0 means 1 picosecond, regardless of the current timeunit. If that expression gets passed to another scope having a different timeunit, you can multiply it again by 1ps
timeunit 1ns
real timestamp;
timestamp = $realtime / 1pa;
call_another_timunit(timestamp);
timeunit 1ps;
function void call_another_timeunit(real ts);
$display("time current timescale",, ts * 1ps );
endfunction
Lets say we were at time 100 ps when the fist code snippet executes. $realtime returns 0.1 whereas $time would have rounded to return 0. 1ps returns 0.001 when the timeunit is in nanoseconds. So (0.1/0.001) = 100. Whatever the timeunit, this expression would always return 100.
Now call the function call_another_timunit() with the value 100. If we multiply it by 1ps when the timeunit is 1ps, that results in 100 * 1 = 100.