生成块中的系统Verilog参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成块中的系统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尚未声明。”错误。

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

答案

将参数定义放置在生成块内会生成相对于生成块内的分层范围的新本地参数。 defparam通常是覆盖参数值的方式。然而,IEEE std 1800-2012明确指出defparam不能影响其在第23.10.1节中的父范围:

生成块实例(见第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));

挑战可能是每个参数可能需要其自己的功能。使用具有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在零时自动执行一次,而始终@ *等待,直到推断的灵敏度列表中的信号发生更改。

另一答案

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

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

另一答案

这工作(通常说你需要使所有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

以上是关于生成块中的系统Verilog参数的主要内容,如果未能解决你的问题,请参考以下文章

Notepad++编辑器——Verilog代码片段直接编译

您好,刚开始接触verilog 请问,是否reg型信号必须在always块中,而always块的输出可以不是reg型数据

在verilog HDL语言中的阻塞赋值和非阻塞赋值究竟有啥不同?同一变量在不同的过程块中(同时触发)又是如

matlab如何生成verilog

Verilog 中的案例陈述?

Verilog学习笔记基本语法篇········ 生成块