```////////////////////////////////////////////////////////////////////////////////
//
/// LSU EE 4755 Fall 2014 Homework 1 -- SOLUTION
//

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

`default_nettype none

//////////////////////////////////////////////////////////////////////////////
///  Problem 1
//
/// Logical Right Shift Module 1
//
//   The module below performs a logical right shift of a 16-bit
//   quantity.
//
//   [x]  Don't substantially change the way the code works.
//   [x]  Don't try to make the code synthesizable.
//   [x]  Don't use shift (<<) or concatenation operators ({}) ..
//        .. assign shifted bit-by-bit as the code already does.

module shift_right1
( output logic [15:0] shifted,
input wire [15:0] unshifted,
input wire [3:0] amt );

/// Problem 1 solution goes in this module.

localparam int width = 16;

always @* begin

automatic int limit = width - amt;

for ( int i=0; i<limit; i++ ) shifted[i] = unshifted[i+amt];

/// SOLUTION
//  Just zero the "vacated" bits.
//
for ( int i=limit; i<width; i++ ) shifted[i] = 0;

end

endmodule

//////////////////////////////////////////////////////////////////////////////
///  Problem 2
//
/// Logical Right Shift Module 2
//
//   The module below performs a logical right shift of a 16-bit
//   quantity.
//

// Perform Two Possible Shifts:  by 0 bits or by fsamt bits.
//
module shift_right_fixed
( output wire [15:0] shifted,
input wire [15:0] unshifted,
input wire shift );

// Problem 2: DON'T modify this module.

// (Fixed) Shift Amount
//
parameter int fsamt = 3;

// If shift is true shift by fsamt, otherwise don't shift.
//
assign    shifted =  shift  ?  unshifted >> fsamt  :  unshifted;

endmodule

module shift_right2
( output wire [15:0] shifted,
input wire [15:0] unshifted,
input wire [3:0] amt );

/// Problem 2 solution goes in this module.

/// SOLUTION
//
//  Declare wires to interconnect the modules.
//
uwire [15:0]  s8, s4, s2;

shift_right_fixed #(8) sm8
( .shifted(s8), .unshifted(unshifted), .shift(amt[3]) );

/// SOLUTION
//
//  Instantiate three more modules and connect them.
//  Note: You don't have to use named ports.

shift_right_fixed #(4) sm4 (s4, s8, amt[2]);
shift_right_fixed #(2) sm2 (s2, s4, amt[1]);
shift_right_fixed #(1) sm1 (shifted, s2, amt[0]);

endmodule

//////////////////////////////////////////////////////////////////////////////
/// Testbench Code
//
//  The code below instantiates shift_right1 and shift_right2,
//  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
//  considered a correct solution. (The idea is to put in tests which
//  make it easier to determine what the problem is, for example, test
//  inputs that are all 0's or all 1's.)

module testbench();

uwire logic [15:0] sout1, sout2;
logic [15:0] sin;
logic [3:0] amt;

shift_right1 my_sr1(sout1, sin, amt);
shift_right2 my_sr2(sout2, sin, amt);

// Width of shifters' input and output.
// The parameter is used only by this testbench.
//
localparam int width = 16;
//
// To keep things simple the shifter modules themselves are written
// with a hardcoded width of 16 bits. That's bad style since
// changing the width would be tedious and error prone. The
// hardcoded widths are used in this first homework assignment only
// to keep things simple. (The shifter modules could have used a
// parameter to specify the width or a user-defined type.)

// Provide names for the modules for use in error messages.
//
localparam string name[2] = '{"Prob 1", "Prob 2"};

initial begin

// Count of errors for each module.
//
automatic int err_count[2] = '{0,0};
//
// Note: The automatic qualifier is needed so that the initialization
// could appear on the same line as the declaration.

// Number of test inputs (stimuli).
//
automatic int test_count = 0;

// Provide one test pattern per shift amount.
//
for ( int i=0; i<width; i++ ) begin

test_count++;

sin = \$random;
amt = i;

#1;

// Check the output of each Module Under Test.
//
foreach ( name[ mut ] ) begin

automatic logic [15:0] sout = mut == 0 ? sout1 : sout2;

if ( shadow_sout !== sout ) begin
err_count[mut]++;
if ( err_count[mut] < 5 )
\$display
("MUT %s wrong result for %h >> %d:  %h != %h (correct)\n",
end

end

end

\$display("Ran %d tests, %d, %d errors found.\n",
test_count, err_count[0], err_count[1]);

end

endmodule