// Solution for Homework 5D
// J. Dean Brock <brock@unca.edu>

module SerialALU
      (input   logic        CLOCK,
       input   logic  [6:0] INSTRUCTION,
       input   logic [15:0] INPUT,
       output  logic  [2:0] STATUS,
       output  logic [15:0] OUTPUT
      ) ;

   logic [2:0] OPCODE ;
   logic [1:0] SOURCE ;
   logic [1:0] TARGET ;

   assign {OPCODE, SOURCE, TARGET} = INSTRUCTION ;

   logic [15:0] register [1:3] ;
   initial
     begin
       register[1] = 16'd320 ;
       register[2] = 16'hbeef ;
       register[3] = 16'hfade ;
     end

   logic [15:0] source_value ;
   logic [15:0] target_value ;
   logic [16:0] result_value ;        // One more bit...

   assign source_value = SOURCE == 2'b00 ? INPUT : register[SOURCE] ;
   assign target_value = TARGET == 2'b00 ? INPUT : register[TARGET] ;

   
   always_comb
      case (OPCODE)
        3'b000: result_value = target_value + source_value ;
        3'b001: result_value = target_value - source_value ;
        3'b010: result_value = target_value + source_value ;
        3'b011: result_value = target_value - source_value ;
        3'b100: result_value = target_value & source_value ;
        3'b101: result_value = target_value | source_value ;
        3'b110: result_value = target_value ^ source_value ;
        3'b111: result_value = source_value ;
      endcase

      assign OUTPUT = result_value[15:0] ;

endmodule
