1
\$\begingroup\$

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.

toolic
10.8k11 gold badges31 silver badges35 bronze badges
asked Oct 13, 2023 at 17:30
\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

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.

answered Oct 13, 2023 at 19:22
\$\endgroup\$
0
\$\begingroup\$

A const is a write once at initialization time, not an elaboration constant like a parameter.

You can break this up into two steps.

  1. Generate the random values you want to use for your modules. You can do this using SystemVerilog or whatever other languages your want.
  2. 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.

answered Oct 13, 2023 at 19:23
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.