Placing the parameter definition inside the generation block generates a new local parameter relative to the hierarchical region inside the generation block. defparam is usually a way to override a parameter value. However, IEEE std 1800-2012 explicitly indicates that defparam cannot affect its parent area in the & sect; 10.23.1:
the defparam statement in the hierarchy inside or under the generation block instance (see section 27) or an array of instances (see 28.3.5 and 23.3.2) should not change the value of the parameter outside this hierarchy.
For complex derived parameter assignments, you can use functions. For instance:
parameter P01 = FUNC01(WORDS,P00); function byte FUNC01(input byte w,p); endfunction
This is also legal: module foo #(parameter WORDS, P00=FUNC00(WORDS));
The task may be that each parameter may require its own function. Using a parameter with a structure data type is a potential work for grouping assignments into a single function. This approach should 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(); function param_t FUNC_P(); param_t rtn; return rtn; endfunction logic [P.sub01-1:0] tmpvar;
As Morgan stated, you can define most of the parameters as logic and use a combinational block. However, I would strongly insist on using the always_comb block instead of always @* to ensure that the values ββare computed. As indicated in LRM & sect; 9.2.2.2.2:
always_comb is automatically executed once at time zero, while always @ * waits until the signal changes in the expected sensitivity list.
source share