2

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

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 尚未声明”。错误。

似乎生成块被忽略了。这里有什么问题?

4

3 回答 3

1

将参数定义放置在生成块内会生成相对于生成块内的分层范围的新局部参数。defparam通常是覆盖参数值的方法。然而IEEE 标准 1800-2012在 §23.10.1 中明确声明 adefparam不能影响其父范围:

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

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

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

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

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

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所说,您可以定义大多数parametersaslogic并使用组合块。但是,我强烈坚持使用always_comb块而不是 aalways @*来保证值是计算的。如LRM §9.2.2.2.2 所述:

always_comb 在时间 0 自动执行一次,而 always @* 一直等到推断的敏感度列表中的信号发生变化。

于 2013-09-28T01:04:30.187 回答
1

最近这里有很多问题,不恰当地使用生成和分配,不确定是否编写了一个新教程,它没有正确地教授这些东西。

参数或 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 。

于 2013-07-19T06:56:59.343 回答
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
于 2013-09-16T18:50:47.150 回答