Updated PC, Harv, ALU, to work w/ MULT(U), DIV(U)

This commit is contained in:
Jeevaha Coelho 2020-12-15 13:48:28 -08:00
parent 6e600966db
commit 90917f7566
3 changed files with 106 additions and 26 deletions

View file

@ -1,11 +1,18 @@
module mips_cpu_alu(
input logic clk, //clock for special registers Hi and Lo
input logic rst,
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].
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
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 GPR rs (Variable)
input logic[31:0] Hi_in,
input logic[31:0] Lo_in,
input logic SpcRegWriteEn,
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
output logic[31:0] ALURes, // The ouput of the ALU
output logic[31:0] ALUHi, //Special Hi Register output
output logic[31:0] ALULo //Special Hi Register output
);
/*
@ -37,7 +44,8 @@ Alu Operations:
- Greater Than or Equal to (>=) (signed)
- Negative Equality(=/=) (signed)
-Implementation Operation: A design choice used for implmentation.
- 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.)
- MTHI (move the contents of GPR rs to special register Hi)
- MTLO (move the contents of GPR rs to special register Lo)
*/
@ -62,17 +70,35 @@ Alu Operations:
GRT = 5'd16,
GEQ = 5'd17,
NEQ = 5'd18,
PAS = 5'd19,
// PAS = 5'd19, no need for PAS as it was based on faulty reasoning that speical registers Hi and Lo are in the reg file.
SLT = 5'd20,//signed compare
SLTU = 5'd21,//unsigned compare
MULU = 5'd22,//unsigned divide
DIVU = 5'd23//unsigned multiply
DIVU = 5'd23,//unsigned multiply
MTHI = 5'd24,
MTLO = 5'd25
} Ops;
Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming errors, as a result of enum implemetnation.
logic signed[63:0] SMulRes;//signed result of multiplication.
logic[63:0] UMulRes;//unsigned result of multiplication.
logic[31:0] temp_Hi;
logic[31:0] temp_Lo;
reg [31:0] Hi;
reg [31:0] Lo;
assign ALUHi = Hi;//combinatorial read of Hi register
assign ALULo = Lo;//combinatorial read of Lo register
initial begin
Hi <= 32'd0;
Lo <= 32'd0;
end
always_comb begin
assign ALUOps = ALUOp;
case(ALUOps)
@ -85,11 +111,14 @@ Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming
end
MUL: begin
ALURes = $signed(A) * $signed(B);
SMulRes = $signed(A) * $signed(B);
temp_Hi = SMulRes[63:32];
temp_Lo = SMulRes[31:0];
end
DIV: begin
ALURes = $signed(A) / $signed(B);
temp_Lo = $signed(A) / $signed(B);
temp_Hi = $signed(A) % $signed(B);
end
AND: begin
@ -205,13 +234,35 @@ Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming
end
MULU: begin
ALURes = $signed(A) * $signed(B);
UMulRes = A * B;
temp_Hi = UMulRes[63:32];
temp_Lo = UMulRes[31:0];
end
DIVU: begin
ALURes = $signed(A) / $signed(B);
temp_Lo = A / B;
temp_Hi = A % B;
end
MTHI: begin
temp_Hi = Hi_in;
end
MTLO: begin
temp_Lo = Lo_in;
end
endcase
end
always_ff @(posedge clk) begin
if(rst)begin
Hi <= 0;
Lo <= 0;
end else if (SpcRegWriteEn) begin
Hi <= temp_Hi;
Lo <= temp_Lo;
end
end
endmodule

View file

