////////////////////////////////////////////////////////////////////////////////
//
/// LSU EE 4755 Fall 2017 Homework 1
//

 /// Assignment  http://www.ece.lsu.edu/koppel/v/2017/hw01.pdf

 /// Instructions:
  //
  // (1) Find the undergraduate workstation laboratory, room 126 EE
  //     Building.
  //
  // (2) Locate your account.  If you did not get an account please
  //     E-mail: koppel@ece.lsu.edu
  //
  // (3) Log in to a Linux workstation.
  //
  // (4) If you haven't already, follow the account setup instructions here:
  //     http://www.ece.lsu.edu/koppel/v/proc.html
  //
  // (5) Copy this assignment, local path name
  //     /home/faculty/koppel/pub/ee4755/hw/2017/hw01
  //     to a directory ~/hw01 in your class account. (~ is your home
  //     directory.) Use this file for your solution.
  ///      BE SURE THAT YOUR FILE IS CORRECTLY NAMED AND IN THE RIGHT PLACE.
  //
  // (6) Find the problems in this file and solve them.
  //
  //     Your entire solution should be in this file.
  //
  //     Do not change module names.
  //
  // (7) Your solution will automatically be copied from your account by
  //     the TA-bot.


 /// Additional Resources
  //
  // Verilog Documentation
  //    The Verilog Standard
  //      http://standards.ieee.org/getieee/1800/download/1800-2012.pdf
  //    Introductory Treatment (Warning: Does not include SystemVerilog)
  //      Brown & Vranesic, Fundamentals of Digital Logic with Verilog, 3rd Ed.
  //
  // Account Setup and Emacs (Text Editor) Instructions
  //      http://www.ece.lsu.edu/koppel/v/proc.html
  //      To learn Emacs look for Emacs tutorial.
  //
  // Unix Help (Very outdated.  Alternatives welcome.)
  //      http://www.ece.lsu.edu/koppel/v/4ltrwrd/


`default_nettype none

//////////////////////////////////////////////////////////////////////////////
///  Problem 1
//
 /// Modify mux4 so that it implements a 4-input mux as described in handout.
//
//     [ ] Make sure that the testbench does not report errors.
//     [ ] Code must instantiate three mux2 modules as shown in hw01.pdf.
//     [ ] Make sure that parameters set correctly in instantiation.

module mux4
  #( int w = 6 )
   ( output uwire [w-1:0] x,
     input uwire [1:0] s,
     input uwire [w-1:0] a[3:0] );

   // Solution to Problem 1 goes here.

endmodule

module mux2
  #( int w = 16 )
   ( output uwire [w-1:0] x,
     input uwire s,
     input uwire [w-1:0] a, b );

   assign  x = s == 0 ? a : b;

endmodule


//////////////////////////////////////////////////////////////////////////////
///  Problem 2
//
 /// Modify mux8 so that it implements an 8-input mux as described in handout.
//
//     [ ] Make sure that the testbench does not report errors.
//     [ ] Code must instantiate two mux4 and one mux2 modules.
//     [ ] Make sure that parameters set correctly in instantiation.


module mux8
  #( int w = 5 )
   ( output uwire [w-1:0] x,
     input uwire [2:0] s,
     input uwire [w-1:0] a[7:0] );

   // Solution to Problem 2 goes here.
   // See testbench for examples of splitting an array, such as input a above.


endmodule


//////////////////////////////////////////////////////////////////////////////
/// Testbench Code
//
//  The code below instantiates some of the modules above,
//  provides test inputs, and verifies the outputs.
//
//  The testbench may be modified to facilitate your solution. Of
//  course, the removal of tests which your module fails is not a
//  method of fixing a broken module. (One might modify the testbench
//  so that the first tests it performs are those which make it easier
//  to determine what the problem is, for example, test inputs that
//  are all 0's or all 1's.)



// cadence translate_off


module testbench();

   localparam int wid = 10;
   localparam int n_in_max = 8;
   localparam int n_mut = 3;

   uwire [wid-1:0] x[n_mut];
   logic [2:0]  s;
   logic [wid-1:0] a[n_in_max-1:0];

   mux2 #(wid) mm2(x[0], s[0], a[0], a[1]);
   mux4 #(wid) mm4(x[1], s[1:0], a[3:0]);
   mux8 #(wid) mm8(x[2], s[2:0], a[7:0]);

   initial begin

      automatic int n_test = 0;
      automatic int n_err = 0;

      for ( int i=0; i < n_in_max; i++ ) begin
         n_test++;
         s = i;
         for ( int j=0; j<n_in_max; j++ ) a[j] = $random;
         #1;
         for ( int m=0; m<n_mut; m++ ) begin

            automatic int n_in = 2 << m;
            automatic int sm = i & ( n_in - 1 );

            if ( x[m] !== a[sm] ) begin
               n_err++;
               $write("Error in %0d-input mux for s=%0d, 0x%0x != 0x%0x (correct)\n",
                      n_in, sm, x[m], a[sm]);
            end
         end
      end
      $write("Done with %0d tests, %0d errors found.\n",n_test,n_err);
   end

endmodule

// cadence translate_on