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.
-
1\$\begingroup\$ Does this answer your question? Non-constant index in a synthesizable Verilog deserializer \$\endgroup\$toolic– toolic2022年08月17日 10:33:08 +00:00Commented Aug 17, 2022 at 10:33
1 Answer 1
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.