@ -5,12 +5,13 @@ module mips_cpu_control(
output logic[1:0] CtrlRegDst,
output logic[1:0] CtrlPC,
output logic CtrlMemRead,
output logic[1:0] CtrlMemtoReg,
output logic[2:0] CtrlMemtoReg,
output logic[4:0] CtrlALUOp,
output logic[4:0] Ctrlshamt,
output logic CtrlMemWrite,
output logic CtrlALUSrc,
output logic CtrlRegWrite
output logic CtrlRegWrite,
output logic CtrlSpcRegWriteEn
);
typedef enum logic[5:0]{
@ -53,6 +54,8 @@ typedef enum logic[5:0]{
SRAV = 6'd7,
JR = 6'd8,
JALR = 6'd9,
MFLO = 6'd18,
MFHI = 6'd16,
MTHI = 6'd17,
MTLO = 6'd19,
MULT = 6'd24,
@ -87,7 +90,7 @@ always @(*) begin
if((op==ADDIU) || (op==ANDI) || (op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LUI) || (op==LW) || (op==LWL) || (op==LWR) || (op==ORI) || (op==SLTI) || (op==SLTIU) || (op==XORI))begin
CtrlRegDst = 2'd0; //Write address comes from rt
$display("CTRLREGDST: Rt");
end else if ((op==SPECIAL)&&((funct==ADDU) || (funct==AND) || (funct==JALR) || (funct==OR) || (funct==SLL) || (funct==SLLV) || (funct==SLT) || (funct==SLTU) || (funct==SRA) || (funct==SRAV) || (funct==SRL) || (funct==SRLV) || (funct==SUBU) || (funct==XOR)))begin
end else if ((op==SPECIAL)&&((funct==ADDU) || (funct==AND) || (funct==JALR) || (funct==MFLO) || (funct==MFHI) || (funct==OR) || (funct==SLL) || (funct==SLLV) || (funct==SLT) || (funct==SLTU) || (funct==SRA) || (funct==SRAV) || (funct==SRL) || (funct==SRLV) || (funct==SUBU) || (funct==XOR)))begin
CtrlRegDst = 2'd1; //Write address comes from rd
$display("CTRLREGDST: Rd");
end else if (op == JAL)begin
@ -106,17 +109,21 @@ always @(*) begin
//$display("Ctrl PC Jump Register");
end else begin CtrlPC = 2'd0; /*/$display("Ctrl PC No Jump/Branch");*/end // No jumps or branches, just increment to next word
//CtrlMemRead and CtrlMemtoReg logic -- Interesting quirk that they have the same logic. Makes sense bc you'd only want to select the read data out when the memory itself is read enabled.
//CtrlMemRead and CtrlMemtoReg logic -- Interesting quirk that they have the same logic where both are concerned. Makes sense bc you'd only want to select the read data out when the memory itself is read enabled.
if((op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LW) || (op==LWL) || (op==LWR))begin
CtrlMemRead = 1;//Memory is read enabled
CtrlMemtoReg = 2'd1;//write data port of memory is fed from data memory
CtrlMemtoReg = 3'd1;//write data port of regfile is fed from data memory
$display("Memory read enabled");
end else if ((op==ADDIU) || (op==ANDI) || (op==ORI) || (op==SLTI) || (op==SLTIU) || (op==XORI) || ((op==SPECIAL)&&((funct==ADDU) || (funct==AND) || (funct==DIV) || (funct==DIVU) || (funct==MTHI) || (funct==MTLO) || (funct==MULT) || (funct==MULTU) || (funct==OR) || (funct==SLL) || (funct==SLLV) || (funct==SLT) || (funct==SLTU) || (funct==SRA) || (funct==SRAV) || (funct==SRL) || (funct==SRLV) || (funct==SUBU) || (funct==XOR))))begin
end else if ((op==ADDIU) || (op==ANDI) || (op==ORI) || (op==SLTI) || (op==SLTIU) || (op==XORI) || ((op==SPECIAL)&&((funct==ADDU) || (funct==AND) || (funct==OR) || (funct==SLL) || (funct==SLLV) || (funct==SLT) || (funct==SLTU) || (funct==SRA) || (funct==SRAV) || (funct==SRL) || (funct==SRLV) || (funct==SUBU) || (funct==XOR))))begin
CtrlMemRead = 0;//Memory is read disabled
CtrlMemtoReg = 2'd0;//write data port of memory is fed from ALURes
CtrlMemtoReg = 3'd0;//write data port of regfile is fed from ALURes
$display("Memory read disabled");
end else if ((op==JAL) || ((op==SPECIAL)&&(funct == JALR)))begin
CtrlMemtoReg = 2'd2;//write data port of memory is fed from PC + 8
CtrlMemtoReg = 3'd2;//write data port of regfile is fed from PC + 8
end else if ((op==SPECIAL)&&(funct == MTHI)))begin
CtrlMemtoReg = 3'd3;//write data port of regfile is fed from ALUHi
end else if ((op==SPECIAL)&&(funct == MTLO)))begin
CtrlMemtoReg = 3'd4;//write data port of regfile is fed from ALULo
end else begin CtrlMemRead = 1'bx;end//Not all instructions are encompassed so, added incase for debug purposes
//CtrlALUOp Logic
@ -146,8 +153,10 @@ always @(*) begin
$display("LB IN CONTROL");
end else if(op==LUI)begin
CtrlALUOp = 5'd7;//SLL from ALUOps
end else if((op==SPECIAL)&&((funct==MTHI) || (funct==MTLO)))begin
CtrlALUOp = 5'd19;//PAS from ALUOps
end else if((op==SPECIAL)&&((funct==MTHI)))begin
CtrlALUOp = 5'd24;//MTHI from ALUOps
end else if((op==SPECIAL)&&((funct==MTLO)))begin
CtrlALUOp = 5'd25;//MTLO from ALUOps
end else if((op==SPECIAL)&&(funct==MULT))begin
CtrlALUOp = 5'd2;//MUL from ALUOps
end else if((op==SPECIAL)&&(funct==MULTU))begin
@ -197,6 +206,11 @@ always @(*) begin
CtrlMemWrite = 1;//Memory is write enabled
end else begin CtrlMemWrite = 0;end//default is 0 to ensure no accidental overwriting.
//CtrlSpcRegWriteEn logic
if((op==SPECIAL)&&((funct==MTHI) || (funct==MTLO)))begin
CtrlSpcRegWriteEn = 1;//Special register Hi and Lo are write enabled
end else begin CtrlSpcRegWriteEn = 0;end//default is 0 to ensure no accidental overwriting.
//CtrlALUSrc logic
if((op==ADDIU) || (op==ANDI) || (op==LUI) || (op==ORI) || (op==SLTI) || (op==SLTIU) || (op==XORI) || (op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LW) || (op==LWL) || (op==LWR) || (op==SB) || (op==SH) || (op==SW))begin
CtrlALUSrc = 1;//ALU Bus B is fed from the 16-bit immediate sign extended to 32-bit value taken from Instr[15-0]
@ -205,7 +219,7 @@ always @(*) begin
end else begin CtrlALUSrc = 1'bx;end
//CtrlRegWrite logic
if((op==ADDIU) || (op==ANDI) || (op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LUI) || (op==LW) || (op==LWL) || (op==LWR) || (op==ORI) || (op==SLTI) || (op==XORI) || ((op==SPECIAL)&&((funct==ADDU) || (funct==AND) || (funct==DIV) || (funct==DIVU) || (funct==MULT) || (funct==MULTU) || (funct==OR) || (funct==SLL) || (funct==SLLV) || (funct==SLT) || (funct==SLTU) || (funct==SRA) || (funct==SRAV) || (funct==SRL) || (funct==SRLV) || (funct==SUBU) || (funct==XOR)))) begin
if((op==ADDIU) || (op==ANDI) || (op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LUI) || (op==LW) || (op==LWL) || (op==LWR) || (op==ORI) || (op==SLTI) || (op==XORI) || ((op==SPECIAL)&&((funct==ADDU) || (funct==AND) || (funct==MFLO) || (funct==MFHI) || (funct==OR) || (funct==SLL) || (funct==SLLV) || (funct==SLT) || (funct==SLTU) || (funct==SRA) || (funct==SRAV) || (funct==SRL) || (funct==SRLV) || (funct==SUBU) || (funct==XOR)))) begin
CtrlRegWrite = 1;//The Registers are Write Enabled
end else begin CtrlRegWrite = 0;end // The Registers are Write Disabled
end

