In section 2.5, it says
"Note that if a time literal is used as an actual parameter to a
module or interface instance, the current time unit and precision
are those of the module or interface instance."
First of all, this is incorrect terminology, which makes it unclear
what it is referring to. I assume it is referring to overriding a
module parameter value using a module instance parameter value
assignment. If so, then it should say so. Since this is unclear,
it is unclear whether it also applies to defparams. I realize that
the SystemVerilog LRM deprecates defparams, but this is unlikely to
occur in the eventual Verilog language.
Second, this makes the rules for scaling time literals inconsistent,
varying with where they are referenced in the module. This appears to
be an attempt to get the literal scaled properly for where it will
ultimately be used as a delay. However, this rule does not actually
accomplish that goal. The fact that it does work in some situations
may make the problem worse by misleading users into thinking that it
will work in all situations. A simpler and more consistent rule
will be easier for users to understand, and less likely to surprise
them.
It is easy to produce examples where this rule does not accomplish
the presumed goal. All that is necessary is for the overridden
parameter to be passed on to another module instance that has a
different timescale. It may even be used as a delay in different
modules that have different timescales, so that no scaled value
would be correct. Here is an artificial example that displays
the problem:
`timescale 1ns/10ps
module foo;
parameter delay = 0;
initial #delay $display("time = %t", $time);
endmodule
`timescale 1ps/1ps
module bar;
parameter delay = 0;
initial #delay $display("time = %t", $time);
endmodule
`timescale 100ps/100ps
module mid;
parameter delay = 0;
foo #(delay) f();
bar #(delay) b();
endmodule
`timescale 1ns/1ns
module top;
mid #(5.5ns) m();
endmodule
Here the rules say that 5.5ns should get scaled to the timescale of module
mid, and therefore top.m.delay would be set to 55. Then top.m.f.delay
and top.m.b.delay would both be set to 55. In top.m.f, that would mean
55ns and in top.m.b, that would mean 55ps. Neither of these is the 5.5ns
that was specified.
In a more realistic example, the modules foo and bar would be in different
files and/or libraries, and would use the delays as propagation delays.
Also consider what happens if the user decides to pass the delay down to
multiple submodules. Normally you would want to put that commonly used
value into a parameter, so you can change it in once place:
`timescale 1ns/1ns
module top;
parameter delay = 5.5ns;
mid #(delay) m();
mid2 #(delay) m2();
endmodule
But that completely changes the behavior. Now the 5.5ns will be scaled
to the timescale of module top, so delay will have a value of 6. The
resulting delay in top.m.f would be 6ns (which is accidentally scaled
correctly, but incorrectly rounded off), and in top.m.b would be 6ps.
Changing a literal in an expression to a parameter defined to have the
same value as the literal has the effect of changing the behavior.
This will be unexpected by most users.
This note complicates the way time literals work, without actually giving
the correct timescaling in the general case. Simply deleting this special
case would at least simplify things. It would also solve the unexpected
behavior in the second example.
BTW, to solve the general case would require something like a special type
to indicate that an object (e.g. a parameter) contains a time, instead of
just a number. Then the scaling could be deferred until the value was
actually used as a delay, allowing the scaling to be done with the timescale
where the delay was actually used. It is unfortunate that the type names
"time" and "realtime" have already been used for simple integer and real
types, since those would be ideal names.
Steven Sharp
sharp@cadence.com
Received on Tue Aug 31 15:08:15 2004
This archive was generated by hypermail 2.1.8 : Tue Aug 31 2004 - 15:08:27 PDT