Parameters 生成块中的系统Verilog参数

Parameters 生成块中的系统Verilog参数,parameters,system-verilog,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;

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

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
如果我对“parameter P00=33”赋值进行注释,我会得到一个“标识符P00尚未声明。”错误


似乎正在忽略生成块。这里出了什么问题?

最近在这里出现了很多问题,不恰当地使用了generates和assigns,不确定是否编写了新教程,但没有正确地教授这些内容

参数或Localparams不应定义多次,它们是常量,因此不能更改值。我认为您还缺少模块foo中的parameter关键字

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是不必要的。

最近在此处出现了很多问题,不适当地使用generates和assigns不确定是否编写了新教程,但没有正确地教授这些内容

参数或Localparams不应定义多次,它们是常量,因此不能更改值。我认为您还缺少模块foo中的parameter关键字

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个generate块的名称相同):

这是可行的(一般说来,您需要使所有4个生成块的名称相同):


将参数定义放置在生成块内会生成一个相对于生成块内的层次范围的新局部参数
defparam
通常是覆盖参数值的方法。但是,明确规定,
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
这也是合法的:
模块foo#(参数字,P00=FUNC00(字))

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

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;
如前所述,您可以将大多数
参数定义为
逻辑
,并使用组合块。但是,我强烈要求使用
始终_comb
块,而不是
始终@*
来保证值是可计算的。如§9.2.2.2.2所述:

always_comb在时间零点自动执行一次,而 @*等待,直到推断灵敏度中的信号发生变化 名单


将参数定义放置在生成块内会生成一个相对于生成块内的层次范围的新局部参数
defparam
通常是覆盖参数值的方法。但是,明确规定,
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
这也是合法的:
模块foo#(参数字,P00=FUNC00(字))

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

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;
如前所述,您可以将大多数
参数定义为
逻辑
,并使用组合块。但是,我强烈要求使用
始终_comb
块,而不是
始终@*
来保证值是可计算的。如§9.2.2.2.2所述:

always_comb在时间零点自动执行一次,而 @*等待,直到推断灵敏度中的信号发生变化 名单


如果我正确地阅读了语言规范,那么当您在生成块中使用参数类型时,实际上是在不同的范围内创建了一个新参数。它指出,“在[generate blocks]中,parameter关键字应是localparam关键字的同义词。”此外,“本地参数与参数相同,只是它们不能由……实例参数值赋值直接修改。”如果您有语言参考的副本并想了解更多信息,请参阅第6.20.4节。在我看来,你需要一种不同的方法来解决这个问题。@Dan-谢谢。我确实阅读了上面的手册部分,但我没有发现generate块实际上创建了与模块不同的作用域。我尝试显示C.P00,但也不起作用。如果创建了一个新的作用域,我如何访问它?我不太清楚。我自己刚刚开始学习这门语言,但是@Morgan似乎有一个很好的答案。如果我正确地阅读了语言规范,那么您实际上是在以不同的方式创建一个新参数