How to create a 64 bit Carry Look ahead adder

adderverilog

I am trying to implement the verilog code using generate statement.There is issue with taking four bits for calculating P and G values.Added the code below for reference.
Cin is taken as Zero.

`timescale 1ns/10ps

module cla_64bit(sum,c_out,a,b,c_in);

input [64:0]a,b;
input c_in;
output [64:0]sum;
output c_out;
wire [65:0]sum_out;
wire [64:0]c_in;
wire [64:0]c_out;

assign c_in[0]=1'b0;


genvar i;
generate
  for (i = 0;i<64;i=i+16)
        begin : FA
            add_16bit FINALBITBLOCK(
              .sum    (sum_out[i]),
              .c_out  (c_in[i-1]),
              .a  (a[i]),
              .b  (b[i]),
            .c_in   (c_in[i])
            );
          //assign g[i]=a[i] & b[i];
          //assign p[i]=a[i] ^ b[i];
          //assign c_in[i+1]= g[i]|(p[i] & c_in[i]);
          end 

assign c_out=c_in[63];
assign sum=sum_out[63:0];

endgenerate 
endmodule

module add_16bit(sum,c_out,a,b,c_in);
input [15:0]a,b;
input c_in;
output [15:0]sum;
output c_out;
wire [15:0]p,g;
wire [15:0]sum_out;
wire [16:0]c_in;
wire [16:0]c_out;

assign c_in[0]=1'b0;

genvar i;
generate
  for (i = 0;i<16;i=i+4)
        begin : FA
            add_4bit FOURBITBLOCK(
              .sum    (sum_out[i]),
              .c_out  (c_in[i+1]),
              .a  (a[i]),
              .b  (b[i]),
            .c_in   (c_in[i])
            );
          assign g[i]=a[i] & b[i];
          assign p[i]=a[i] ^ b[i];
          assign c_in[i+1]= g[i]|(p[i] & c_in[i]);
          end 

assign c_out=c_in[15];
//assign sum=sum[15:0];

endgenerate
endmodule

module add_4bit(sum,c_out,a,b,c_in);
input [3:0]a,b;
input c_in;
output [3:0]sum;
output c_out;
wire  [3:0]p,g;
wire [3:0]sum_out;
wire [4:0]c_in;
wire [4:0]c_out;  
assign c_in[0]=1'b0;


genvar i;
generate
  for (i = 0;i<4;i=i+1)
        begin : FA
            add_full FA(
              .sum    (sum_out[i:0]),
              .c_out  (c_in[i+1]),
              .a  (a[i]),
              .b  (b[i]),
            .c_in   (c_in[i])
            );
          assign g[i]=a[i] & b[i];
          assign p[i]=a[i] ^ b[i];
          assign c_in[i]= g[i]|(p[i] & c_in[i]);
          end 

assign c_out=c_in[3];
assign sum=sum_out[3:0];

endgenerate
endmodule

module add_full (sum, c_out, a, b, c_in);
output sum, c_out;   
input  a, b, c_in;   
wire   w1, w2, w3;   

add_half M1 (w1, w2, a, b);   
add_half M2 (sum, w3, w1, c_in);   
or M3 (c_out, w2, w3);
endmodule

module add_half (sum, c_out, a, b);
output sum, c_out;   
input  a, b;     
xor M1 (sum, a, b);     
and M2 (c_out, a, b);
endmodule 

Best Answer

c_in is a 1-bit input, but is also defined as a 64-bit (too wide) interconnect. Lets rename the interconnect to carry and make it 5 bits wide; one bit for each of the add_16bit's c_in plus the final carry out.

You need to use range section. [i] only indexes one bit. To get 16-bits use [16*i+15 : 16*i] or use bit slicing (+:) [i +: 16]. Bit slicing is explained on StackOverflow: Indexing vectors and arrays with +: and What is +: and -:?. The big difference is bit slicing can be used in procedural blocks and generate loops. The expanded form can only be used when i is a genvar or parameter.

wire [4:0] carry;
genvar i;
for (i = 0;i<64;i=i+16) begin : FA
  add_16bit FINALBITBLOCK(
    .sum    (sum[i +: 16]),
    .c_out  (carry[(i>>4)+1]),
    .a      (a[i +: 16]),
    .b      (b[i +: 16]),
    .c_in   (carry[i>>4])
  );
end
assign carry[0] = c_in;
assign c_out = carry[4];