生成块中的系统 Verilog 参数
Posted
技术标签:
【中文标题】生成块中的系统 Verilog 参数【英文标题】:System Verilog parameters in generate block 【发布时间】:2013-07-18 21:33:32 【问题描述】:我想根据实例化模块时设置的参数设置参数。我有以下。
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 尚未声明”。错误。
似乎生成块被忽略了。这里有什么问题?
【问题讨论】:
如果我正确阅读了语言规范,那么当您在生成块中使用参数类型时,您实际上是在不同范围内创建新参数。它指出,“在 [生成块] 中,参数关键字应是 localparam 关键字的同义词。”此外,“本地参数与参数相同,只是它们不能直接通过...实例参数值分配进行修改。”如果您有语言参考的副本并想了解更多信息,请查看第 6.20.4 节。在我看来,您需要一种不同的方法来解决这个问题。 @Dan - 谢谢。我确实阅读了上面的手册部分,但我没有得到生成块实际上创建的范围与模块的范围不同。我尝试显示 C.P00 但这也不起作用。如果创建了新范围,我如何访问它? 我不太清楚。我自己刚开始学习这门语言,但@Morgan 下面似乎有一个很好的答案。 【参考方案1】:最近这里有很多问题,使用不恰当的生成和分配不确定是否编写了一个新教程,它没有正确地教授这些东西。
Parameters 或 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。
【讨论】:
谢谢。您的评论很好,并且确实有效,但这并不是我所需要的。我使用了 generate 块,因为我只想根据 WORDS 的数量合成一个案例。该示例是该模块的简化版本。参数的数量随着 WORDS 的数量而增加。也许我误解了您所说的 generate 的使用。此外,添加了顶部的参数声明 - 设置 P00=33 - 只是为了查看是否在生成块中设置了任何参数。我添加它会导致错误,但它没有导致错误。 @user2382841 我会仔细检查您的警告以及错误。生成对于基于参数或将块互连在一起创建层次结构(多个实例)很有用。如果输入是恒定的,则输出是恒定的,综合工具将很好地创建最少的硬件。如果 P00 是一个常数,逻辑(reg)或参数没有区别。【参考方案2】:将参数定义放在生成块内会生成一个相对于生成块内的层次范围的新局部参数。 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));
一个挑战可能是每个参数可能需要自己的功能。使用具有结构数据类型的参数是一种潜在的解决方法,可以将分配分组到单个函数中。这种方法需要通过您的模拟器、合成器和其他工具进行评估。示例:
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 在时间 0 自动执行一次,而 always @* 等到推断灵敏度的信号发生变化 列表。
【讨论】:
【参考方案3】:这可行(通常说您需要使所有 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 参数的主要内容,如果未能解决你的问题,请参考以下文章
您好,刚开始接触verilog 请问,是否reg型信号必须在always块中,而always块的输出可以不是reg型数据
verilog 如何处理需要在两个always 中赋值的变量