View file

@ -30,7 +30,8 @@ logic[31:0] out_pc_out, out_ALURes, out_readdata1, out_readdata2, in_B, in_write
logic[4:0] in_readreg1, in_readreg2, in_writereg, out_shamt, out_ALUOp;
logic[5:0] in_opcode;
logic out_ALUCond, out_RegWrite, out_ALUSrc, out_MemWrite, out_MemRead;
logic[1:0] out_RegDst, out_PC, out_MemtoReg;
logic[1:0] out_RegDst, out_PC;
logic[2:0] out_MemtoReg;
assign in_readreg1 = instr_readdata[25:21];
assign in_readreg2 = instr_readdata[20:16];
@ -52,15 +53,21 @@ always @(*) begin
//Picking which output should be written to regfile.
case(out_MemtoReg)
2'd0:begin
3'd0:begin
in_writedata = out_ALURes;//Output from ALU Result.
end
2'd1:begin
3'd1:begin
in_writedata = data_readdata;//Output from Data Memory.
end
2'd2:begin
3'd2:begin
in_writedata = (out_pc_out + 32'd8);//Output from PC +8.
end
3'd3:begin
in_writedata = (out_ALUHi);
end
3'd4:begin
in_writedata = (out_ALULo);
end
endcase
//Picking which output should be taken as the second operand for ALU.
@ -99,7 +106,8 @@ mips_cpu_control control( //instance of the 'mips_cpu_control' module called 'co
.Ctrlshamt(out_shamt),
.CtrlMemWrite(out_MemWrite),
.CtrlALUSrc(out_ALUSrc),
.CtrlRegWrite(out_RegWrite)
.CtrlRegWrite(out_RegWrite),
.CtrlSpcRegWriteEn(out_SpcRegWriteEn)
);
mips_cpu_regfile regfile(
@ -119,13 +127,20 @@ mips_cpu_regfile regfile(
mips_cpu_alu alu(
//Inputs to ALU
.clk(clk),
.rst(reset),
.A(out_readdata1), //operand 1 taken from 'Read data 1' aka the data stored in GPR rs.
.B(in_B), //operand 2 taken either from: 'Read data 2' aka the data stored in rt; or 16-bit immediate sign extended to 32 bits.
.ALUOp(out_ALUOp), //Operation selection for ALU decided, and output by control.
.shamt(out_shamt), //Shift amount required for shift instruction taken from control.
.Hi_in(out_readdata1),
.Lo_in(out_readdata1),
.SpcRegWriteEn(out_SpcRegWriteEn),
//Outputs from ALU
.ALUCond(out_ALUCond), //condition used by control to decide on branch instructions.
.ALURes(out_ALURes) //output/result of operation that goes to either: 'Address' port of Data Memory; or 'Write Data' port of the register file.
.ALURes(out_ALURes), //output/result of operation that goes to either: 'Address' port of Data Memory; or 'Write Data' port of the register file.
.ALUHi(out_ALUHi), //Special register Hi output to be used for MFHI instructions - feeds in_writedata.
.ALULo(out_ALULo), //Special register Hi output to be used for MFLO instructions - feeds in_writedata.
);
endmodule