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( 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] 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[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] 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 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) - Greater Than or Equal to (>=) (signed)
- Negative Equality(=/=) (signed) - Negative Equality(=/=) (signed)
-Implementation Operation: A design choice used for implmentation. -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, GRT = 5'd16,
GEQ = 5'd17, GEQ = 5'd17,
NEQ = 5'd18, 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 SLT = 5'd20,//signed compare
SLTU = 5'd21,//unsigned compare SLTU = 5'd21,//unsigned compare
MULU = 5'd22,//unsigned divide MULU = 5'd22,//unsigned divide
DIVU = 5'd23//unsigned multiply DIVU = 5'd23,//unsigned multiply
MTHI = 5'd24,
MTLO = 5'd25
} Ops; } Ops;
Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming errors, as a result of enum implemetnation. 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 always_comb begin
assign ALUOps = ALUOp; assign ALUOps = ALUOp;
case(ALUOps) case(ALUOps)
@ -85,11 +111,14 @@ Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming
end end
MUL: begin MUL: begin
ALURes = $signed(A) * $signed(B); SMulRes = $signed(A) * $signed(B);
temp_Hi = SMulRes[63:32];
temp_Lo = SMulRes[31:0];
end end
DIV: begin DIV: begin
ALURes = $signed(A) / $signed(B); temp_Lo = $signed(A) / $signed(B);
temp_Hi = $signed(A) % $signed(B);
end end
AND: begin AND: begin
@ -205,13 +234,35 @@ Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming
end end
MULU: begin MULU: begin
ALURes = $signed(A) * $signed(B); UMulRes = A * B;
temp_Hi = UMulRes[63:32];
temp_Lo = UMulRes[31:0];
end end
DIVU: begin 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 end
endcase endcase
end 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 endmodule

View file

