System Verilog parameters in generate block

匿名 (未验证) 提交于 2019-12-03 01:10:02

问题:

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 = 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 for redefining P00 but it compiled and ran and displayed the following instead.

WORDS =       8 tmp    = bb P00    = 33 

If I comment the "parameter P00 = 33" assignment, I get a "Identifier P00 has not been declared yet." error.

It seems that the generate block is being ignored. What is wrong here?

回答1:

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.



回答2:

There has been quite a few questions on here recently using generates and assigns inappropriately not sure if a new tutorial has been written which is not teaching these things correctly.

Parameters or Localparams should not be defined more than once, and they are constants so can not have the value changed. I think you are also missing the parameter keyword from module foo.

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

It is common to use as scaling factors:

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

What you have defined looks like you should just be using a logic not parameter to hold the value;

I would rewrite the whole thing 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 

The use of generate is unnecessary for what you are trying to achieve here.



回答3:

This works (generally say you need to make all 4 generate blocks name as 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 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!