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.

\$\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.

\$\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.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.