```/// LSU EE 3755 Fall 2012
//
//  Code for Homework 2

`timescale 1ns/10ps

//
//
input [11:0]  a, b;
output [12:0] sum;

wire [2:0]  P, G, carry;
wire [2:0]  CO; // Unused.

// Each 4-bit ripple adder computes a piece of the sum.
//
ripple_4_block ad0(sum[3:0],  CO[0], a[3:0],  b[3:0],  carry[0]);
ripple_4_block ad1(sum[7:4],  CO[1], a[7:4],  b[7:4],  carry[1]);
ripple_4_block ad2(sum[11:8], CO[2], a[11:8], b[11:8], carry[2]);

// Use carry lookahead logic to compute carry in signals for ripple
//

gen_prop_4 gp0(G[0], P[0], a[3:0],  b[3:0]);
gen_prop_4 gp1(G[1], P[1], a[7:4],  b[7:4]);
gen_prop_4 gp2(G[2], P[2], a[11:8], b[11:8]);

assign      carry[0] = 1'b0;

assign      carry[1] = G[0];

assign      carry[2] = G[0] & P[1]
| G[1];

assign      sum[12] = G[0] & P[1] & P[2]
| G[1] & P[2]
| G[2];

endmodule

//
//
input [11:0]  a, b;
output [12:0] sum;

wire [2:0]  P, G, carry;

// Each 4-bit carry lookahead adder computes a piece of the sum and
// also computes generate and propagate signals.
//
cla_4_block ad0(sum[3:0],  G[0], P[0], a[3:0],  b[3:0],  carry[0]);
cla_4_block ad1(sum[7:4],  G[1], P[1], a[7:4],  b[7:4],  carry[1]);
cla_4_block ad2(sum[11:8], G[2], P[2], a[11:8], b[11:8], carry[2]);

// Use generate and propagate to compute carry in signals.
//
assign      carry[0] = 1'b0;

assign      carry[1] = G[0];

assign      carry[2] = G[0] & P[1]
| G[1];

assign      sum[12] = G[0] & P[1] & P[2]
| G[1] & P[2]
| G[2];

endmodule

/// Four Bit CLA
//
module cla_4_block(sum,gout,pout,a,b,cin);
input [3:0]  a, b;
input        cin;
output [3:0] sum;
output       gout, pout;

wire [3:0]   carry, p, g;

assign carry[0] = cin;

assign carry[1] = cin  & p[0]
| g[0];

assign carry[2] = cin  & p[0] & p[1]
| g[0] & p[1]
| g[1];

assign carry[3] = cin  & p[0] & p[1] & p[2]
| g[0] & p[1] & p[2]
| g[1] & p[2]
| g[2];

assign gout = g[0] & p[1] & p[2] & p[3]
| g[1] & p[2] & p[3]
| g[2] & p[3]
| g[3];

assign pout = p[0] & p[1] & p[2] & p[3];

cla_slice s0(sum[0],g[0],p[0],a[0],b[0],carry[0]);
cla_slice s1(sum[1],g[1],p[1],a[1],b[1],carry[1]);
cla_slice s2(sum[2],g[2],p[2],a[2],b[2],carry[2]);
cla_slice s3(sum[3],g[3],p[3],a[3],b[3],carry[3]);

endmodule

/// Compute Generate and Propagate Signals
//
//  This module computes generate and propagate signals for a
//  group of four bits.
//
module gen_prop_4(G,P,a,b);
output G;
output P;
input [3:0] a, b;

wire [3:0]  g = a & b;
wire [3:0]  p = a | b;

assign G = g[0] & p[1] & p[2] & p[3]
| g[1] & p[2] & p[3]
| g[2] & p[3]
| g[3];

// assign P = p == 4'hf;   // Method E
assign P = p[0] & p[1] & p[2] & p[3];  // Method G

endmodule

module ripple_4_block(sum,co,a,b,cin);
output [3:0] sum;
output       co;
input [3:0] a, b;
input       cin;

wire [2:0]  carry;

bfa bfa0(sum[0],carry[0],a[0],b[0],cin);
bfa bfa1(sum[1],carry[1],a[1],b[1],carry[0]);
bfa bfa2(sum[2],carry[2],a[2],b[2],carry[1]);
bfa bfa3(sum[3],co,a[3],b[3],carry[2]);

endmodule

module bfa(sum,cout,a,b,cin);
output sum,cout;
input a,b,cin;

assign sum = a ^ b ^ cin;
assign cout = a & b | b & cin | a & cin;

endmodule

module cla_slice(sum,g,p,a,b,cin);
input a, b, cin;
output sum, g, p;

assign g = a & b;
assign p = a | b;
assign sum = a ^ b ^ cin;
endmodule

wire [12:0] sum_r, sum_2, sum_f;
reg [11:0]  a, b;
integer    i;

assign     sum_r = sum_f;

initial begin

for(i=0; i<100; i=i+1) begin

a = \$random;
b = \$random;
#1;
if( sum_2 != shadow_sum || sum_2 != sum_r || sum_2 != sum_f ) begin
\$display("Wrong sum: %h + %h = %h != %h or %h or %h\n",
a, b, shadow_sum, sum_2, sum_f, sum_r);
\$stop;
end
end

\$display("Tests completed.");

end

endmodule