module mul
    #(
         parameter WIDTH = 16
     )
     (
         input      [WIDTH-1:0]      a,
         input      [WIDTH-1:0]      b,
         output reg [(WIDTH<<1)-1:0] c = 0
     );

    reg [(WIDTH<<1)-1:0] tmp;

    reg  [(WIDTH<<1)-1:0] add_a[WIDTH-1:0];
    reg  [(WIDTH<<1)-1:0] add_b[WIDTH-1:0];
    wire [(WIDTH<<1)-1:0] add_y[WIDTH-1:0];

    genvar k;
generate for (k = 0; k < WIDTH; k = k +1) begin
            full_addr #(WIDTH<<1) full_addr_i(add_a[k], add_b[k], add_y[k]);
end endgenerate

    integer i;
    integer j;
generate always @(*) begin
            tmp = 0;
            c   = 0;

            /* generate parallel structure */
            for (j = 0; j < WIDTH; j = j + 1) begin
                for (i = 0; i < WIDTH; i = i + 1) begin
                    tmp[i] = b[i] & a[j];
                end
                add_a[j] = c;
                add_b[j] = (tmp << j);
                c = add_y[j];
            end
        end endgenerate

endmodule