From 9198c4f51b736574785eeaf6e8b42e9423e53716 Mon Sep 17 00:00:00 2001 From: jc4419 <60656643+jc4419@users.noreply.github.com> Date: Mon, 7 Dec 2020 15:49:44 +0400 Subject: [PATCH] Updated ALU and Control --- rtl/mips_cpu_alu.v | 93 +++++--- rtl/mips_cpu_control.v | 506 ++++++++++++++++------------------------- 2 files changed, 250 insertions(+), 349 deletions(-) diff --git a/rtl/mips_cpu_alu.v b/rtl/mips_cpu_alu.v index a3cfefe..4cebaf0 100644 --- a/rtl/mips_cpu_alu.v +++ b/rtl/mips_cpu_alu.v @@ -1,6 +1,6 @@ module mips_cpu_alu( - input signed logic[31:0] A, //Bus A - Input from the Readdata1 output from the reg file which corresponds to rs. - input signed logic[31:0] B, //Bus B - Input from the Readdata2 output from the reg file which corresponds to rt. + 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 @@ -11,9 +11,9 @@ module mips_cpu_alu( /* Alu Operations: --Manipulation Operations: The perform an operation on a value(s). - - Addition - - Subtraction +-Manipulation Operations: They perform an operation on a value(s) and have an output to ALURes. + - Addition (unsigned) + - Subtraction (unsigned) - Multiplication - Division - Bitwise AND @@ -25,14 +25,18 @@ Alu Operations: - Shift Right Logical Variable - Shift Right Arithmetic - Shift Right Arithmetic Variable --Condtional Check Operations: They check conditions. - - Equality (=) - - Less Than (<) - - Less Than or Equal To (<=) - - Greater Than (>) - - Greater Than or Equal to (>=) - - Negative Equality(=/=) --Implementation Operation: + - 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. - 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.) */ @@ -41,8 +45,8 @@ Alu Operations: ADD = 5'd0, SUB = 5'd1, - MUL = 5'd2, - DIV = 5'd3, + MUL = 5'd2,//signed multiply + DIV = 5'd3,//signed divide AND = 5'd4, OR = 5'd5, XOR = 5'd6, @@ -58,11 +62,16 @@ Alu Operations: GRT = 5'd16, GEQ = 5'd17, NEQ = 5'd18, - PAS = 5'd19 + PAS = 5'd19, + SLT = 5'd20,//signed compare + SLTU = 5'd21,//unsigned compare + MULU = 5'd22,//unsigned divide + DIVU = 5'd23//unsigned multiply + } Ops; -Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming errors, as a result of enum implemetnation quirks. +Ops ALUOps; //Note confusing naming to avoid potential duplicate variable naming errors, as a result of enum implemetnation. assign ALUOps = ALUOp @@ -72,19 +81,19 @@ assign ALUOps = ALUOp case(ALUOps) ADD: begin - ALURes = A + B; + ALURes = $signed(A) + $signed(B); end SUB: begin - ALURes = A - B; + ALURes = $signed(A) - $signed(B) ; end MUL: begin - ALURes = A * B; + ALURes = $signed(A) * $signed(B); end DIV: begin - ALURes = A / B; + ALURes = $signed(A) / $signed(B); end AND: begin @@ -124,7 +133,7 @@ assign ALUOps = ALUOp end EQ: begin - if A == B begin + if ($signed(A) == $signed(B)) begin ALUCond = 1; end else begin @@ -134,7 +143,7 @@ assign ALUOps = ALUOp end LES: begin - if A < B begin + if ($signed(A) < $signed(B)) begin ALUCond = 1; end else begin @@ -144,17 +153,7 @@ assign ALUOps = ALUOp end LEQ: begin - if A <= B begin - ALUCond = 1; - end - else begin - ALUCond = 0; - end - - end - - LEQ: begin - if A <= B begin + if ($signed(A) <= $signed(B)) begin ALUCond = 1; end else begin @@ -164,7 +163,7 @@ assign ALUOps = ALUOp end GRT: begin - if A > B begin + if ($signed(A) > $signed(B)) begin ALUCond = 1; end else begin @@ -174,7 +173,7 @@ assign ALUOps = ALUOp end GEQ: begin - if A >= B begin + if ($signed(A) >= $signed(B)) begin ALUCond = 1; end else begin @@ -184,7 +183,7 @@ assign ALUOps = ALUOp end NEQ: begin - if A != B begin + if ($signed(A) != $signed(B)) begin ALUCond = 1; end else begin @@ -197,6 +196,26 @@ assign ALUOps = ALUOp ALURes = A; end + SLT: begin + if ($signed(A) < $signed(B)) begin + ALURes = 1; + end + end + + SLTU: begin + if (A < B) begin + ALURes = 1; + end + end + + MULU: begin + ALURes = A * B; + end + + DIVU: begin + ALURes = A / B; + end + endcase end endmodule \ No newline at end of file diff --git a/rtl/mips_cpu_control.v b/rtl/mips_cpu_control.v index 1bbf79b..0bac657 100644 --- a/rtl/mips_cpu_control.v +++ b/rtl/mips_cpu_control.v @@ -1,319 +1,201 @@ -/* -Instr -*0: XOR SUBU SRLV SRL SRAV SRA SLTU SLT SLLV - SLL OR MULTU MULT MTLO MTHI JR JALR DIVU - DIV AND ADDU -1: BLTZAL BLTZ BGEZAL BGEZ -2: J -3: JAL -4: BEQ -5: BNE -6: BLEZ -7: BGTZ -*9: ADDIU -10: SLTI -11: SLTIU -12: ANDI -13: ORI -14: XORI -15: LUI -32: LB -33: LH -34: LWL -*35: LW -36: LBU -37: LHU -38: LWR -40: SB -41: SH -*43: SW -*/ +module mips_cpu_control( -/* -Regdst: -00:Instr[20-16] -01:Instr[15-11] -10:2'd31 -*/ + input logic[31:0] Instr, + input logic ALUCond, + + output logic CtrlRegDst, + output logic[1:0] CtrlPC, + output logic CtrlMemRead, + output logic CtrlMemtoReg, + output logic[4:0] CtrlALUOp, + output logic[4:0] Ctrlshamt, + output logic CtrlMemWrite, + output logic CtrlALUSrc, + output logic CtrlRegWrite -/* -Memtoreg: -00: Alu output -01: Memory output -10: PC+4 output -*/ +); -//Commented signals represents dont care(x) +/* logic[5:0] op; +logic[5:0] funct; +logic[4:0] rt; */ -module mips_cpu_control{ - input logic[5:0] Instr, - input logic[5:0] rt, - output logic[1:0] Regdst, - output logic Branch, - output logic Memread, - output logic[1:0] Memtoreg, - output logic Memwrite, - output logic Alusrc, - output logic Regwrite, - output logic Jump, - ); +/* assign op = Instr[31:26]; +assign funct = Instr[5:0]; +assign rt = Instr[20:16]; */ - always_comb begin - case(Instr) - 6'd0: begin - Regdst=2'b01; - Branch=0; - Memread=0; - Memwrite=0; - Memtoreg=2'b00; - Alusrc=0; - Regwrite=1; - Jump=0; - end - 6'd1: begin - Regdst=2'b10; - Branch=1; - Memread=0; - Memwrite=0; - if(rt[5]==1)begin - Memtoreg=2'b10; - Regwrite=1; - end - Alusrc=0; - Jump=0; - end - 6'd2: begin - //Regdst=2'b; - Branch=0; - Memread=0; - //Memtoreg=; - Memwrite=0; - //Alusrc=; - Regwrite=0; - Jump=1; - end - 6'd3: begin - Regdst=2'b10; - Branch=0; - Memread=0; - Memtoreg=2'b10; - Memwrite=0; - //Alusrc=; - Regwrite=1; - Jump=1; - end - 6'd4: begin - //Regdst=2'b; - Branch=1; - Memread=0; - //Memtoreg=; - Memwrite=0; - Alusrc=0; - Regwrite=0; - Jump=0; - end - 6'd5: begin - //Regdst=2'b; - Branch=1; - Memread=0; - //Memtoreg=; - Memwrite=0; - Alusrc=0; - Regwrite=0 - Jump=0; - end - 6'd6: begin - //Regdst=2'b; - Branch=1; - Memread=0; - //Memtoreg=; - Memwrite=0; - Alusrc=0; - Regwrite=0; - Jump=0; - end - 6'd7: begin - //Regdst=2'b; - Branch=1; - Memread=0; - //Memtoreg=; - Memwrite=0; - Alusrc=0; - Regwrite=0; - Jump=0; - end - 6'd9: begin - Regdst=2'b00; - Branch=0; - Memread=0; - Memtoreg=2'b00; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd10: begin - Regdst=2'b00; - Branch=0; - Memread=0; - Memtoreg=2'b00; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd11: begin - Regdst=2'b00; - Branch=0; - Memread=0; - Memtoreg=2'b00; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd12: begin - Regdst=2'b00; - Branch=0; - Memread=0; - Memtoreg=2'b00; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd13: begin - Regdst=2'b00; - Branch=0; - Memread=0; - Memtoreg=2'b00; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd14: begin - Regdst=2'b00; - Branch=0; - Memread=0; - Memtoreg=2'b00; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd15: begin - Regdst=2'b00; - Branch=0; - Memread=0; - Memtoreg=2b'00; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd32: begin - Regdst=2'b00; - Branch=0; - Memread=1; - Memtoreg=2'b01; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd33: begin - Regdst=2'b00; - Branch=0; - Memread=1; - Memtoreg=2'b01; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd34: begin - Regdst=2'b00; - Branch=0; - Memread=1; - Memtoreg=2'b01; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd35: begin - Regdst=2'b00; - Branch=0; - Memread=1; - Memtoreg=2'b01; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd36: begin - Regdst=2'b00; - Branch=0; - Memread=1; - Memtoreg=2'b01; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd37: begin - Regdst=2'b00; - Branch=0; - Memread=1; - Memtoreg=2'b01; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd38: begin - Regdst=2'b00; - Branch=0; - Memread=1; - Memtoreg=2'b01; - Memwrite=0; - Alusrc=1; - Regwrite=1; - Jump=0; - end - 6'd40: begin - //Regdst=2'b; - Branch=0; - Memread=0; - //Memtoreg=; - Memwrite=1; - Alusrc=1; - Regwrite=0; - Jump=0; - end - 6'd41: begin - //Regdst=2'b; - Branch=0; - Memread=0; - //Memtoreg=; - Memwrite=1; - Alusrc=1; - Regwrite=0; - Jump=0; - end - 6'd43: begin - //Regdst=2'b; - Branch=0; - Memread=0; - //Memtoreg=; - Memwrite=1; - Alusrc=1; - Regwrite=0; - Jump=0; - end - endcase +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; +assign op = Instr[31:26]; + +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, + 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; +assign funct = Instr[5:0]; + +typedef enum logic[4:0]{ + BLTZ = 5'd0, + BGEZ = 5'd1, + BLTZAL = 5'd16, + BGEZAL = 5'd17 +} rt_enum; +rt_enum rt; +assign rt = Instr[20:16]; + +always_comb begin + + //CtrlRegDst logic + if(op == (ADDIU | ANDI | LB | LBU | LH | LHU | LUI | LW | LWL | LWR | ORI | SLTI | SLTIU | XORI))begin + CtrlRegDst = 0; //Write address comes from rt + end else if (op == (SPECIAL & (funct == (ADDU | AND | JALR | OR | SLL | SLLV | SLT | SLTU | SRA | SRAV | SRL | SRLV | SUBU | XOR))))begin + CtrlRegDst = 1; //Write address comes from rd + end else begin CtrlRegDst = 1'bx; end//Not all instructions are encompassed so, added incase for debug purposes + + //CtrlPC logic + if(op == (BEQ | BGTZ | BLEZ | BNE | (REGIMM & (rt == (BGEZ | BGEZAL | BLTZ | BLTZAL)))))begin + CtrlPC = 2'd1; // Branches - Jumps relative to PC + end else if(op == (J | JAL))begin + CtrlPC = 2'd2; // Jumps within 256MB Region using 26-bit immediate in J type instruction + end else if(op == (JR | JALR))begin + CtrlPC = 2'd3; // Jumps using Register. + end else begin CtrlPC = 2'd0;end // No jumps, 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. + if(op == (LB | LBU | LH | LHU | LW | LWL | LWR))begin + CtrlMemRead = 1;//Memory is read enabled + CtrlMemtoReg = 1;//write data port of memory is fed from data memory + end else if (op == (ADDIU | ANDI | ORI | SLTI | SLTIU | XORI | (SPECIAL & (funct == (ADDU | AND | DIV | DIVU | MTHI | MTLO | MULT | MULTU | OR | SLL | SLLV | SLT | SLTU | SRA | SRAV | SRL | SRLV | SUBU | XOR)))))begin + CtrlMemRead = 0;//Memory is read disabled + CtrlMemtoReg = 0;//write data port of memory if fed from ALURes + end else begin CtrlMemRead = 1'bx;end//Not all instructions are encompassed so, added incase for debug purposes + + //CtrlALUOp Logic + if(op == (ADDIU | (SPECIAL & (funct == ADDU))))begin + CtrlALUOp = 5'd0; //ADD from ALUOps + end else if (op == (ANDI | (SPECIAL & (funct == AND))))begin + CtrlALUOp = 5'd4;//AND from ALUOps + end else if (op == BEQ) begin + CtrlALUOp = 5'd13;//EQ from ALUOps + end else if (op == (REGIMM & (rt == (BGEZ | BGEZAL))))begin + CtrlALUOp = 5'd17;//GEQ from ALUOps + end else if (op == BGTZ)begin + CtrlALUOp = 5'd16;//GRT from ALUOps + end else if (op == BLEZ)begin + CtrlALUOp = 5'd15;//LEQ from ALUOps + end else if (op == (REGIMM & (rt == (BLTZ | BLTZAL))))begin + CtrlALUOp = 5'd14;//LES from ALUOps + end else if (OP == BNE)begin + CtrlALUOp = 5'd18;//NEQ from ALUOps + end else if (op == (SPECIAL & (funct == DIV)))begin + CtrlALUOp = 5'd3;//DIV from ALUOps + end else if (op == (SPECIAL & (funct == DIVU)))begin + CtrlALUOp = 5'd23;//DIVU from ALUOps + end else if (op == (LB | LBU | LH | LHU | LW | LWL | LWR | SB | SBH | SW))begin + CtrlALUOp = 5'd0;//ADD from ALUOps + end else if (op == LUI)begin + CtrlALUOp = 5'd7;//SLL from ALUOps + end else if (op == (SPECIAL & (funct == MTHI | MTLO)))begin + CtrlALUOp = 5'd19;//PAS from ALUOps + end else if (op == (SPECIAL & (funct == MULT)))begin + CtrlALUOp = 5'd2;//MUL from ALUOps + end else if (op == (SPECIAL & (funct == MULTU)))begin + CtrlALUOp = 5'd22;//MULU from ALUOps + end else if (op == (ORI | (SPECIAL & (funct == OR))))begin + CtrlALUOp = 5'd5;//OR from ALUOps + end else if (op == (SPECIAL & (funct == SLL)))begin + CtrlALUOp = 5'd7;//SLL from ALUOps + end else if (op == (SPECIAL & (funct == SLLV)))begin + CtrlALUOp = 5'd8;//SLLV from ALUOps + end else if (op == (SPECIAL & (funct == SRA)))begin + CtrlALUOp = 5'd11;//SRA from ALUOps + end else if (op == (SPECIAL & (funct == SRAV)))begin + CtrlALUOp = 5'd12;//SRAV from ALUOps + end else if (op == (SPECIAL & (funct == SRL)))begin + CtrlALUOp = 5'd9;//SRL from ALUOps + end else if (op == (SPECIAL & (funct == SRLV)))begin + CtrlALUOp = 5'd10;//SRLV from ALUOps + end else if (op == (SLTI | (SPECIAL & (funct == SLT))))begin + CtrlALUOp = 5'd20;//SLT from ALUOps + end else if (op == (SLTIU | (SPECIAL & (funct == SLTU))))begin + CtrlALUOp = 5'd21;//SLTU from ALUOps + end else if (op == (SPECIAL & (funct == SUBU)))begin + CtrlALUOp = 5'd1;//SUB from ALUOps + end else if (op == (XORI | (SPECIAL & (funct == XOR))))begin + CtrlALUOp = 5'd6;//XOR from ALUOps + end else begin + CtrlALUOp = 5'bxxxxx; end - - + + //Ctrlshamt logic + if(op == (SPECIAL & (funct == (SRA | SRL | SLL))))begin + 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 + if(op == (SB | SH | SW)begin + CtrlMemWrite = 1;//Memory is write enabled + end else begin CtrlMemWrite = 0;end//default is 0 to ensure no accidental overwriting. + + //CtrlALUSrc logic + if(op == (ADDIU | ANDI | LUI | ORI | SLTI | SLTIU | XORI | LB | LBU | LH | LHU | LW | LWL | LWR | SB | SH | 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] + end else if (op == (BEQ | BGTZ | BLEZ | BNE | (REGIMM & (rt == (BGEZ | BGEZAL | BLTZ | BLTZAL)) (SPECIAL & (funct == (ADDU | AND | DIV | DIVU | MULT | MULTU | OR | SLLV | SLT | SLTU | SRAV | SRLV | SUBU | XOR)))))begin + CtrlALUSrc = 0;///ALU Bus B is fed from rt. + end else begin CtrlALUSrc = 1'bx;end + + //CtrlRegWrite logic + if(op == (ADDIU | ANDI | LB | LBU | LH | LHU | LUI | LW | LWL | LWR | ORI | SLTI | SLTIU | XORI | (SPECIAL & (funct == (ADDU | AND | DIV | DIVU | MULT | MULTU | JALR | OR | SLL | SLLV | SLT | SLTU | SRA | SRAV | SRL | SRLV | SUBU | XOR)))))begin + CtrlRegWrite = 1;//The Registers are Write Enabled + end else begin CtrlRegWrite = 0;end // The Registers are Write Disabled + +end endmodule