Index-based Array Right Shifter using concatenation; Error: range is not allowed in prefix

120 Views Asked by At

I am trying to implement an array Right Shifter.

It accepts an array of integers, then right shifts everything to the right-side of specified index position, and inserts a specified integer value at index position.

For e.g.

If arr = {1, 2, 3, 4, 5, 6, 7, .... 16}; idx = 4; insert_value = 0; then new_arr = {1, 2, 3, 0, 4, 5, 6, ... 15}

Below is my code:

// Right shifts the arrays from given index, and inserts given value.

`timescale 1ns / 1ps

module indexed_rsh(
                        input wire [511:0] arr,
                        input wire [3:0] idx,
                        input wire [31:0] insert_value,
                        output wire [511:0] new_arr
                    );

logic [0:15][31:0] arr_sig, new_arr_sig;

assign arr_sig = arr;
assign new_arr = new_arr_sig;

genvar i;
generate
    for (i=0; i < 16; i = i + 1)
        begin
            always_comb
                if(idx == i)
                    new_arr_sig [0:15][31:0]  = {arr_sig[0:i-1][31:0], insert_value, arr_sig[i:14][31:0]};
        end
endgenerate

endmodule

On EDAplayground, I get a syntax error on line 21, and "error: invalid module item" on line 23.

In Vivado, I got an error saying "range is not allowed in prefix" on line 23. If range is not allowed in prefix, what is a good way to index 2D arrays?

2

There are 2 best solutions below

0
On

Here is one way to insert a 32-bit value into a 512-bit value at a given 32-bit index offset, while shifting the other bits right:

module indexed_rsh (
    input wire [511:0] arr,
    input wire [3:0] idx,
    input wire [31:0] insert_value,
    output reg [511:0] new_arr
);

always_comb begin
    for (int i=0; i<16; i++) begin
        int offset32;
        offset32 = 32*i;
        for (int j=0; j<32; j++) begin
            if (i < idx) begin
                new_arr[j + offset32] = arr[j + offset32];
            end else if (i == idx) begin
                new_arr[j + offset32] = insert_value[j];
            end else begin
                new_arr[j + offset32] = arr[j + offset32 - 32];
            end
       end
    end
end

endmodule

If you want to use the internal 2D packed arrays:

module indexed_rsh (
    input wire [511:0] arr,
    input wire [3:0] idx,
    input wire [31:0] insert_value,
    output wire [511:0] new_arr
);

logic [15:0][31:0] arr_sig, new_arr_sig;
assign arr_sig = arr;
assign new_arr = new_arr_sig;

always_comb begin
    for (int i=0; i<16; i++) begin
        if (i < idx) begin
            new_arr_sig[i] = arr_sig[i];
        end else if (i == idx) begin
            new_arr_sig[i] = insert_value;
        end else begin
            new_arr_sig[i] = arr_sig[i-1];
        end
    end
end
endmodule
2
On

(Reply to toolic, posting as answer to attach an image)

Hi, I would like to update here that the above code does not synthesize the expected circuit.

Maybe Vivado is getting confused due to usage of 'i' inside the 'if' conditions, and trying to generate hardware for that.

I tried using generate, to specify that I don't want to synthesize the if conditions but I am getting syntax errors. I will need to figure out where to ideally place generate within the nest of always->for->if blocks, for my ideal circuit.

For now, I ended up doing a hierarchical module, containing the logic shown in the below image. The logic shown in the image is instantiated for each element of the array. I hardwired the signals ref_const[i] to value 'i' (0 for 1st instantiation, 1 for 2nd, ...) using a generate for loop.

(I assigned Sel=0 to error, cause my array will always have non-zero values)

enter image description here