////////////////////////////////////////////////////////////////////////////////
///
/// Template for LSU EE 3755 Spring 2002 Homework 3
///

 /// Due: Friday, 8 March 2002

 /// Instructions:
  //
  // Copy this to a file named hw03.v to directory ~/hw in your
  // class account. (~ is your home directory.)  Use this
  // file for your solution.  Your entire solution should be in
  // this file.
  //
  // Do not rename the modules in this file and be sure to use the
  // directory and filename given above.

  // Local copy of this file: 
  //     /home/classes/ee3755/com/v/hw03.v
  //
  // Instruction on Simulator, Emacs, etc:
  //    "http://www.ece.lsu.edu/ee3755/proc.html
  //
  // Documentation for Simulator, Unix, etc.
  //    "http://www.ece.lsu.edu/ee3755/ref.html


////////////////////////////////////////////////////////////////////////////////

/// Problems 1, 2, and 3

// Complete the three modules below to form a 3-level, 8-bit
// carry-look-ahead adder (with a 9-bit sum).  (Don't cringe, it's not
// that bad!)
//
// Each adder module should instantiate two copies of the next smaller
// adder module.  That is, adder8 instantiates two adder4's, adder4
// instantiates two adder2's, which instantiates two binary full
// adders (bfa's).  (See, it's not so bad ... right?)  The modules
// should use carry-look-ahead logic to generate carry in signals and
// propagate (P) and generate (G) outputs, see the module shells for
// details.  Module adder4 should use synthesizable procedural code
// (the instantiations of course are not part of the procedural code),
// the others can use structural or synthesizable procedural code.
//
// Use testbench test_adder8 to test adder8.  There is no testbench to
// specifically test adder4 and adder2, if they don't work adder8
// should fail the testbench.  Because it might not be obvious where
// the problem is, make good use of the structure and signals windows
// to debug your code.  This is very important. To debug follow these
// steps:
//
//  Run the testbench. (Do not change stop_on_error, it should be 1.)
//  If it says "PASS" there's nothing to debug, otherwise:
//  Press the "V" button in the "ModelSim" window. Three windows should pop up.
//  On the structure window click "adder8"
//  The top lines of the signals window should show a, b, sum, and sum
//   should be something other than a+b.
//  Expand adder8 in the structure window by clicking on the little "+".
//   It should show the modules instantiated within adder8, two adder4's.
//  Click on one of the adder4's.  The signals window should change to
//   show signals in the adder4 instantiation you clicked.
//  Determine whether a+b+cin, using the values in the signals window,
//   is equal to sum + <carry out>, where sum is the value in the signals
//   window and <carry out> is something you figure out from the P and G
//   outputs.
//  If it's not equal, the problem is in that adder4, apply the steps 
//   above to it.
//  If it is equal, select the other adder4.
//  Also be sure to check the carry in signals.
//
//  The wave window is not necessary here because the circuit is combinational.
//
// Note: The debugging procedure above makes alot more sense if you
// understand how the adder is supposed to work.
//
// Some may find it easier to work on adder2 first, then adder4, then
// adder8, that is a bottom-up approach.  Others prefer a top-down
// approach: adder8, then adder4, then adder2.
//
// Complete the modules as specified by the Sure-Solve [tm] checklist
// items in each module.
//

 /// Grading Criteria
//
//   Passes the testbench.
//   If it fails, partial credit will be given based on the type of
//   problem.  A large amount of credit will be deducted for
//   compilation errors.
//
//   Follows the guidelines.
//   Be sure to instantiate two modules per module.
//   Use procedural code where indicated.
//
//   Coded cleanly.
//   Points will be deducted for code that is correct but much more
//   complex, unreadable, or inefficient than it has to be.
//   For example, points would be deducted for the second assign below.
`ifdef XXX
assign x = a & b;  // Use assign on this line instead of one on line below.
assign x = a == 1'b1 ? ( b == 1'b1 ? 1'b1 : 1'b0 ) : ( b == 1'b1 ? 1'b0 : 1'b0 );
`endif


////////////////////////////////////////////////////////////////////////////////
/// Problem 1
///

module adder8(sum,a,b);
   input [7:0] a, b;
   output [8:0] sum;

   // Implement an 8-bit adder.
   //
   //  [ ]  Instantiate two adder4's (the module appears further below).
   //  [ ]  Name the instances a0 and a1.
   //  [ ]  Use carry-look-ahead logic to compute a carry in.
   //  [ ]  Use carry-look-ahead logic to compute the MSB of the sum.
   //
   //  Can be solved with four additional lines of Verilog (including
   //  declarations), but more are okay.


   
endmodule


////////////////////////////////////////////////////////////////////////////////
/// Problem 2
///

module adder4(sum,P,G,a,b,cin);
   input [3:0] a, b;
   input       cin;
   output [3:0] sum;
   output       P, G;

   // Implement a 4-bit adder:
   //
   //  [ ]  Instantiate two adder2's (the module appears further below).
   //  [ ]  Name the instances a0 and a1.
   //  [ ]  Use carry-look-ahead logic to compute a carry in.
   //  [ ]  Use carry-look-ahead logic to compute P and G.
   //  [ ]  Use two always blocks.
   //  [ ]  DO NOT use assign statements in this module.
   //
   // Can be solved with 12 added lines of Verilog, that includes
   // declarations, begin's, end's, etc.


   
endmodule


////////////////////////////////////////////////////////////////////////////////
/// Problem 3
///

module adder2(sum,P,G,a,b,cin);
   input [1:0] a, b;
   input       cin;
   output [1:0] sum;
   output       P, G;

   // Implement a 2-bit ripple adder with propagate and generate outputs.
   //
   //  [ ]  Instantiate two bfa's (the module appears further below).
   //  [ ]  Name the instances a0 and a1.
   //  [ ]  Make a two-bit ripple adder from the bfa's.
   //  [ ]  Use carry-look-ahead logic to compute P and G.
   //
   // Can be solved with 5 to 9 added lines of Verilog, that includes
   // declarations. A different number of lines is okay.


   
endmodule


////////////////////////////////////////////////////////////////////////////////
/// Module used in the solution.
///

// Do not modify the module below.

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

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

endmodule


////////////////////////////////////////////////////////////////////////////////
/// Testbench
///

module test_add8();

   parameter stop_on_error = 1;
   parameter max_errs = 10;

   wire [8:0] sum;
   reg [7:0]  a, b;
   
   adder8 a8(sum,a,b);

   integer    i, err;
   reg [8:0]  shadow_sum;
   
   initial begin

      err = 0;

      for(i=0; i<='hffff; i=i+1) begin
         {a,b} = i;
         #1;

         shadow_sum = a + b;

         if( shadow_sum !== sum ) begin

            err = err + 1;

            if( err < max_errs ) 
              $display("FAIL: Wrong sum: %d + %d = %d (correct) != %d",
                       a, b, shadow_sum, sum);

            if( err == max_errs )
              $display("Maximum error message count reached.");

            if( stop_on_error ) $stop;
            
         end
                          
      end

      $display("Tests completed.");
      if( err == 0 )
        $display("PASS: No errors detected.");
      else
        $display("FAIL: %d errors.\n",err);

   end
   

endmodule