//  *********************************************************************************************
//  Project Version  : v1.0
//  Project          : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
//  -----
//  Copyright (c)    : 2025 Fraunhofer IIS, Department IDS
//  Created          : 12.Jun.2025  by Lund University [commit 5b1e415]
//  Last Modified    : 23.Oct.2025  by Bomin Kim       [commit 2f8f03d]
//  -----
//  HISTORY          : Date         By         Comments
//                     -----------  ---------  -------------------------------------------------
//                     15.Oct.2025  Bomin Kim  Refactored ALU logic from decoder into this file
//  *********************************************************************************************



module alu (
  input  logic[2:0]   aluOp,
  input  logic        aluNegAr,
  input  logic        aluBypass,
  input  logic[31:0]  op1,
  input  logic[31:0]  op2,
  output logic[31:0]  result,
  output logic        eqFlag
);

  // Local parameters; list of aluOp
  localparam logic[2:0] f3add    = 3'b000;
  localparam logic[2:0] f3sl     = 3'b001;
  localparam logic[2:0] f3slt    = 3'b010;
  localparam logic[2:0] f3sltU   = 3'b011;
  localparam logic[2:0] f3xor    = 3'b100;
  localparam logic[2:0] f3sr     = 3'b101;
  localparam logic[2:0] f3or     = 3'b110;
  localparam logic[2:0] f3and    = 3'b111;

  // ALU logic
  always_comb begin : ALU
    eqFlag = op1 == op2;
    if (aluBypass) result = op1;
    else case(aluOp)
      f3add:  result = aluNegAr ? op1 - op2 : op1 + op2;
      f3sl:   result = op1 << op2[4:0];
      f3slt:  result = {31'b0, $signed(op1) < $signed(op2)};
      f3sltU: result = {31'b0, $unsigned(op1) < $unsigned(op2)};
      f3xor:  result = op1 ^ op2;
      f3sr:   result = aluNegAr ? $signed(op1) >>> op2[4:0] : $signed(op1) >> op2[4:0];
      f3or:   result = op1 | op2;
      f3and:  result = op1 & op2;
    endcase
  end

endmodule
