ELEC50010-IAC-CW/rtl/mips_cpu_control.v

231 lines
10 KiB
Coq
Raw Normal View History

2020-12-07 11:49:44 +00:00
module mips_cpu_control(
input logic[31:0] Instr,
input logic ALUCond,
output logic[1:0] CtrlRegDst,
2020-12-07 11:49:44 +00:00
output logic[1:0] CtrlPC,
output logic CtrlMemRead,
output logic[2:0] CtrlMemtoReg,
2020-12-07 11:49:44 +00:00
output logic[4:0] CtrlALUOp,
output logic[4:0] Ctrlshamt,
output logic CtrlMemWrite,
2020-12-16 08:38:46 +00:00
output logic[1:0] CtrlALUSrc,
output logic CtrlRegWrite,
output logic CtrlSpcRegWriteEn
2020-12-07 11:49:44 +00:00
);
2020-12-01 07:30:57 +00:00
2020-12-07 11:49:44 +00:00
typedef enum logic[5:0]{
SPECIAL = 6'd0,
REGIMM = 6'd1,
J = 6'd2,
JAL = 6'd3,
BEQ = 6'd4,
BNE = 6'd5,
BLEZ = 6'd6,
BGTZ = 6'd7,
ADDI = 6'd8,
ADDIU = 6'd9,
SLTI = 6'd10,
SLTIU = 6'd11,
ANDI = 6'd12,
ORI = 6'd13,
XORI = 6'd14,
LUI = 6'd15,
LB = 6'd32,
LH = 6'd33,
LWL = 6'd34,
LW = 6'd35,
LBU = 6'd36,
LHU = 6'd37,
LWR = 6'd38,
SB = 6'd40,
SH = 6'd41,
SW = 6'd43
} op_enum;
op_enum op;
2020-12-07 11:49:44 +00:00
typedef enum logic[5:0]{
SLL = 6'd0,
SRL = 6'd2,
SRA = 6'd3,
SLLV = 6'd4,
SRLV = 6'd6,
SRAV = 6'd7,
JR = 6'd8,
JALR = 6'd9,
MFLO = 6'd18,
MFHI = 6'd16,
2020-12-07 11:49:44 +00:00
MTHI = 6'd17,
MTLO = 6'd19,
MULT = 6'd24,
MULTU = 6'd25,
DIV = 6'd26,
DIVU = 6'd27,
ADDU = 6'd33,
SUBU = 6'd35,
AND = 6'd36,
OR = 6'd37,
XOR = 6'd38,
SLT = 6'd42,
SLTU = 6'd43
} funct_enum;
funct_enum funct;
2020-12-07 11:49:44 +00:00
typedef enum logic[4:0]{
BLTZ = 5'd0,
BGEZ = 5'd1,
BLTZAL = 5'd16,
BGEZAL = 5'd17
} rt_enum;
rt_enum rt;
always @(*) begin
assign op = Instr[31:26];
assign funct = Instr[5:0];
assign rt = Instr[20:16];
2020-12-07 11:49:44 +00:00
//CtrlRegDst 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==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==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
CtrlRegDst = 2'd2; //const reg 31, for writing to the link register
$display("CTRLREGDST: Link");
end else begin CtrlRegDst = 1'bx; $display("xxxxxxxxxxxxxx");end//Not all instructions are encompassed so, added incase for debug purposes
2020-12-07 11:49:44 +00:00
//CtrlPC logic
2020-12-09 12:24:21 +00:00
if(ALUCond && ((op==BEQ) || (op==BGTZ) || (op==BLEZ) || (op==BNE) || ((op==REGIMM)&&((rt==BGEZ) || (rt==BGEZAL) || (rt==BLTZ) || (rt==BLTZAL)))))begin
2020-12-07 11:49:44 +00:00
CtrlPC = 2'd1; // Branches - Jumps relative to PC
2020-12-09 12:24:21 +00:00
end else if((op==J) || (op==JAL))begin
2020-12-07 11:49:44 +00:00
CtrlPC = 2'd2; // Jumps within 256MB Region using 26-bit immediate in J type instruction
$display("Jump PC Ctrl");
2020-12-16 08:38:46 +00:00
end else if((op==SPECIAL)&&((funct==JR) || (funct==JALR)))begin
2020-12-07 11:49:44 +00:00
CtrlPC = 2'd3; // Jumps using Register.
2020-12-16 08:38:46 +00:00
$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
2020-12-07 11:49:44 +00:00
//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.
2020-12-09 12:24:21 +00:00
if((op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LW) || (op==LWL) || (op==LWR))begin
2020-12-07 11:49:44 +00:00
CtrlMemRead = 1;//Memory is read enabled
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==OR) || (funct==SLL) || (funct==SLLV) || (funct==SLT) || (funct==SLTU) || (funct==SRA) || (funct==SRAV) || (funct==SRL) || (funct==SRLV) || (funct==SUBU) || (funct==XOR))))begin
2020-12-07 11:49:44 +00:00
CtrlMemRead = 0;//Memory is read disabled
CtrlMemtoReg = 3'd0;//write data port of regfile is fed from ALURes
$display("Memory read disabled");
2020-12-09 12:24:21 +00:00
end else if ((op==JAL) || ((op==SPECIAL)&&(funct == JALR)))begin
CtrlMemtoReg = 3'd2;//write data port of regfile is fed from PC + 8
2020-12-16 08:38:46 +00:00
end else if ((op==SPECIAL)&&(funct == MFHI))begin
CtrlMemtoReg = 3'd3;//write data port of regfile is fed from ALUHi
2020-12-16 08:38:46 +00:00
end else if ((op==SPECIAL)&&(funct == MFLO))begin
CtrlMemtoReg = 3'd4;//write data port of regfile is fed from ALULo
2020-12-07 11:49:44 +00:00
end else begin CtrlMemRead = 1'bx;end//Not all instructions are encompassed so, added incase for debug purposes
2020-12-16 08:38:46 +00:00
$display("OP: %d, Funct: %d", op, funct);
2020-12-07 11:49:44 +00:00
//CtrlALUOp Logic
2020-12-09 12:24:21 +00:00
if((op==ADDIU) || ((op==SPECIAL)&&(funct==ADDU)))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd0; //ADD from ALUOps
$display("ALU OP = 0 (ADDU/ADDIU)");
end else if((op==ANDI) || ((op==SPECIAL)&&(funct==AND)))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd4;//AND from ALUOps
2020-12-09 12:24:21 +00:00
end else if(op==BEQ) begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd13;//EQ from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==REGIMM)&&((rt==BGEZ) || (rt==BGEZAL)))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd17;//GEQ from ALUOps
2020-12-09 12:24:21 +00:00
end else if(op==BGTZ)begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd16;//GRT from ALUOps
2020-12-09 12:24:21 +00:00
end else if(op==BLEZ)begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd15;//LEQ from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==REGIMM)&&((rt==BLTZ) || (rt==BLTZAL)))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd14;//LES from ALUOps
2020-12-09 12:24:21 +00:00
end else if(op==BNE)begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd18;//NEQ from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==DIV))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd3;//DIV from ALUOps
2020-12-16 08:38:46 +00:00
$display("DIV CONTROL ALUOps");
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==DIVU))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd23;//DIVU from ALUOps
end else if((op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LW) || (op==LWL) || (op==LWR) || (op==SB) || (op==SH) || (op==SW))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd0;//ADD from ALUOps
$display("LB IN CONTROL");
2020-12-09 12:24:21 +00:00
end else if(op==LUI)begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd7;//SLL 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
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==MULT))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd2;//MUL from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==MULTU))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd22;//MULU from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==ORI) || ((op==SPECIAL)&&(funct==OR)))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd5;//OR from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==SLL))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd7;//SLL from ALUOps
2020-12-12 16:25:36 +00:00
$display("ALU Op = 7 (SLL)");
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==SLLV))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd8;//SLLV from ALUOps
$display("ALU Op = 9 (SLLV)");
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==SRA))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd11;//SRA from ALUOps
$display("ALU Op = 11 (SRA)");
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==SRAV))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd12;//SRAV from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==SRL))begin
2020-12-12 16:25:36 +00:00
$display("ALU Op = 7 (SRL)");
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd9;//SRL from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==SRLV))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd10;//SRLV from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==SLTI) || ((op==SPECIAL)&&(funct==SLT)))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd20;//SLT from ALUOps
$display("ALU Op = 20 (SLT/SLTI)");
2020-12-09 12:24:21 +00:00
end else if((op==SLTIU) || ((op==SPECIAL)&&(funct==SLTU)))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd21;//SLTU from ALUOps
$display("ALU Op = 21 (SLTU/SLTIU)");
2020-12-09 12:24:21 +00:00
end else if((op==SPECIAL)&&(funct==SUBU))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd1;//SUB from ALUOps
2020-12-09 12:24:21 +00:00
end else if((op==XORI) || ((op==SPECIAL)&&(funct==XOR)))begin
2020-12-07 11:49:44 +00:00
CtrlALUOp = 5'd6;//XOR from ALUOps
$display("ALU Op = 6 (XOR)");
2020-12-07 11:49:44 +00:00
end else begin
CtrlALUOp = 5'bxxxxx;
2020-12-01 07:30:57 +00:00
end
2020-12-07 11:49:44 +00:00
//Ctrlshamt logic
2020-12-09 12:24:21 +00:00
if((op==SPECIAL)&&((funct==SRA) || (funct==SRL) || (funct==SLL)))begin
2020-12-07 11:49:44 +00:00
Ctrlshamt = Instr[10:6];// Shift amount piped in from the instruction
end else if(op == LUI)begin
Ctrlshamt = 5'd16;//Used specifically to implement LUI as the instruction itslef does not include shamt
end else begin Ctrlshamt = 5'bxxxxx;end
//CtrlMemWrite logic
2020-12-09 12:24:21 +00:00
if((op==SB) || (op==SH) || (op==SW))begin
2020-12-07 11:49:44 +00:00
CtrlMemWrite = 1;//Memory is write enabled
end else begin CtrlMemWrite = 0;end//default is 0 to ensure no accidental overwriting.
//CtrlSpcRegWriteEn logic
2020-12-16 08:38:46 +00:00
if((op==SPECIAL)&&((funct==MTHI) || (funct==MTLO) || (funct==MULT) || (funct==MULTU) || (funct==DIV) || (funct==DIVU)))begin
CtrlSpcRegWriteEn = 1;//Special register Hi and Lo are write enabled
2020-12-16 08:38:46 +00:00
$display("Temp being written");
end else begin CtrlSpcRegWriteEn = 0;end//default is 0 to ensure no accidental overwriting.
2020-12-07 11:49:44 +00:00
//CtrlALUSrc logic
2020-12-16 08:38:46 +00:00
if((op==ADDIU) || (op==LUI) || (op==SLTI) || (op==SLTIU) || (op==LB) || (op==LBU) || (op==LH) || (op==LHU) || (op==LW) || (op==LWL) || (op==LWR) || (op==SB) || (op==SH) || (op==SW))begin
2020-12-07 11:49:44 +00:00
CtrlALUSrc = 1;//ALU Bus B is fed from the 16-bit immediate sign extended to 32-bit value taken from Instr[15-0]
end else if((op==BEQ) || (op==BGTZ) || (op==BLEZ) || (op==BNE) || ((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))) || ((op==REGIMM)&&((rt==BGEZ) || (rt==BGEZAL) || (rt==BLTZ) || (rt==BLTZAL))))begin
2020-12-07 11:49:44 +00:00
CtrlALUSrc = 0;///ALU Bus B is fed from rt.
2020-12-16 08:38:46 +00:00
end else if ((op==ORI) || (op==ANDI) || (op==XORI)) begin
CtrlALUSrc = 2;
2020-12-07 11:49:44 +00:00
end else begin CtrlALUSrc = 1'bx;end
2020-12-09 12:24:21 +00:00
2020-12-07 11:49:44 +00:00
//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==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
2020-12-07 11:49:44 +00:00
CtrlRegWrite = 1;//The Registers are Write Enabled
2020-12-16 08:38:46 +00:00
$display("OPcode mflo: %h", op);
2020-12-07 11:49:44 +00:00
end else begin CtrlRegWrite = 0;end // The Registers are Write Disabled
end
endmodule