2
\$\begingroup\$

I'm trying to create 8 16-bit registers in Verilog that will take 16-bit values from a 128-bit long shift register. Obviously, I have to make use of index variable such as "i" to make this work, but I get an error. How to do this with variable index?

Error: "i" is not a constant. Range must be bounded by constant expressions.

parameter DATA_WIDTH = 16;
parameter ratio = 8;
parameter shift_reg_size = DATA_WIDTH * ratio;
integer i;
reg [shift_reg_size-1:0] shift_reg;
reg [DATA_WIDTH-1:0] reg_data [ratio-1:0];
always @(posedge clk or negedge rst)
 begin
 if (~rst)
 begin
 for (i = 0; i < ratio; i = i + 1)
 begin
 reg_data[i] <= 0;
 end
 end
 else
 begin
 for (i = 0; i < ratio; i = i + 1)
 begin
 reg_data[ratio-i-1] <= shift_reg[((shift_reg_size-1)-(DATA_WIDTH*i)):((shift_reg_size-DATA_WIDTH)-(DATA_WIDTH*i))]; 
 // Error on above line
 end
 end

Basically, the for loop translates to:

reg_data[7] <= shift_reg[127:112]; 
reg_data[6] <= shift_reg[111:96];
reg_data[5] <= shift_reg[95:80];
reg_data[4] <= shift_reg[79:64];
reg_data[3] <= shift_reg[63:48];
reg_data[2] <= shift_reg[47:32];
reg_data[1] <= shift_reg[31:16];
reg_data[0] <= shift_reg[15:0];

But I want to make it work with index variable. Is it possible?

Thanks.

blackblade
4885 silver badges11 bronze badges
asked Aug 17, 2022 at 4:29
\$\endgroup\$
1

1 Answer 1

3
\$\begingroup\$

You will need to use the indexed part select operator: out <= in[LSB+:WIDTH] or out <= in[MSB-:WIDTH].

So in your case:

reg_data[ratio-i-1] <= shift_reg[((shift_reg_size-1)-(DATA_WIDTH*i)) -: DATA_WIDTH];

Or

reg_data[i] <= shift_reg[(DATA_WIDTH*i) +: DATA_WIDTH];

The reason for this is that the regular range selection operator doesn't allow the use of variables. For example if you said x[var1 : var2], then if var1-var2 could ever change you would be asking the synthesis tools to infer a variable width data bus which is not possible.

Even if you use the same variable on both sides of the range, it is still possible to get variable widths due to truncation when the values are calculated, so it is still not possible to ensure a constant width bus.

The indexed part select on the other hand is different. Here we specify the width of the selection directly (using a constant expression calculatable at synthesis). Because the width of the selection is now guaranteed to be fixed, we can now use a variable for the starting (+:) or ending (-:) index, which will now nicely infer a multiplexer.

answered Aug 17, 2022 at 8:58
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.