I\'d like to set a parameter based on a parameter which is set when the module is instantiated. I have the following.
module foo #(WORDS = 8);
parameter P00
Placing a parameter definition inside a generate block generates a new local parameter relative to the hierarchical scope within the generate block. defparam is the usually the way to override a parameter value. However the IEEE std 1800-2012 explicitly states a defparam cannot effect its parent scope in §23.10.1:
a defparam statement in a hierarchy in or under a generate block instance (see Clause 27) or an array of instances (see 28.3.5 and 23.3.2) shall not change a parameter value outside that hierarchy.
For complex derived parameter assignments you can use functions. For example:
parameter P01 = FUNC01(WORDS,P00);
function byte FUNC01(input byte w,p);
/* ... */
endfunction
This is also legal: module foo #(parameter WORDS, P00=FUNC00(WORDS));
A challenge could be that each parameter may need its own function. Using a parameter with a struct data type is a potential work around to group the assignments into a single function. This approach needs to be evaluated by your simulator, synthesizer and other tools. Example:
typedef struct packed {
int sub00;
byte sub01;
/* ... */
bit [13:0] subNN
} param_t;
paramter param_t P = FUNC_P(/* inputs */);
function param_t FUNC_P(/* inputs */);
param_t rtn;
/* assign all rtn.sub* */
return rtn;
endfunction
logic [P.sub01-1:0] tmpvar;
As Morgan has stated, you could define most of the parameters as logic and use a combination block. However I would strongly insist on using an always_comb block instead of a always @* to guarantee the values are calculation. As stated in the LRM §9.2.2.2.2:
always_comb automatically executes once at time zero, whereas always @* waits until a change occurs on a signal in the inferred sensitivity list.