// Problem 1

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

   reg [3:0] sum;
   reg       cout;

   wire [3:0] a, b;
   wire       cin;
   reg [4:0]  fullsum;

   always @( a or b or cin ) {cout,sum} = a + b + cin;

endmodule // add4

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

   wire [7:0] sum;
   wire       cout;

   wire [7:0] a, b;
   wire       cin;

   wire       cbetween;

   // Named ports are used for readability.
   add4 a0(.sum(sum[3:0]),.cout(cbetween),.a(a[3:0]),.b(b[3:0]),.cin(cin));
   add4 a1(.sum(sum[7:4]),.cout(cout),    .a(a[7:4]),.b(b[7:4]),.cin(cbetween));
   
endmodule // add8

module testadder();

   reg [7:0] a, b;
   wire [7:0] sum;
   reg       cin;
   wire      cout;

   add8 adder(sum,cout,a,b,cin);

   initial begin:I
      integer i;

      for(i=0; i<'h20000; i=i+1) begin
         {cin,a,b} = i;
         #1;
         if( {cout,sum} != a + b + cin ) begin
            $display("Error: %d + %d + %d =?= %d %d\n",
                    a,b,cin,cout,sum);
            $stop;
         end
         
      end

   end

endmodule // testadder



// Problem 3

module acc(sum,amt,reset,clk);
   output sum;
   input  amt, reset, clk;

   reg [31:0] sum;
   wire [31:0] amt;
   wire        reset, clk;
   reg [31:0]  nextsum;

   always @( clk or posedge reset)
     if( reset ) begin 
        nextsum = 0; sum = 0;
     end else if( clk === 1 )
       nextsum = amt + sum;
     else sum = nextsum;

endmodule // acc

module testacc();

   reg clk, reset;
   wire [31:0] sum;
   reg [31:0]  amt;

   acc acc1(sum,amt,reset,clk);

   reg [31:0]  shadowout, shadownext;

   initial begin:I
      integer i,r;
      clk = 0;
      shadowout = sum;
      shadownext = acc1.nextsum;

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

         #( 2 + ( $random & 31 ) );

         if( reset ) begin
            if( $random & 1 ) reset = 0;
         end else begin
            if( ! ( $random & 15 ) ) reset = 1;
         end

         amt = $random >> 5;

      end // for (i=0; i<1000; i=i+1)

      $stop;
      
   end

   always #10 clk = ~clk;

   always @( posedge reset ) begin shadowout = 0; shadownext = 0; end

   always @( posedge clk ) if( !reset ) shadownext = shadownext + amt;

   always @( negedge clk ) shadowout = shadownext;

   initial begin
      #1;
      forever @( shadowout or sum ) #1
        if( shadowout !== sum ) begin $display("Error"); $stop; end
   end

endmodule // testacc


// Problem 4a

// This is the code given in the problem.

module delays();

   integer a;

   initial begin

      a = 1;
      #1;
      a = 2;
      #1;
      a = 3;
      #1;
      a <= 4;
      #1;
      a <= 5;
      #1;
      #3 a = a+1;
      #1;
      a = #3 a+1;
      #1;
      a <= #3 a+1;
      #1;
      a = a+1;
   end
   
endmodule // delays


// Problem 4b

// Original code:

module prob4b();

   initial begin:I

      integer i, c;
      integer a[0:1000];
      
      i = 0;

      while( i < 1000 ) begin:LOOP
            
         if( a[i] == c ) disable LOOP;

         i = i + 1;

      end
      
   end
   
endmodule 

   
// Solution

module prob4bsol();

   initial begin:I

      integer i, c;
      integer a[0:1000];
      
      i = 0;

      begin:LOOP
         while( i < 1000 ) begin
            
            if( a[i] == c ) disable LOOP;

            i = i + 1;
            
         end
      end
      
   end
   
endmodule