mirror of
https://github.com/supleed2/ELEC50010-IAC-CW.git
synced 2024-12-22 21:35:48 +00:00
Updated PC, Harv, ALU, to work w/ MULT(U), DIV(U)
This commit is contained in:
parent
6e600966db
commit
90917f7566
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue