/// LSU EE 3755 -- Fall 2013 -- Computer Organization
//
/// Ripple Adder Demonstration

// Code in this file used to demonstrate use of the Verilog
// simulation tools.

 /// Binary Full Adder
//
module bfa_structural(sum,cout,a,b,cin);
   input a,b,cin;
   output sum,cout;

   wire   term001, term010, term100,term111;
   wire   ab, bc, ac;
   wire   na, nb, nc;

   or o1(sum,term001,term010,term100,term111);
   or o2(cout,ab,bc,ac);

   and a1(term001,na,nb,cin);
   and a2(term010,na,b,nc);
   and a3(term100,a,nb,nc);
   and a4(term111,a,b,cin);

   not n1(na,a); 
   not n2(nb,b); 
   not n3(nc,cin);

   and a10(ab,a,b);
   and a11(bc,b,cin);
   and a12(ac,a,cin);

endmodule

 /// Four-Bit Ripple Adder
//
// Instantiate four bfa's to make a 4-bit adder.
//
module ripple_4(sum,cout,a,b,cin);
   input [3:0] a;
   input [3:0] b;
   input       cin;
   output [3:0] sum;
   output       cout;

   wire         c0, c1, c2;

   bfa_structural bfa0(sum[0],c0,a[0],b[0],cin);
   bfa_structural bfa1(sum[1],c1,a[1],b[1],c0);
   bfa_structural bfa2(sum[2],c2,a[2],b[2],c1);
   bfa_structural bfa3(sum[3],cout,a[3],b[3],c2);

endmodule


 /// A 16-bit Ripple Adder
//
// Instantiate four ripple_4 modules to make a 16-bit ripple adder.
//
module ripple_16(sum,cout,a,b,cin);
   input [15:0] a;
   input [15:0] b;
   input        cin;
   output [15:0] sum;
   output       cout;

   wire         c0, c1, c2;

   ripple_4 r1(sum[3:0],c0,a[3:0],b[3:0],cin);
   ripple_4 r2(sum[7:4],c1,a[7:4],b[7:4],c0);
   ripple_4 r3(sum[11:8],c2,a[11:8],b[11:8],c1);
   ripple_4 r4(sum[15:12],cout,a[15:12],b[15:12],c2);

endmodule


// The comment below is actually a directive to the synthesis program
// telling it to ignore the Verilog that follows. In this case, the
// Verilog that follows is used to test the design, and is not meant
// to be synthesized.
//
// cadence translate_off

module testadd16();

   wire [16:0] sum;
   wire [15:0] sum_16;
   reg [16:0] shadow_sum;
   reg [15:0]  a, b;
   integer    i;
   wire       cout;
   integer    num_of_tests = 10;

   assign     sum = {cout,sum_16};

   ripple_16 ripple_16(sum_16,cout,a,b,1'b0);

   initial begin
      a = 0; b = 0;
      #1;  // Delay of one unit.
      
      for (i=0; i<num_of_tests; i=i+1) begin

         a = $random;
         b = $random;

         shadow_sum = a + b;

         # 20; // Wait before checking results.

         if( sum !== shadow_sum ) begin
            $display
              ("Wrong sum for test input %d: %d + %d = %d != %d (correct)\n",
               i, a, b, sum, shadow_sum);
            $stop;
         end

      end

      $display("Completed %d tests, no problems found.",num_of_tests);

      $stop;
      
   end

endmodule

// cadence translate_on