I'm trying to pass a random value using $urandom
into a parameter
for a top-level module in my testbench. But, I get the error:
Illegal non-local reference to constant function [10.3.5(IEEE)].
when running with the code below:
generate
for (genvar chip=0; chip<NUM_CHIPS; chip++) begin: gen_yodawg
YODAWG #(
.TEL_VSUM_OFFSET_ERROR('{(($urandom/(1 << 31))-1)*0.025, (($urandom/(1 << 31))-1)*0.025, (($urandom/(1 << 31))-1)*0.025, (($urandom/(1 << 31))-1)*0.025}),
.TEL_VSUM_GAIN_ERROR('{(($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05}),
.TEL_VOUT_OFFSET_ERROR('{(($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05}),
.TEL_VOUT_GAIN_ERROR('{(($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05, (($urandom/(1 << 31))-1)*0.05}),
.TEL_VIN_OFFSET_ERROR((($urandom/(1 << 31))-1)*0.05),
.TEL_VIN_GAIN_ERROR((($urandom/(1 << 31))-1)*0.05),
.TEL_TEMP_OFFSET_ERROR((($urandom/(1 << 31))-1)*0.05),
.TEL_TEMP_GAIN_ERROR((($urandom/(1 << 31))-1)*0.05)
) yodawg (
// ports
);
end
endgenerate
I'm assuming that the $urandom
isn't being done at compile time, so this doesn't work. Is there any way to get $urandom
to generate its value at compile time and then pass that into the parameter
?
I tried generating all the parameter
values in an initial
block, or generating const values, but it doesn't seem like I can pass any variable into a parameter
, even if it's a const.
2 Answers 2
The expression passed to a module parameter
must be a compile-time constant; it must be constant before the simulation begins running. This means you can not use the $urandom
system task calls.
If you can change the YODAWG
module, you could change each parameter
to an input
port. Then you can create variables in the upper module to drive the inputs with random values.
Another common approach is to automatically generate the Verilog code using a scripting language (Perl, Python, etc.). It is common to use scripts to run simulations anyway, so this would just be another step in the process. You could either generate the code for the module instances, of generate a list of parameters with random values.
A const
is a write once at initialization time, not an elaboration constant like a parameter
.
You can break this up into two steps.
- Generate the random values you want to use for your modules. You can do this using SystemVerilog or whatever other languages your want.
- Feed those random values into the compilation/elaboration step into the modules
Since these are real
values you are passing down, I doubt they need to be parameters. You could change these to ports of your module, or make direct hierarchical assignments.
Explore related questions
See similar questions with these tags.