-1

With ncsim the following code throws the error:

Bit-select or part-select index out of declared bounds.

However, the commented out code which does exactly the same thing doesn't. Am I missing something or is the compiler mistaken?

   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

I ran a python script to print the indeces to double check:

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)), "]")

Prints:

[ 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 ]
Charles Clayton
  • 17,005
  • 11
  • 87
  • 120

2 Answers2

1

Move the conditional if (i+2*j < 25) outside of the always block:

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

Both assignments compile without warnings or errors for me.

toolic
  • 57,801
  • 17
  • 75
  • 117
  • Hmm, you're right that moving the `always` up somehow resolves the error in the example. Unfortunately I can't really do that in the full design because there's an `else` associated with the `if`, which would mean I'm assigning to the same `reg` in separate `always` blocks which won't synthesize. Weird that ncsim is choking on this. – Charles Clayton Jan 25 '18 at 20:31
  • My question is why it's generating the warning, this doesn't really answer that. I already showed I can get around the warning with the `-: 10` indexing without having to move around the `always` block. – Charles Clayton Jan 26 '18 at 15:22
1

you asked verilog compiler to compile this code in the always block

assign_to_reg[10*(i+2*j)+9 -: 10]

which for i == 1 and j == 12 is generated by the generate block as:

 assign_to_reg[259 : 250]

The above is clearly outside of the declared bounds [256:0].

Moving the 'if' into the generate block, as @toolic suggested would cause verilog not to generate the last always block at all, therefore, it will not be compiled and no warning/error would be produced.

So, the other solution with generate blocks would be to declare your assign_to_reg as [259:0].

And yet the best solution would be to get rid of the generate block all together and move all your loops inside the single always block:

  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

This should let compiler to calculate indexes at run-time and will not cause out-of-bound access as well.

Serge
  • 11,616
  • 3
  • 18
  • 28
  • I didn't ask it to compile that though, because when `i == 1` and `j == 12`, then `(i+2*j == 1+12*2) == 25`. So `if (i+2*j < 25)` isn't satisfied and it shouldn't be generated. That's why it works when I use the `-:`. – Charles Clayton Jan 26 '18 at 00:37
  • 1
    You can think of the `generate` block as a preprocessor. The `generate` statement evaluates all genvar expressions and generates the always blocks with constant values. So, it genarates 24 different always blocks, and the last one, like this: `always if(25 < 25) assign_to_reg[259:250]=asiign_fom_reg;` The compiler gives you a waring, based on this view of the code. – Serge Jan 26 '18 at 11:46
  • Oh I see, thank you. That makes more sense! Still strange that it would generate `[259 -: 10]` and not throw a warning for that code though. – Charles Clayton Jan 26 '18 at 15:18