@ -5,12 +5,13 @@ module mips_cpu_control(
output logic[1:0] CtrlRegDst, output logic[1:0] CtrlRegDst,
output logic[1:0] CtrlPC, output logic[1:0] CtrlPC,
output logic CtrlMemRead, output logic CtrlMemRead,
output logic[1:0] CtrlMemtoReg, output logic[2:0] CtrlMemtoReg,
output logic[4:0] CtrlALUOp, output logic[4:0] CtrlALUOp,
output logic[4:0] Ctrlshamt, output logic[4:0] Ctrlshamt,
output logic CtrlMemWrite, output logic CtrlMemWrite,
output logic CtrlALUSrc, output logic CtrlALUSrc,
output logic CtrlRegWrite output logic CtrlRegWrite,
output logic CtrlSpcRegWriteEn
); );
typedef enum logic[5:0]{ typedef enum logic[5:0]{
@ -53,6 +54,8 @@ typedef enum logic[5:0]{
SRAV = 6'd7, SRAV = 6'd7,
JR = 6'd8, JR = 6'd8,
JALR = 6'd9, JALR = 6'd9,
MFLO = 6'd18,
MFHI = 6'd16,
MTHI = 6'd17, MTHI = 6'd17,
MTLO = 6'd19, MTLO = 6'd19,
MULT = 6'd24, 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 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 CtrlRegDst = 2'd0; //Write address comes from rt
$display("CTRLREGDST: 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 CtrlRegDst = 2'd1; //Write address comes from rd
$display("CTRLREGDST: Rd"); $display("CTRLREGDST: Rd");
end else if (op == JAL)begin end else if (op == JAL)begin
@ -106,17 +109,21 @@ always @(*) begin
//$display("Ctrl PC Jump Register"); //$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 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 if((op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LW) || (op==LWL) || (op==LWR))begin
CtrlMemRead = 1;//Memory is read enabled 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"); $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 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"); $display("Memory read disabled");
end else if ((op==JAL) || ((op==SPECIAL)&&(funct == JALR)))begin 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 end else begin CtrlMemRead = 1'bx;end//Not all instructions are encompassed so, added incase for debug purposes
//CtrlALUOp Logic //CtrlALUOp Logic
@ -146,8 +153,10 @@ always @(*) begin
$display("LB IN CONTROL"); $display("LB IN CONTROL");
end else if(op==LUI)begin end else if(op==LUI)begin
CtrlALUOp = 5'd7;//SLL from ALUOps CtrlALUOp = 5'd7;//SLL from ALUOps
end else if((op==SPECIAL)&&((funct==MTHI) || (funct==MTLO)))begin end else if((op==SPECIAL)&&((funct==MTHI)))begin
CtrlALUOp = 5'd19;//PAS from ALUOps 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 end else if((op==SPECIAL)&&(funct==MULT))begin
CtrlALUOp = 5'd2;//MUL from ALUOps CtrlALUOp = 5'd2;//MUL from ALUOps
end else if((op==SPECIAL)&&(funct==MULTU))begin end else if((op==SPECIAL)&&(funct==MULTU))begin
@ -197,6 +206,11 @@ always @(*) begin
CtrlMemWrite = 1;//Memory is write enabled CtrlMemWrite = 1;//Memory is write enabled
end else begin CtrlMemWrite = 0;end//default is 0 to ensure no accidental overwriting. 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 //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 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] 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 end else begin CtrlALUSrc = 1'bx;end
//CtrlRegWrite logic //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 CtrlRegWrite = 1;//The Registers are Write Enabled
end else begin CtrlRegWrite = 0;end // The Registers are Write Disabled end else begin CtrlRegWrite = 0;end // The Registers are Write Disabled
end 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[4:0] in_readreg1, in_readreg2, in_writereg, out_shamt, out_ALUOp;
logic[5:0] in_opcode; logic[5:0] in_opcode;
logic out_ALUCond, out_RegWrite, out_ALUSrc, out_MemWrite, out_MemRead; 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_readreg1 = instr_readdata[25:21];
assign in_readreg2 = instr_readdata[20:16]; assign in_readreg2 = instr_readdata[20:16];
@ -52,15 +53,21 @@ always @(*) begin
//Picking which output should be written to regfile. //Picking which output should be written to regfile.
case(out_MemtoReg) case(out_MemtoReg)
2'd0:begin 3'd0:begin
in_writedata = out_ALURes;//Output from ALU Result. in_writedata = out_ALURes;//Output from ALU Result.
end end
2'd1:begin 3'd1:begin
in_writedata = data_readdata;//Output from Data Memory. in_writedata = data_readdata;//Output from Data Memory.
end end
2'd2:begin 3'd2:begin
in_writedata = (out_pc_out + 32'd8);//Output from PC +8. in_writedata = (out_pc_out + 32'd8);//Output from PC +8.
end end
3'd3:begin
in_writedata = (out_ALUHi);
end
3'd4:begin
in_writedata = (out_ALULo);
end
endcase endcase
//Picking which output should be taken as the second operand for ALU. //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), .Ctrlshamt(out_shamt),
.CtrlMemWrite(out_MemWrite), .CtrlMemWrite(out_MemWrite),
.CtrlALUSrc(out_ALUSrc), .CtrlALUSrc(out_ALUSrc),
.CtrlRegWrite(out_RegWrite) .CtrlRegWrite(out_RegWrite),
.CtrlSpcRegWriteEn(out_SpcRegWriteEn)
); );
mips_cpu_regfile regfile( mips_cpu_regfile regfile(
@ -119,13 +127,20 @@ mips_cpu_regfile regfile(
mips_cpu_alu alu( mips_cpu_alu alu(
//Inputs to 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. .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. .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. .ALUOp(out_ALUOp), //Operation selection for ALU decided, and output by control.
.shamt(out_shamt), //Shift amount required for shift instruction taken from 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 //Outputs from ALU
.ALUCond(out_ALUCond), //condition used by control to decide on branch instructions. .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 endmodule