是否可以在SystemVerilog中参数化数组元素的宽度?
目前,我正在做以下事情:
localparam N = 5;
localparam int widths[0:N - 1] = '{32, 16, 8, 4, 2};
localparam max_width = widths[0];
bit [max_width - 1:0] data [0:N - 1];
然后在代码中,我仅根据
data
中指定的相应元素的宽度来访问widths
,期望合成过程会消除不必要的部分:
smth_3 <= data[3][widths[3] - 1:0];
data[1][widths[1] - 1:0] <= smth_1;
有没有一种方法可以通过类似数组的访问来实现这一点,以获得更好的代码可读性和建模便利性?
PS。我已经看到(here)一种使用生成块的方法,但是,它不合适,因为在 Vivado 中我无法使用这样的迭代索引访问数据。
module playgroynd();
localparam N = 5;
localparam int widths [0:N - 1] = '{32, 16, 8, 4, 2};
for (genvar i = 0; i < N; i++) begin : stage
bit [widths[i] - 1:0] data;
end
initial begin
for (int i = 0; i < N; i++) begin
$display("stage data = %0d, width %0d", stage[i].data, $size(stage[i].data)); // Cannot be simulated
end
// $display("stage data = %0d, width %0d", stage[0].data, $size(stage[0].data)); // Can be simulated
end
endmodule
正确。 verilog 中所有基于参数的表达式(生成块)均在编译的细化阶段解析。它们在运行时之前完全展开。
内部过程块(always、initial、final)的所有循环和表达式在运行时进行评估。
因此,在编译时解析的索引表达式在运行时无效。
访问此类数据的唯一方法是仅在编译时。在您的情况下,您可以将初始块移动到生成块内,如您的修改示例所示:
module playgroynd();
localparam N = 5;
localparam int widths [0:N - 1] = '{32, 16, 8, 4, 2};
for (genvar i = 0; i < N; i++) begin : stage
bit [widths[i] - 1:0] data;
end
for (genvar i = 0; i < N; i++) begin : init
initial begin
$display("stage data = %0d, width %0d", stage[i].data, $size(stage[i].data)); // Cannot be simulated
end
end
endmodule