为什么这两种索引模式中的一种给我一个“索引越界”错误?

时间:2018-01-25 19:57:42

标签: indexing verilog bus

使用ncsim时,以下代码会引发错误:

  

声明边界的位选择或部分选择索引。

然而,完全相同的注释掉的代码却没有。我错过了什么或者编译器错了吗?

   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脚本来打印indeces以进行双重检查:

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 ]

2 个答案:

答案 0 :(得分:1)

将条件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

这两个作业都是在没有警告或错误的情况下编译的。

答案 1 :(得分:1)

你要求verilog编译器在always块

中编译这段代码
assign_to_reg[10*(i+2*j)+9 -: 10]
生成块生成i == 1j == 12

 assign_to_reg[259 : 250]

以上显然超出了声明的界限[256:0]。

将'if'移动到generate块中,因为@toolic建议会导致verilog not 生成最后一个始终块,因此,它将不会被编译,也不会出现警告/错误生产。

因此, 生成块的其他解决方案是将assign_to_reg声明为[259:0]

然而,最好的解决方案是一起摆脱生成块,并在单个always块中移动 all 你的循环:

  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

这应该让编译器在运行时计算索引,也不会导致越界访问。