////////////////////////////////////////////////////////////////////////////////
///
/// Solution to LSU EE 3755 Spring 2002 Homework 1
///

// Assignment:"http://www.ee.lsu.edu/ee3755/2002/hw01.pdf

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

module decode_2_to_4(x0,x1,x2,x3,a);
   input [1:0] a;
   output      x0, x1, x2, x3;

   not n0(a0n,a[0]);
   not n1(a1n,a[1]);

   and a0(x0,a1n,a0n);
   and a1(x1,a1n,a[0]);
   and a2(x2,a[1],a0n);
   and a3(x3,a[1],a[0]);
   
endmodule


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

module atoi_implicit(i,s);
   input [15:0] s;
   output [7:0] i;

   assign  i[3:0] = s[3:0] + ( s[6] ? 4'd9 : 4'd0 );
   assign  i[7:4] = s[11:8] + ( s[14] ? 4'd9 : 4'd0 );
   
endmodule

module not_a_good_solution_atoi_implicit(i,s);
   input [15:0] s;
   output [7:0] i;

   parameter  ascii_0 = 48;
   parameter  ascii_a = 97;

   // The code below should work (but not tested) however it requires
   // more hardware than the first solution.  In particular, it does a
   // magnitude comparison when it's sufficient to test a single bit
   // of s.  It does 8-bit subtractions when only the four least
   // significant bits are used.
   
   assign i[3:0] = s[7:0] >= ascii_a ? s[7:0] - ascii_a + 10 : s[7:0] - ascii_0;
   assign i[7:4] = s[15:8] >= ascii_a 
                   ? s[15:8] - ascii_a + 10
                   : s[15:8] - ascii_0;
   
endmodule


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


module atoi_explicit(i,s);
   input [15:0] s;
   output [7:0] i;

   add4 s0(i[3:0],s[3:0],{s[6],2'b0,s[6]});
   add4 s1(i[7:4],s[11:8],{s[14],2'b0,s[14]});
   
endmodule

//
// Modules for use in Problem 3
//
// DO NOT modify these modules.

module sub4(d,a,b);
   input [3:0] a, b;
   output [3:0] d;

   assign       d = a - b;
   
endmodule

module add4(d,a,b);
   input [3:0] a, b;
   output [3:0] d;

   assign       d = a + b;
   
endmodule

module sub7(d,a,b);
   input [6:0] a, b;
   output [6:0] d;

   assign       d = a - b;
   
endmodule

module add7(d,a,b);
   input [6:0] a, b;
   output [6:0] d;

   assign       d = a + b;
   
endmodule

////////////////////////////////////////////////////////////////////////////////
/// Testbenches
///

module test_decoder();

   parameter stop_on_error = 1;
   
   reg [1:0] a;
   wire      x0, x1, x2, x3;
   reg [3:0] x;

   decode_2_to_4 your_decoder(x0,x1,x2,x3,a);

   integer   i, err;

   initial begin

      err = 0;

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

         a = i[1:0];
         #1;
         x = 1 << a;
         if( {x3,x2,x1,x0} !== x )
           begin
              $display("FAIL: Demux wrong output for input %d",a);
              err = err + 1;
              if( stop_on_error ) $stop;
           end
      end

      if( !err ) $write("PASS: ");
      $write("Tests completed, ");
      if( err )
        $display("encountered %d errors.",err);
      else
        $display("no errors found.\n");

      $display("Thank you for using the decode testbench.");

   end
   
endmodule

module test_atoi();

   wire [7:0] ie, ii;
   reg [15:0] s;

   parameter  stop_on_error = 1;
   parameter  ascii_0 = 48;
   parameter  ascii_a = 97;
   
   atoi_explicit our_atoi_explicit(ie,s);
   atoi_implicit our_atoi_implict(ii,s);

   integer    i, err_i, err_e;

   integer    d0, d1;

   initial begin

      err_i = 0;  err_e = 0;

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

           d0 = i & 15;
           d1 = i >> 4;
           s[7:0]  = d0 < 10 ? d0 + ascii_0 : d0 + ascii_a - 10;
           s[15:8] = d1 < 10 ? d1 + ascii_0 : d1 + ascii_a - 10;
           #1;
           if( ie !== i ) begin
              $display("FAIL: Explicit, wrong output, 0x%h (correct) != 0x%h",
                       i,ie);
              err_e = err_e + 1;
              if( stop_on_error ) $stop;
           end
           if( ii !== i ) begin
              $display("FAIL: Implicit, wrong output, 0x%h (correct) != 0x%h",
                       i,ii);
              err_i = err_i + 1;
              if( stop_on_error ) $stop;
           end

        end
      if( !err_i ) $write("PASS: ");
      $write("Implicit tests completed, ");
      if( err_i )
        $display("encountered %d errors.",err_i);
      else
        $display("no errors found.\n");

      if( !err_e ) $write("PASS: ");
      $write("Explicit tests completed, ");
      if( err_e )
        $display("encountered %d errors.",err_e);
      else
        $display("no errors found.\n");


   end

endmodule