xtt
xtt

Reputation: 917

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?

Upvotes: 2

Views: 2506

Answers (2)

Muhammad Adnan
Muhammad Adnan

Reputation: 1

Actually, what you need for your code to be synthesizable is using genvar as the type of i. Kind of like this (using macros, put it above your module):

`define PACK_ARRAY_2D2(PK_WIDTH,PK_LEN,PK_DIMS,PK_SRC,PK_DEST,PK_OFFS) ({\
 genvar pk_idx; genvar pk_dims; \
 generate \
 for (pk_idx=0; pk_idx<(PK_LEN); pk_idx=pk_idx+1) \
 begin \
    for (pk_dims=0; pk_dims<(PK_DIMS); pk_dims=pk_dims+1) \
        begin  \
    assign PK_DEST[(((PK_WIDTH)*(pk_idx+pk_dims+1))-1+((PK_WIDTH)*PK_OFFS*pk_idx)):(((PK_WIDTH)*(pk_idx+pk_dims))+((PK_WIDTH)*PK_OFFS*pk_idx))] = PK_SRC[pk_idx][pk_dims][((PK_WIDTH)-1):0];\
    end\
 end\
 endgenerate\
 }) 

`define UNPACK_ARRAY_2D2(PK_WIDTH,PK_LEN,PK_DIMS,PK_DEST,PK_SRC,PK_OFFS) ({\
 genvar unpk_idx; genvar unpk_dims; \
 generate \
    for (unpk_idx=0; unpk_idx<(PK_LEN); unpk_idx=unpk_idx+1)  \
 begin \
    for (unpk_dims=0; unpk_dims<(PK_DIMS); unpk_dims=unpk_dims+1)\
  begin  \
  assign PK_DEST[unpk_idx][unpk_dims][((PK_WIDTH)-1):0] = PK_SRC[(((PK_WIDTH)*(unpk_idx+unpk_dims+1))-1+((PK_WIDTH)*PK_OFFS*unpk_idx)):(((PK_WIDTH)*(unpk_idx+unpk_dims))+((PK_WIDTH)*PK_OFFS*unpk_idx))];\
  end end endgenerate\
  })

and here is how to use it (just put in inside pack_unpack.v) as an example of function to transpose matrix :

// Macros for Matrix
`include "pack_unpack.v"

module matrix_weight_transpose(
    input signed [9*5*32-1:0] weight,               // 5 columns, 9 rows, 32 bit data length
    
    output signed [9*5*32-1:0] weight_transposed    // 9 columns, 5 rows, 32 bit data length
);
 
 wire [31:0] weight_in [8:0][4:0];
`UNPACK_ARRAY_2D2(32,9,5,weight_in,weight,4)

 wire [31:0] weight_out [4:0][8:0];
 `PACK_ARRAY_2D2(32,5,9,weight_out,weight_transposed,8)
 
 generate                                           // Computing the transpose
    genvar i;
    for (i = 0; i < 9; i = i + 1)
     begin     : columns              
     genvar j;
         for (j = 0; j < 5; j = j + 1)
         begin   : rows
            assign weight_out[j][i] = weight_in[i][j];
         end
    end
 endgenerate

endmodule

Upvotes: 0

Matthew
Matthew

Reputation: 13937

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.

Upvotes: 2

Related Questions