Verilog system parameters in block generation

I would like to set a parameter based on the parameter that is set when the module is instantiated. I have the following.

module foo #(WORDS = 8); parameter P00 = 33; logic [7:0] tmp; generate case (WORDS) 4: begin : A assign tmp = 8'haa; parameter P00 = 4; end 8: begin : B assign tmp = 8'hbb; parameter P00 = 8; end 16: begin : C assign tmp = 8'hcc; parameter P00 = 16; end default: begin : D assign tmp = 8'hdd; parameter P00 = 8; end endcase endgenerate initial begin $display ("WORDS = %d", WORDS); $display ("tmp = %h", tmp); $display ("P00 = %d", P00); end endmodule 

I expected to get an error to override P00, but it compiled and ran and displayed the following.

 WORDS = 8 tmp = bb P00 = 33 

If I comment on the assignment of the parameter "P00 = 33", I get "P00 ID not yet declared." error.

The generation block seems to be ignored. What is wrong here?

+1
source share
3 answers

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(/* 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 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.

+1
source

Recently, there have been many questions related to the use of generators and assignment of inadequately unsure whether a new textbook has been written that incorrectly teaches these things.

Parameters or Local parameters should not be defined more than once, and they are constants, so changing the value cannot. I think you also lack the parameter keyword from the foo module.

 module foo #( parameter WORDS = 8 ); localparam P00 = WORD; 

It is generally accepted to use as scaling factors:

 module foo #( parameter WIDTH = 8 parameter MAX_VALUE = 2**WIDTH ); 

What you defined looks like you should just use a boolean parameter to hold the value;

I would rewrite all of this as:

 module foo #(WORDS = 8); logic [31:0] P00 = 33; logic [7:0] tmp; always @* begin case (WORDS) 4: begin : A tmp = 8'haa; P00 = 4; end 8: begin : B tmp = 8'hbb; P00 = 8; end 16: begin : C tmp = 8'hcc; P00 = 16; end default: begin : D tmp = 8'hdd; P00 = 8; end endcase end 

Using generation is not necessary for what you are trying to achieve here.

0
source

This works (they usually say that you need to make all 4 block block names the same):

 module foo #(WORDS = 8); parameter P00 = 33; logic [7:0] tmp; generate case (WORDS) 4: begin : B assign tmp = 8'haa; parameter P00 = 4; end 8: begin : B assign tmp = 8'hbb; parameter P00 = 8; end 16: begin : B assign tmp = 8'hcc; parameter P00 = 16; end default: begin : B assign tmp = 8'hdd; parameter P00 = 8; end endcase endgenerate initial begin $display ("WORDS = %d", WORDS); $display ("tmp = %h", tmp); $display ("P00 = %d", B.P00); end endmodule 
0
source

Source: https://habr.com/ru/post/1494865/


All Articles