////////////////////////////////////////////////////////////////////////////////
///
/// Solution to LSU EE 3755 Fall 2001 Midterm
///

// Exam: http://www.ece.lsu.edu/ee3755/2001f/mt.pdf
// Complete Exam Solution: http://www.ece.lsu.edu/ee3755/2001f/mt_sol.pdf

// Solutions to problems requiring Verilog code.


/// Problem 1

module cla_32(sum,a,b);
   input [31:0] a, b;
   output [32:0] sum;

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

   // Code for other carry signals omitted.
   //
   //   Start answer here  

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


   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]);
// Code for other cla_slices omitted.
   cla_slice s5(sum[5],g[5],p[5],a[5],b[5],carry[5]);
// Code for other cla_slices omitted.

endmodule


/// Problem 2

module add(sum,overflow,a,b,s);
   input [31:0] a, b;
   input        s;
   output [31:0] sum;
   output        overflow;

   reg [31:0]    sum;
   reg           overflow;

   always @( a or b or s ) begin

      sum = a + b;

      if( s ) 
        overflow = a[31] == b[31] && a[31] != sum[31];
      else
        overflow = a[31] && b[31] || ( a[31] || b[31] ) && ! sum[31];

   end
   
endmodule


/// Problem 3

module longest_run(lrun,bit,reset,clk);
   output [31:0] lrun;
   input         bit, reset, clk;

   reg [31:0]    this_run, lrun;

   always @( posedge clk ) begin

      if( reset ) begin lrun = 0; this_run = 0; end

      if( bit == 1 ) begin

         this_run = this_run + 1;

      end else begin

         this_run = 0;
         
      end

      if( this_run > lrun ) lrun = this_run;

   end

endmodule

 // Demo for problem 2.

module tlr();

   wire [31:0] lrun;
   reg         bit, clk, reset;

   longest_run lr(lrun,bit,reset,clk);

   always begin clk = 0; #5 clk = 1; #5; end

   integer i;
   reg [31:0] v, r;

   initial begin

      #0;

      v = 32'b0101_1101_0110;
      r = 32'b0010_0000_0001;

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

         bit = v[i];
         reset = r[i];
         @( negedge clk );

      end

      $stop;

   end

endmodule


/// Problem 4

// Code used in exam.
// Solution coming soon.

module syn(x,r,a,b,m,neg);
   input [31:0] a, b;
   input        m, neg;
   output [31:0] x, r;

   reg [31:0]    x, r, bn;

   always @( a or b or m or neg ) begin

      if( neg ) bn = -b; else bn = b;

      x = a + bn;

      if( m ) r = x + b;

   end

endmodule