98 lines
3.5 KiB
Plaintext
98 lines
3.5 KiB
Plaintext
//
|
|
// ALU
|
|
//
|
|
// This module is a Arithmetic Logic Unit (ALU) implementation for RISC-V. It is
|
|
// reponsible for mathematical operations inside the CPU.
|
|
//
|
|
import RV_ISA::*;
|
|
export AluCfg, AluIfc(..), mkAlu, Execute(..);
|
|
|
|
typeclass Execute#(numeric type xlen);
|
|
function Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2);
|
|
endtypeclass
|
|
|
|
instance Execute#(32);
|
|
function Maybe#(Bit#(32)) execute(RVALUOperator operator, Bit#(32) operand1, Bit#(32) operand2);
|
|
let sum = operand1 + operand2;
|
|
let difference = operand1 - operand2;
|
|
let bitwise_and = operand1 & operand2;
|
|
let bitwise_or = operand1 | operand2;
|
|
let bitwise_xor = operand1 ^ operand2;
|
|
let sltu = (operand1 < operand2 ? 1 : 0);
|
|
let slt = (begin
|
|
Int#(32) signedOperand1 = unpack(pack(operand1));
|
|
Int#(32) signedOperand2 = unpack(pack(operand2));
|
|
(signedOperand1 < signedOperand2 ? 1 : 0);
|
|
end);
|
|
|
|
let sll = operand1 << operand2[4:0];
|
|
let sra = signedShiftRight(operand1, operand2[4:0]);
|
|
let srl = operand1 >> operand2[4:0];
|
|
|
|
return case(operator)
|
|
alu_ADD: tagged Valid sum;
|
|
alu_SUB: tagged Valid difference;
|
|
alu_AND: tagged Valid bitwise_and;
|
|
alu_OR: tagged Valid bitwise_or;
|
|
alu_XOR: tagged Valid bitwise_xor;
|
|
alu_SLTU: tagged Valid sltu;
|
|
alu_SLT: tagged Valid slt;
|
|
alu_SLL: tagged Valid sll;
|
|
alu_SRA: tagged Valid sra;
|
|
alu_SRL: tagged Valid srl;
|
|
default: tagged Invalid;
|
|
endcase;
|
|
endfunction
|
|
endinstance
|
|
|
|
instance Execute#(64);
|
|
function Maybe#(Bit#(64)) execute(RVALUOperator operator, Bit#(64) operand1, Bit#(64) operand2);
|
|
let sum = operand1 + operand2;
|
|
let difference = operand1 - operand2;
|
|
let bitwise_and = operand1 & operand2;
|
|
let bitwise_or = operand1 | operand2;
|
|
let bitwise_xor = operand1 ^ operand2;
|
|
let sltu = (operand1 < operand2 ? 1 : 0);
|
|
let slt = (begin
|
|
Int#(64) signedOperand1 = unpack(pack(operand1));
|
|
Int#(64) signedOperand2 = unpack(pack(operand2));
|
|
(signedOperand1 < signedOperand2 ? 1 : 0);
|
|
end);
|
|
|
|
let sll = operand1 << operand2[5:0];
|
|
let sra = signedShiftRight(operand1, operand2[5:0]);
|
|
let srl = operand1 >> operand2[5:0];
|
|
|
|
return case(operator)
|
|
alu_ADD: tagged Valid sum;
|
|
alu_SUB: tagged Valid difference;
|
|
alu_AND: tagged Valid bitwise_and;
|
|
alu_OR: tagged Valid bitwise_or;
|
|
alu_XOR: tagged Valid bitwise_xor;
|
|
alu_SLTU: tagged Valid sltu;
|
|
alu_SLT: tagged Valid slt;
|
|
alu_SLL: tagged Valid sll;
|
|
alu_SRA: tagged Valid sra;
|
|
alu_SRL: tagged Valid srl;
|
|
default: tagged Invalid;
|
|
endcase;
|
|
endfunction
|
|
endinstance
|
|
|
|
typedef struct {
|
|
} AluCfg#(numeric type xlen);
|
|
|
|
interface AluIfc#(numeric type xlen);
|
|
method Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2);
|
|
endinterface
|
|
|
|
module mkAlu#(AluCfg#(xlen) cfg)(AluIfc#(xlen))
|
|
provisos(
|
|
Execute#(xlen)
|
|
);
|
|
|
|
method Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2);
|
|
return execute(operator, operand1, operand2);
|
|
endmethod
|
|
endmodule
|