在 Verilog 中验证参数
Verify Parameters in Verilog
我创建了一个模块,它接受一个指定模块数据线字节宽度的参数。它看起来像:
module wrapper#
(
parameter DATA_BYTE_WIDTH = 1
)
(
din, dout, ..
);
localparam DATA_BIT_WIDTH = 8*DATA_BYTE_WIDTH;
input [DATA_BIT_WIDTH-1:0] din;
output [DATA_BIT_WIDTH-1:0] dout;
.....
generate
if( DATA_BYTE_WIDTH == 1 ) begin
// Various modules and interconnects for 1-byte data
else if( DATA_BYTE_WIDTH == 2) begin
// Various modules and interconnects for 2-byte data
else if....
// and so on, for 4, 8, and 16
else
// DATA_BYTE_WIDTH is not a valid value
// HERE is where I want to throw an error
end
endgenerate
// other code
endmodule
问题是唯一有效的宽度是 1、2、4、8 或 16 字节。如果任何其他值用于 DATA_BYTE_WIDTH,则根本不会生成互连。但 Xilinx 似乎并不关心这些。如果提供了无效值,它会很高兴 "generate" 什么都不做:生成的设计综合但根本不起作用。
有没有办法检查参数的值并在无效时抛出错误?我试过 $error
和 assert
(如 here), as well as $display
(as mentioned here 所讨论)。 Xilinx 拒绝使用这些函数中的任何一个,而是抛出语法错误并拒绝继续。
理想情况下,我希望在 generate
中的最后 else
中添加一些内容,但此时我几乎可以接受任何内容。
Verilog 没有一个干净的解决方案来验证参数。至少有一个在 IEEE 标准 1364 的任何版本中都没有提到。最好的 Verilog 解决方法是使用一个不存在的模块。
generate
// ...
else begin // invalid parameter configuration
nonexistent_module_to_throw_a_custom_error_message_for invalid_parameters();
end
endgenerate
A false 替代方法是将不存在的模块行替换为:
initial begin
$display("Runtime error for invalid parameter value %b",DATA_BYTE_WIDTH);
$finish(1);
end
这是一个 false 替代方案,因为大多数综合工具忽略 $display
(我相信他们会忽略 $finish
以及)。你也不会知道有一个参数问题,直到模拟,编译之后。不存在的模块是优越的,因为它是一个语法干净的参数条件编译错误。它只缺少显示违规参数值的消息。
从 IEEE 标准 1800-2009 开始,SystemVerilog 中确实存在一个干净的解决方案,它添加了细化系统任务。看起来 Xilinx ISE 不支持 SystemVerilog。 Xilinx Vivado 有,但我不确定它是否完全符合 LRM。如果可以,请尝试一下。阅读 IEEE Std 1800-2012 § 20.11 细化系统任务 中的完整描述。 (*-2012 可免费下载,以促进 SV 的采用。*-2009 较旧且仍处于付费墙之后。关于详细系统任务的部分在两个版本之间逐字逐句。)
generate
// ...
else begin // invalid parameter configuration
$error("Elaboration error for invalid parameter value %b in", DATA_BYTE_WIDTH);
/* alternative $fatal. This prevents further elaboration from
happening. $error allows the rest of the design to elaborate.
Both block simulation. */
//$fatal(1,"Fatal elab. error for invalid parameter value %b in", DATA_BYTE_WIDTH);
end
endgenerate
我创建了一个模块,它接受一个指定模块数据线字节宽度的参数。它看起来像:
module wrapper#
(
parameter DATA_BYTE_WIDTH = 1
)
(
din, dout, ..
);
localparam DATA_BIT_WIDTH = 8*DATA_BYTE_WIDTH;
input [DATA_BIT_WIDTH-1:0] din;
output [DATA_BIT_WIDTH-1:0] dout;
.....
generate
if( DATA_BYTE_WIDTH == 1 ) begin
// Various modules and interconnects for 1-byte data
else if( DATA_BYTE_WIDTH == 2) begin
// Various modules and interconnects for 2-byte data
else if....
// and so on, for 4, 8, and 16
else
// DATA_BYTE_WIDTH is not a valid value
// HERE is where I want to throw an error
end
endgenerate
// other code
endmodule
问题是唯一有效的宽度是 1、2、4、8 或 16 字节。如果任何其他值用于 DATA_BYTE_WIDTH,则根本不会生成互连。但 Xilinx 似乎并不关心这些。如果提供了无效值,它会很高兴 "generate" 什么都不做:生成的设计综合但根本不起作用。
有没有办法检查参数的值并在无效时抛出错误?我试过 $error
和 assert
(如 here), as well as $display
(as mentioned here 所讨论)。 Xilinx 拒绝使用这些函数中的任何一个,而是抛出语法错误并拒绝继续。
理想情况下,我希望在 generate
中的最后 else
中添加一些内容,但此时我几乎可以接受任何内容。
Verilog 没有一个干净的解决方案来验证参数。至少有一个在 IEEE 标准 1364 的任何版本中都没有提到。最好的 Verilog 解决方法是使用一个不存在的模块。
generate
// ...
else begin // invalid parameter configuration
nonexistent_module_to_throw_a_custom_error_message_for invalid_parameters();
end
endgenerate
A false 替代方法是将不存在的模块行替换为:
initial begin
$display("Runtime error for invalid parameter value %b",DATA_BYTE_WIDTH);
$finish(1);
end
这是一个 false 替代方案,因为大多数综合工具忽略 $display
(我相信他们会忽略 $finish
以及)。你也不会知道有一个参数问题,直到模拟,编译之后。不存在的模块是优越的,因为它是一个语法干净的参数条件编译错误。它只缺少显示违规参数值的消息。
从 IEEE 标准 1800-2009 开始,SystemVerilog 中确实存在一个干净的解决方案,它添加了细化系统任务。看起来 Xilinx ISE 不支持 SystemVerilog。 Xilinx Vivado 有,但我不确定它是否完全符合 LRM。如果可以,请尝试一下。阅读 IEEE Std 1800-2012 § 20.11 细化系统任务 中的完整描述。 (*-2012 可免费下载,以促进 SV 的采用。*-2009 较旧且仍处于付费墙之后。关于详细系统任务的部分在两个版本之间逐字逐句。)
generate
// ...
else begin // invalid parameter configuration
$error("Elaboration error for invalid parameter value %b in", DATA_BYTE_WIDTH);
/* alternative $fatal. This prevents further elaboration from
happening. $error allows the rest of the design to elaborate.
Both block simulation. */
//$fatal(1,"Fatal elab. error for invalid parameter value %b in", DATA_BYTE_WIDTH);
end
endgenerate