在 Systemverilog 中选择生成语句而不是定义宏和反之亦然的准则是什么?
例如,如果我想有条件地实例化模块 1 或模块 2,似乎我可以做
`ifdef COND1
module1 ();
`else
module2 ();
或者
generate
if (COND1) begin
module1 ();
end else begin
module2();
end
endgenerate
在 Systemverilog 中选择生成语句而不是定义宏和反之亦然的准则是什么?
例如,如果我想有条件地实例化模块 1 或模块 2,似乎我可以做
`ifdef COND1
module1 ();
`else
module2 ();
或者
generate
if (COND1) begin
module1 ();
end else begin
module2();
end
endgenerate
人们会有不同的意见,但两者之间的一大区别是生成允许不同的实例进行不同的配置,而宏则不允许。这是因为生成是在细化时评估的,而不是在编译时。
例如,如果我们有一个模块:
module ahwoogaa #(bit COND1) ();
generate
if (COND1) begin
module1 ();
end else begin
module2();
end
endgenerate
endmodule
我可以像这样用 COND1 实例化两次:
module neeenaaaw();
ahwoogaa #(1'b0) alarm1();
ahwoogaa #(1'b1) alarm2();
endmodule
使用 adefine
您必须COND1
为所有实例设置一个值,因为您在编译模块时设置了一次值。
我个人说只要有可能就去生成。
`ifdef
可以在端口列表中使用:
module music
output [31:0] left,
`ifdef STEREO
output [31:0] right,
`enfif
...
生成允许循环,实例化 X 次
genvar inst;
generate
for (inst=0; inst<3; inst=inst+1) begin : gen_block
sub_module instancex( .clk, .din(din[inst]), .dout(dout[inst]) );
end
endgenerate
注意:这引入了额外的层次结构(gen_block)。
我假设这些问题仅涉及条件实例化。
前段时间我们也遇到过类似的困境,当时我们的项目最初是为了集成到特定平台而开发的,必须适应额外的平台。我们想使用 IFDEFs/Generates 来区分单个源代码。
在我看来:
1) IFDEF 看起来比 Generates 简单得多(它们确实如此),但它们很危险。仅当您完全确定您的条件实例化将是独占的(请参阅 Paul S 的答案),您无法使用 generate 实现相同的功能,并且您完全确定您需要此条件实例化时才使用它们。使用 IFDEF 的通常位置是在顶级层次结构中。
编辑: StackOverflow 上还有另一个问题,这是验证工程师因某些设计师滥用 `ifdefs 而苦苦挣扎的一个例子。
2)在我用上面的 1 警告你之后,我可以看出 IFDEF 有一个巨大的优势(因为它们被预处理):你可以有条件地用 IFDEF 实例化网络、参数和端口。比较 IFDEF 的以下用法:
module module1 (
input in1,
output logic out1
`ifdef COND
, output logic out2
`endif
);
assign out1 = in1;
`ifdef COND
submodule submodule1(.in(in1), .out(out2));
`else
endmodule
并生成:
module module1 (
input in1,
output logic out1,
output logic out2
);
assign out1 = in1;
generate if (COND)
submodule submodule1(.in(in1), .out(out2));
else
assign out2 = in1;
endgenerate
endmodule
在上面的(非常简单的)示例中,当 COND 不为真并且您使用 IFDEF 时,您可能不必担心驱动“out2”——该端口将不存在。不利的一面是,在实例化“module1”时必须使用相同的 IFDEF。在这个例子中,IFDEF 的优势可能并不明显,但假设您有 100 个端口(或网络)连接某个子模块。如果子模块未实例化,则在使用 Generate 时所有这些端口都会绑定到某个值,但您可以使用 IFDEF 删除它们。
3) 正如 Morgan 所提到的,Generate 引入了一层额外的层次结构。虽然在设计导航器中看到这一点有点令人恼火,但当您想将生成插入现有代码并且有一些工具使用模块路径时,它会成为@ss 中的真正痛苦 - 您必须找到所有这些工具和在那里改变层次结构。
4)我听说IFDEF“老化”得很厉害。这意味着如果您使用 IFDEF 而不是 Generates,那么维护您的代码将更加困难。
总结:在尝试了一些时间来区分我们的设计与 IFDEF 和 Generates 之后,我们意识到这并不实用。现在我们并行维护两个源代码 - 每个平台一个。在顶层模块中使用 IFDEF 来移除/切换模块并移除不必要的端口和参数。当您想以稍微不同的参数化使用相同的模块时,请使用 Generates。不要使用这些结构来对您的设计进行重大更改。