Verilog vector inner product
I am trying to implement a synthesizable verilog module, which produces a vector product of 2 vector/arrays, each containing eight 16-bit unsigned integers. Design Compiler reported error that symbol i must be a constant or parameter
. I don't know how to fix it. Here's my code.
module VecMul16bit (a, b, c, clk, rst);
// Two vector inner product, each has 8 elements
// Each element is 16 bits
// So the Output should be at least 2^32*2^3 = 2^35 in order to
// prevent overflow
// Output is 35 bits
input clk;
input rst;
input [127:0] a,b;
output [35:0] c;
reg [15:0] a_cp [0:7];
reg [15:0] b_cp [0:7];
reg [35:0] c_reg;
reg k,c_done;
integer i;
always @ (a)
begin
for (i=0; i<=7; i=i+1) begin
a_cp[i] = a[i*15:i*15+15];
end
end
always @ (b)
begin
for (i=0; i<=7; i=i+1) begin
b_cp[i] = b[i*15:i*15+15];
end
end
assign c = c_reg;
always @(posedge clk or posedge rst)
begin
if (rst) begin
c_reg <= 0;
k <= 0;
c_done <= 0;
end else begin
c_reg <= c_done ? c_reg : (c_reg + a_cp[k]*b_cp[k]);
k <= c_done ? k : k + 1;
c_done <= c_done ? 1 : (k == 7);
end
end
endmodule
As you can see, I'm trying to copy a
to a_cp
through a loop, is this the right way to do it?
If yes, how should I defined it i
and can a constant be used as a stepper in for loop?
Solution 1:
A part select in verilog must have constant bounds. So this is not allowed:
a_cp[i] = a[i*15:i*15+15];
Verilog-2001 introduced a new indexed part select syntax where you specify the starting position and the width of the selected group of bits. So, you need to replace the above line by:
a_cp[i] = a[i*15+:16];
This takes a 16-bit width slice of a
starting at bit i*15
counting rightwards. You can use -:
instead of +:
, in which case you count leftwards.
Be careful: it is very easy to type :+
instead of +:
and :+
is valid syntax and so might not be spotted by your compiler (but could still be a bug). In fact I did exactly that when typing this EDA Playground example, though my typo was caught by the compiler in this case.