为什么这两种索引模式之一给我一个 "index out of bounds" 错误?
Why does one of these two indexing patterns give me an "index out of bounds" error?
使用 ncsim 时,以下代码会引发错误:
Bit-select or part-select index out of declared bounds.
但是,执行完全相同操作的注释掉的代码却没有。是我遗漏了什么还是编译器弄错了?
module pd__test;
genvar i, j;
reg [10-1:0] assign_from_reg;
reg [256:0] assign_to_reg;
generate
for (i=0; i<2; i=i+1) begin
for (j=0; j<13; j=j+1) begin
always @* begin
if (i+2*j < 25) begin
// gives me an index out of bounds error
assign_to_reg[10*(i+2*j)+9 : 10*(i+2*j)] = assign_from_reg;
// gives me no such error, however the indices are the same
// assign_to_reg[10*(i+2*j)+9 -: 10] = assign_from_reg;
end else begin
// do something else
end
end
end
end
endgenerate
endmodule
我运行一个python脚本来打印索引以仔细检查:
for i in range(2):
for j in range(13):
if (i+(2*j) < 25):
print("[", 10*(i+(2*j))+9, ":", 10*(i+(2*j)), "]")
打印:
[ 9 : 0 ]
[ 29 : 20 ]
[ 49 : 40 ]
[ 69 : 60 ]
[ 89 : 80 ]
[ 109 : 100 ]
[ 129 : 120 ]
[ 149 : 140 ]
[ 169 : 160 ]
[ 189 : 180 ]
[ 209 : 200 ]
[ 229 : 220 ]
[ 249 : 240 ]
[ 19 : 10 ]
[ 39 : 30 ]
[ 59 : 50 ]
[ 79 : 70 ]
[ 99 : 90 ]
[ 119 : 110 ]
[ 139 : 130 ]
[ 159 : 150 ]
[ 179 : 170 ]
[ 199 : 190 ]
[ 219 : 210 ]
[ 239 : 230 ]
将条件 if (i+2*j < 25)
移到 always
块之外:
module pd__test;
genvar i, j;
reg [10-1:0] assign_from_reg;
reg [256:0] assign_to_reg;
generate
for (i=0; i<2; i=i+1) begin
for (j=0; j<13; j=j+1) begin
if (i+2*j < 25) begin
always @* begin
//assign_to_reg[10*(i+2*j)+9 : 10*(i+2*j)] = assign_from_reg;
assign_to_reg[10*(i+2*j)+9 -: 10] = assign_from_reg;
end
end
end
end
endgenerate
endmodule
对我来说,这两个作业编译时没有警告或错误。
你要求 verilog 编译器在 always 块中编译这段代码
assign_to_reg[10*(i+2*j)+9 -: 10]
其中 i == 1
和 j == 12
由生成块生成为:
assign_to_reg[259 : 250]
以上显然超出了声明的范围[256:0]。
将 'if' 移动到生成块中,正如@toolic 所建议的那样,将导致 verilog not 根本不生成最后一个 always 块,因此,它不会已编译,不会生成 warning/error。
因此,与生成块的另一个解决方案是将您的assign_to_reg声明为[259:0]
。
但最好的解决方案是一起摆脱 generate 块,并将 all 循环移动到 single always 中区块:
always @* begin
for (int i=0; i<2; i=i+1) begin
for (int j=0; j<13; j=j+1) begin
if (i+2*j < 25) begin
assign_to_reg[10*(i+2*j)+9 -: 10] = assign_from_reg;
end
end
end
end
这应该让编译器在 运行 时计算索引,并且也不会导致越界访问。
使用 ncsim 时,以下代码会引发错误:
Bit-select or part-select index out of declared bounds.
但是,执行完全相同操作的注释掉的代码却没有。是我遗漏了什么还是编译器弄错了?
module pd__test;
genvar i, j;
reg [10-1:0] assign_from_reg;
reg [256:0] assign_to_reg;
generate
for (i=0; i<2; i=i+1) begin
for (j=0; j<13; j=j+1) begin
always @* begin
if (i+2*j < 25) begin
// gives me an index out of bounds error
assign_to_reg[10*(i+2*j)+9 : 10*(i+2*j)] = assign_from_reg;
// gives me no such error, however the indices are the same
// assign_to_reg[10*(i+2*j)+9 -: 10] = assign_from_reg;
end else begin
// do something else
end
end
end
end
endgenerate
endmodule
我运行一个python脚本来打印索引以仔细检查:
for i in range(2):
for j in range(13):
if (i+(2*j) < 25):
print("[", 10*(i+(2*j))+9, ":", 10*(i+(2*j)), "]")
打印:
[ 9 : 0 ]
[ 29 : 20 ]
[ 49 : 40 ]
[ 69 : 60 ]
[ 89 : 80 ]
[ 109 : 100 ]
[ 129 : 120 ]
[ 149 : 140 ]
[ 169 : 160 ]
[ 189 : 180 ]
[ 209 : 200 ]
[ 229 : 220 ]
[ 249 : 240 ]
[ 19 : 10 ]
[ 39 : 30 ]
[ 59 : 50 ]
[ 79 : 70 ]
[ 99 : 90 ]
[ 119 : 110 ]
[ 139 : 130 ]
[ 159 : 150 ]
[ 179 : 170 ]
[ 199 : 190 ]
[ 219 : 210 ]
[ 239 : 230 ]
将条件 if (i+2*j < 25)
移到 always
块之外:
module pd__test;
genvar i, j;
reg [10-1:0] assign_from_reg;
reg [256:0] assign_to_reg;
generate
for (i=0; i<2; i=i+1) begin
for (j=0; j<13; j=j+1) begin
if (i+2*j < 25) begin
always @* begin
//assign_to_reg[10*(i+2*j)+9 : 10*(i+2*j)] = assign_from_reg;
assign_to_reg[10*(i+2*j)+9 -: 10] = assign_from_reg;
end
end
end
end
endgenerate
endmodule
对我来说,这两个作业编译时没有警告或错误。
你要求 verilog 编译器在 always 块中编译这段代码
assign_to_reg[10*(i+2*j)+9 -: 10]
其中 i == 1
和 j == 12
由生成块生成为:
assign_to_reg[259 : 250]
以上显然超出了声明的范围[256:0]。
将 'if' 移动到生成块中,正如@toolic 所建议的那样,将导致 verilog not 根本不生成最后一个 always 块,因此,它不会已编译,不会生成 warning/error。
因此,与生成块的另一个解决方案是将您的assign_to_reg声明为[259:0]
。
但最好的解决方案是一起摆脱 generate 块,并将 all 循环移动到 single always 中区块:
always @* begin
for (int i=0; i<2; i=i+1) begin
for (int j=0; j<13; j=j+1) begin
if (i+2*j < 25) begin
assign_to_reg[10*(i+2*j)+9 -: 10] = assign_from_reg;
end
end
end
end
这应该让编译器在 运行 时计算索引,并且也不会导致越界访问。