ELEC50010-IAC-CW/rtl/mips_cpu_alu.v

217 lines
5.2 KiB
Coq
Raw Normal View History

module mips_cpu_alu(
2020-12-07 11:49:44 +00:00
input logic[31:0] A, //Bus A - Input from the Readdata1 output from the reg file which corresponds to rs.
input logic[31:0] B, //Bus B - Input from the Readdata2 output from the reg file which corresponds to rt. Or from the 16-bit immediate sign extended to 32-bit value taken from Instr[15-0].
2020-12-05 19:37:01 +00:00
input logic [4:0] ALUOp, // 5-bit output from Control that tells the alu what operation to do from a list of 20 distinct alu operations(see below).
input logic [4:0] shamt, //5-bit input used to specify shift amount for shift operations. Taken directly from the R-type instruction (Non-Variable) or from
2020-12-02 12:51:53 +00:00
2020-12-05 19:37:01 +00:00
output logic ALUCond, //If a relevant condition is met, this output goes high(Active High). Note: Relevant as in related to current condition being tested.
output logic[31:0] ALURes // The ouput of the ALU
2020-12-02 12:51:53 +00:00
);
2020-12-05 19:37:01 +00:00
/*
Alu Operations:
2020-12-07 11:49:44 +00:00
-Manipulation Operations: They perform an operation on a value(s) and have an output to ALURes.
- Addition (unsigned)
- Subtraction (unsigned)
2020-12-05 19:37:01 +00:00
- Multiplication
- Division
- Bitwise AND
- Bitwise OR
- Bitwise XOR
- Shift Left Logical
- Shift Left Logical Variable
- Shift Right Logical
- Shift Right Logical Variable
- Shift Right Arithmetic
- Shift Right Arithmetic Variable
2020-12-07 11:49:44 +00:00
- Set On Less Than (signed)
- Set On Less Than Unsigned
- Multiplication (unsigned)
- Division (unsigned)
-Condtional Check Operations: They check conditions and have an output to ALUCond
- Equality (=) (signed)
- Less Than (<) (signed)
- Less Than or Equal To (<=) (signed)
- Greater Than (>) (signed)
- Greater Than or Equal to (>=) (signed)
- Negative Equality(=/=) (signed)
-Implementation Operation: A design choice used for implmentation.
2020-12-05 19:37:01 +00:00
- Pass-through (Used to implement MTHI and MTLO, as these instructions do not need the ALU but the alu is in the pathway to the regfile, so the register value simply passes through.)
*/
typedef enum logic [4:0]{ //Enum list to use words instead of numbers when refering to operations.
ADD = 5'd0,
SUB = 5'd1,
2020-12-07 11:49:44 +00:00
MUL = 5'd2,//signed multiply
DIV = 5'd3,//signed divide
2020-12-05 19:37:01 +00:00
AND = 5'd4,
OR = 5'd5,
XOR = 5'd6,
SLL = 5'd7,
SLLV = 5'd8,
SRL = 5'd9,
SRLV = 5'd10,
SRA = 5'd11,
SRAV = 5'd12,
EQ = 5'd13,
LES = 5'd14,
LEQ = 5'd15,
GRT = 5'd16,
GEQ = 5'd17,
NEQ = 5'd18,
2020-12-07 11:49:44 +00:00
PAS = 5'd19,
SLT = 5'd20,//signed compare
SLTU = 5'd21,//unsigned compare
MULU = 5'd22,//unsigned divide
DIVU = 5'd23//unsigned multiply
2020-12-05 19:37:01 +00:00
} Ops;
2020-12-07 11:49:44 +00:00
Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming errors, as a result of enum implemetnation.
2020-12-05 19:37:01 +00:00
always_comb begin
assign ALUOps = ALUOp;
2020-12-05 19:37:01 +00:00
case(ALUOps)
ADD: begin
$signed(ALURes) = $signed(A) + $signed(B);
end
SUB: begin
$signed(ALURes) = $signed(A) - $signed(B) ;
end
2020-12-02 12:51:53 +00:00
2020-12-05 19:37:01 +00:00
MUL: begin
$signed(ALURes) = $signed(A) * $signed(B);
end
2020-12-02 12:51:53 +00:00
DIV: begin
$signed(ALURes) = $signed(A) / $signed(B);
end
2020-12-02 12:51:53 +00:00
2020-12-05 19:37:01 +00:00
AND: begin
ALURes = A & B;
end
2020-12-02 12:51:53 +00:00
OR: begin
ALURes = A | B;
end
2020-12-05 19:37:01 +00:00
XOR: begin
ALURes = A^B;
end
2020-12-02 12:51:53 +00:00
2020-12-05 19:37:01 +00:00
SLL: begin
ALURes = B << shamt;
2020-12-05 19:37:01 +00:00
end
2020-12-02 12:51:53 +00:00
SLLV: begin
ALURes = B << A;
end
2020-12-02 12:51:53 +00:00
2020-12-05 19:37:01 +00:00
SRL: begin
ALURes = B >> shamt;
2020-12-05 19:37:01 +00:00
end
SRLV: begin
ALURes = B >> A;
2020-12-05 19:37:01 +00:00
end
2020-12-05 19:37:01 +00:00
SRA: begin
$signed(ALURes) = $signed(B) >>> shamt;
2020-12-05 19:37:01 +00:00
end
SRAV: begin
$signed(ALURes) = $signed(B) >>> A;
end
2020-12-05 19:37:01 +00:00
EQ: begin
2020-12-07 11:49:44 +00:00
if ($signed(A) == $signed(B)) begin
2020-12-05 19:37:01 +00:00
ALUCond = 1;
end
else begin
2020-12-05 19:37:01 +00:00
ALUCond = 0;
end
end
2020-12-05 19:37:01 +00:00
LES: begin
2020-12-07 11:49:44 +00:00
if ($signed(A) < $signed(B)) begin
2020-12-05 19:37:01 +00:00
ALUCond = 1;
end
else begin
2020-12-05 19:37:01 +00:00
ALUCond = 0;
end
2020-12-05 19:37:01 +00:00
end
2020-12-05 19:37:01 +00:00
LEQ: begin
2020-12-07 11:49:44 +00:00
if ($signed(A) <= $signed(B)) begin
2020-12-05 19:37:01 +00:00
ALUCond = 1;
end
else begin
2020-12-05 19:37:01 +00:00
ALUCond = 0;
end
2020-12-05 19:37:01 +00:00
end
2020-12-05 19:37:01 +00:00
GRT: begin
2020-12-07 11:49:44 +00:00
if ($signed(A) > $signed(B)) begin
2020-12-05 19:37:01 +00:00
ALUCond = 1;
end
else begin
2020-12-05 19:37:01 +00:00
ALUCond = 0;
end
2020-12-05 19:37:01 +00:00
end
2020-12-05 19:37:01 +00:00
GEQ: begin
2020-12-07 11:49:44 +00:00
if ($signed(A) >= $signed(B)) begin
2020-12-05 19:37:01 +00:00
ALUCond = 1;
end
else begin
2020-12-05 19:37:01 +00:00
ALUCond = 0;
end
2020-12-05 19:37:01 +00:00
end
2020-12-05 19:37:01 +00:00
NEQ: begin
2020-12-07 11:49:44 +00:00
if ($signed(A) != $signed(B)) begin
2020-12-05 19:37:01 +00:00
ALUCond = 1;
end
else begin
ALUCond = 0;
end
end
2020-12-05 19:37:01 +00:00
PAS: begin
ALURes = A;
end
2020-12-07 11:49:44 +00:00
SLT: begin
if ($signed(A) < $signed(B)) begin
ALURes = 1;
end
end
SLTU: begin
if (A < B) begin
ALURes = 1;
end
end
MULU: begin
$signed(ALURes) = $signed(A) * $signed(B);
2020-12-07 11:49:44 +00:00
end
DIVU: begin
$signed(ALURes) = $signed(A) / $signed(B);
2020-12-07 11:49:44 +00:00
end
endcase
end
endmodule