生成块中的系统Verilog参数

时间:2013-07-18 21:33:32

标签: parameters system-verilog

我想根据在实例化模块时设置的参数设置参数。我有以下内容。

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

我希望重新定义P00会出错,但是编译并运行并显示以下内容。

WORDS =       8
tmp    = bb
P00    = 33

如果我评论“参数P00 = 33”分配,我得到“标识符P00尚未声明”。错误。

似乎忽略了生成块。这有什么不对?

3 个答案:

答案 0 :(得分:1)

在生成块中放置参数定义会生成相对于生成块中的分层范围的新本地参数。 defparam通常是覆盖参数值的方法。但是IEEE std 1800-2012明确指出defparam不能影响其在§23.10.1中的父作用域:

  

生成块中或下的层次结构中的defparam语句   实例(见第27条)或实例数组(见28.3.5和   23.3.2)不得更改该层次结构之外的参数值。

对于复杂的派生参数分配,您可以使用函数。例如:

parameter P01 = FUNC01(WORDS,P00);
function byte FUNC01(input byte w,p);
/* ... */
endfunction

这也是合法的:module foo #(parameter WORDS, P00=FUNC00(WORDS));

挑战可能是每个参数可能需要自己的功能。使用具有struct数据类型的参数是将分配分组到单个函数中的潜在工作。这种方法需要通过模拟器,合成器和其他工具进行评估。例如:

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;

正如Morgan所述,您可以将parameters的大多数定义为logic并使用组合块。但是,我强烈坚持使用always_comb块而不是always @*来保证值是计算。如LRM§9.2.2.2.2中所述:

  

always_comb在零时自动执行一次,而始终   @ *等待,直到推断的灵敏度中的信号发生变化   列表。

答案 1 :(得分:0)

最近有很多问题使用生成和分配不当,不确定是否编写了一个没有正确教授这些内容的新教程。

参数或Localparams不应定义多次,并且它们是常量,因此不能更改值。我想你也缺少模块foo的参数关键字。

module foo #(
  parameter WORDS = 8
);

localparam P00 = WORD;

通常用作缩放因子:

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

您定义的内容看起来应该只使用逻辑非参数来保存值;

我会把整个事情重写为:

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

对于您在此处尝试实现的目标,不必使用generate。

答案 2 :(得分:0)

这是有效的(通常说你需要使所有4个生成块的名称相同):

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