MIPS multi cycle CPU design and Implementation (40 instructions)

##No abnormal instructions (40 in total)
###1. Arithmetic instruction

  1. ADDIU
  2. ADDU
  3. SUBU
  4. MULU
  5. DIVU
  6. MUL
  7. DIV
    ###2. Logic instruction
  8. AND
  9. ANDI
  10. NOR
  11. OR
  12. ORI
  13. XOR
  14. XORI
  15. LUI
    ###3. Shift instruction
  16. SLLV
  17. SLL
  18. SRAV
  19. SRA
  20. SLT
  21. SLTI
  22. SLTIU
  23. SLTU
  24. SRL
  25. SRLV
    ###4. Branch jump instruction
  26. J
  27. JAL
  28. JR
  29. BEQ
  30. BNE
  31. BGEZ
  32. BGTZ
  33. BLEZ
  34. BLTZ
    ###5. Read write instruction
  35. LW
  36. SW
    ###6. Data movement
    1.MFLO
    2.MFHI
    3.MTLO
    4.MTHI

##Modules included

  1. mips module is a CPU, which only contains reset signal rst and clock signal clk. It is internally composed of PC, NPC, DM, IM, EXT, ALU, IR, Ctrl and other modules, as well as some multiplexers and buffers.
  2. PC (program counter): PC is an instruction counter. Its main function is to output the current instruction address and save the next instruction address. After reset, the PC points to 0x0000_3000, here is the address of the first instruction.
  3. NPC(NextPC computing unit): NPC is the next instruction counter. Its main function is to calculate the address of the next instruction. NPCOp[1:0] determines how to calculate NPC.
  4. Regfile (general register group, also known as register file and register file): the main function of RF is to save register file and support access to general registers.
  5. ALU (arithmetic logic unit): the main function of ALU is to complete the arithmetic logic calculation of input data, including addition, subtraction, bitwise OR operation, and judge whether the two operands are equal.
  6. EXT (extension unit): the main function of EXT is to expand 16 bit data into 32-bit data.
  7. Imem (instruction memory): IM is the instruction memory. Its main function is to read and write the 32-bit data corresponding to the addr address according to the read control signal DMWr.
  8. IR (instruction register): the main function of IR is to buffer the instructions from IM.
  9. DMEM (data memory): DM is a data memory. Its main function is to read and write 32-bit data corresponding to addr address according to the read-write control signal DMWr.
  10. MUX (data selector): the main function is multiplexer. mux. The V file contains four multiplexers: one out of two, one out of four, one out of eight and one out of sixteen. When instantiating a multiplexer, you can use # (xxx) to instantiate a multiplexer with a bit width of XXX.
  11. ICUT: the main function is to divide 32-bit instructions into several parts and transfer them to different places.
  12. MDU: unit for multiplication and division
  13. Define: macro define all names.

##Module
##1.PC
####Port description

Signal namedirectiondescribe
ClkIclock signal
RstIReset signal
1: Set PC as initial value
0: invalid
PCwrIPC read / write enable terminal signal
1: Can write
0: not writable
PCin[31:0]IAddress of the next instruction
PCout[31:0]OAddress of the current instruction (mapping)

####Function definition

Serial numberfunctiondescribe
1resetSet PC as initial value
2countWhen the PCWR is valid and the clock rising edge, the PC updates to the NPC output

##2.IMEM
####Port description

Signal namedirectiondescribe
AddrIAddress of the current instruction
IoutOCurrent instruction

####Function definition

Serial numberfunctiondescribe
1Fetch instructionOutput the current instruction represented by Addr address

##3.IR
####Port description

Signal namedirectiondescribe
clkIclock signal
IRinIInstructions from IMEM
IRwrIControl the reading and writing of instruction register
1: Can write
0: not writable
IRoutOCurrent instruction

####Function definition

Serial numberfunctiondescribe
1bufferBuffering instructions from IMEM

##4.Regfile
####Port description

Signal namedirectiondescribe
ClkIclock signal
rstIreset signal
Ra[4:0]I5-bit address input signal to read the contents of the register to Raout
Rb[4:0]I5-bit address input signal to read the contents of the register to Rbout
Rw[4:0]IThe 5-bit address input signal takes the register as the target register
Wd[31:0]I32-bit data input signal
IRwrIControl IR reading and writing
1: Writable
0: not writable
RaoutOOutputs 32-bit data in the register specified by Raout
RboutOOutputs 32-bit data in the register specified by Rbout

####Function definition

Serial numberfunctiondescribe
1Read dataRead out the data of 1 in the register corresponding to Ra and Rb addresses to Raout and Rbout
2Write dataWhen RFwr is valid and the rising edge of the clock comes, write the data in Wd to the register corresponding to Rw

##5.ALU
####Port description

Signal namedirectiondescribe
A[31:0]IOperand A
B[31:0]IOperand B
ALUop[3:0]ISee menu for details
Out[31:0]OALU output result is 32-bit data

####Function definition

Serial numberfunctiondescribe
1Addition operation0000:Out = A + B
2Subtraction operation0001:Out = A - B
3And operation0010:Out = A & B
4Or non operation0011:Out = ~(A | B)
5XOR operation0100:Out = A ^ B
6Or operation0101:Out = A | B
7Logical shift left0110:Out = B << A[10:6]
8Logical shift right0111:Out = B >> A[10:6]
9Arithmetic shift right1000:Out = Signed(B) >>> A[10:6]
10Less than 1 (signed)1001:Out = Signed(A) < Signed(B) ? 1 : 0
11Less than 1 (unsigned)1010:Out = A < B ? 1 : 0
12Shift the A operand to the left by 16 bits (LUI)1011:Out = A << 16

##6.DMEM
####Port description

Signal namedirectiondescribe
DMwrIData memory write enable signal
1: Writable
0: invalid
Addr[31:0]I32-bit address input, specifying read or write address data
Imm[31:0]IAn expanded 32-bit immediate used to calculate the address
Din[31:0]I32 is data input
Dout[31:0]O32 is the data output, which is specified by the calculated address

####Function definition

Serial numberfunctiondescribe
1Read dataRead the data specified by Addr to Dout
2Calculate addressCalculate the address added by Addr and immediate
3Write dataWhen DMwr is valid and the clock rises, write the input data Din to the address specified by the calculation result

##7.EXT
####Port description

Signal namedirectiondescribe
EXTinI16 bit input data
EXTopIExpansion mode selection signal
0: symbol extension
1: Zero extension
EXToutOOutput data extended to 32 bits

####Function definition

Serial numberfunctiondescribe
1Symbol extensionThe 16 bit input data is symbol extended to output 32-bit data
2Zero extensionZero extension of 16 bit input data to output 32-bit data

##8.NPC
####Port description

Signal namedirectiondescribe
Immj[25:0]IMiddle 26 bits of jump instruction destination address
ImmB[31:0]IOffset 00 of branch instruction (added when branch is selected)
PC[31:0]IBranch instruction base address
CmpAIThe first comparison number of the branch instruction, which is used as the address when the instruction is Jump
CmpBISecond comparison number of branch instructions
is_JRIJudge whether it is JR instruction alone
NPCop[2:0]ISee menu for details
JORBISelect Jump and Branch
0:Jump
1:Branch
NPCout[31:0]ONext instruction address selected from Jump and Branch
NextPCONormal PC + 4

####Function definition

Serial numberfunctiondescribe
1Calculate branch addressFirst expand the immediate number and calculate the branch address according to the comparison results:
000:BEQ
001:BNE
010:BLEZ
011:BGTZ
100:BLTZ
101:BGEZ
2Calculate jump addressThe jump address is calculated by bit splicing

##9.MDU
####Port description

Signal namedirectiondescribe
clkIclock signal
rstIreset signal
MDUresselIRead register selection signal
0: read LO register
1: Read HI register
A[31:0]IThe first value involved in the calculation
B[31:0]IThe second value involved in the calculation
MDUcoacIMDU enable end
MDUop[2:0]IMDU function selection signal
000:{HI, LO} = $signed(A) * $signed(B)
001:{HI, LO} = A * B
010:LO = A / B, HI = A % B
011:LO = $signed(A) / $signed(B, HI = $signed(A) % $signed(B)
100:LO = A
101:HI = A
MDUout[31:0]OOutput calculation results

####Function definition

Serial numberfunctiondescribe
1Unsigned multiplication{HI, LO} = A * B
2Signed multiplication{HI, LO} = $signed(A) * $signed(B)
3Unsigned DivisionLO = A / B, HI = A % B
4Signed DivisionLO = $signed(A) / $signed(B, HI = $signed(A) % $signed(B)
5Write LO registerLO = A
6Read LO registerMDUout = LO
7Write HI registerHI = A
8Read HI registerMDUout = HI

##10.ICUT
####Port description

Signal namedirectiondescribe
Ins[31:0]IIncoming 32-bit instruction
op[5:0]Ors register
rt[4:0]Ort register
rd[4:0]Ord register
rs[4:0]OOperation code
sa[4:0]ODisplacement
Imm[15:0]OImmediate number
Addr[25:0]OJ instruction address fragment
Insout[31:0]O32-bit instruction passed to control

####Function definition

Serial numberfunctiondescribe
1divisionThe 32-bit instruction is divided into segments and transmitted to each port

##11.Control
####Port description

Signal namedirectiondescribe
RstIReset
ClkIclock signal
InsI32-bit instruction for decoding
PCwrOControls whether the PC is writable
0: not writable
1: Writable
IRwrOControls whether the IR is writable
0: not writable
1: Writable
Regin[1:0]OSelect the address to write to Regfile
00: write to rt register
01: write to rd register
10: Write to 1F register
RFwrOControls whether Regfile can be written
0: not writable
1: Writable
SEL_AOSelect A operand
0: from Regfile
1: From EXT
SEL_BOSelect B operand
0: from Regfile
1: From EXT
ALUop[3:0]OControl which operation ALU selects. See ALU function description for details
JORBOControl NPCout to choose Jump or Branch
0:Jump
1:Branch
NPCop[2:0]OSelect the type of Branch. See NPC function description for details
MDUresselORead register selection signal
0: read LO register
1: Read HI register
MDUop[2:0]OSelect the function of MDU. See the function description for details
DMwrOControls whether DM is writable
0: not writable
1: Writable
EXTop[1:0]OSee the menu for the control extension mode
WBsel[1:0]OSelect where the data written back to the register comes from
NPCOselOSelect whether to execute the next branch normally or jump to the branch
is_JRODetermine whether CMPA is used as the address of JR
MDUcoacOMDU enable signal
1: Can be calculated
0: calculation is not allowed

##CPU data path diagram

##Status corresponding signal





##Module code implementation
###1.ALU

module ALU(
    input [31:0]A,          // Operand A
    input [31:0]B,          // Operand B
    input [3:0]ALUop,       // Select function
    output reg [31:0]Out        // Output results
);

    always @(*) begin
        case(ALUop)
            4'b0000: Out = A + B;
            4'b0001: Out = A - B;
            4'b0010: Out = A & B;
            4'b0011: Out = A | B;
            4'b0100: Out = A ^ B;                               // XOR
            4'b0101: Out = ~(A | B);                            // NOR
            4'b0110: Out = B << A[10:6];                        // SLL
            4'b0111: Out = B >> A[10:6];                        // SRL
            4'b1000: Out = $signed(B) >>> A[10:6];              // SRA
            4'b1001: Out = ($signed(A) < $signed(B)) ? 1 : 0;   // SLT and SLTI
            4'b1010: Out = (A < B) ? 1 : 0;                     // SLTU and SLTIU
            4'b1011: Out = A << 16;                             // LUI
        endcase 
    end

endmodule

###2.Control

`include "define.v"

module Control(
    input clk,                  // clock signal
    input rst,                  // reset signal 
    input [31:0]Ins,            // Incoming 32-bit instruction
    output reg PCwr,                // Controls whether the PC can write
    output reg IRwr,                // Controls whether the IR can be written
    output reg[1:0]Regin,       // Enter Regfile's selection
    output reg RFwr,                // Controls whether Regfile can be written
    output reg SEL_A,               // A operand selected into ALU
    output reg SEL_B,               // B operand selected into ALU
    output reg[3:0]ALUop,          // ALU operation
    output reg JORB,                // Judge whether it's Jump or Branch
    output reg[2:0]NPCop,          // Judge what kind of Branch it is
    output reg MDUressel,           // Select HI or LO
    output reg[2:0]MDUop,          // Operation of MDU
    output reg DMwr,                // DM enable signal
    output reg[1:0]EXTop,          // What kind of extension is it
    output reg[1:0]WBsel,          // Where does the data written back come from
    output reg NPCOsel,             // Select the results from NPC (jump or normal)
    output reg is_JR,               // To judge whether it is a JR, you need to use CmpA as the address
    output reg Dtype,               // Judge whether DM is read or write
    output reg MDUcoac              // MDU enable signal
);

    parameter  IF = 3'b000;    // Finger taking
    parameter  ID = 3'b001;    // decoding
    parameter  EXE = 3'b010;   // implement
    parameter  MEM = 3'b011;   // read
    parameter  WB = 3'b100;    // Write back


    reg[2:0] CurrentState;     // current state
    reg[2:0] NextState;        // Next status

    reg[5:0] Op;
    /*Sequential logic*/
    always @(posedge clk,posedge rst) begin
        if(rst) 
            CurrentState <= IF;
        else
            CurrentState <= NextState;
    end
    
    always @(*) begin
        case(CurrentState)
            IF: begin
                NextState = ID;
                PCwr = 1'b0;
                IRwr = 1'b1;
                RFwr = 1'b0;
                DMwr = 1'b0;
                NPCOsel = 1'b0;
            end

            ID: begin
                JORB = ~(Ins[`op] == `OP_J || Ins[`op] == `OP_JAL || (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_JR));
                NPCOsel = (Ins[`op] == `OP_J || Ins[`op] == `OP_JAL || (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_JR));
                //$display("NPCOsel = %8X", NPCOsel);
                is_JR = (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_JR) ? 1'b1 : 1'b0;

                case(Ins[`op])
                    `OP_J: begin
                        NextState = IF;
                        PCwr = 1'b1;
                        IRwr = 1'b0;
                        RFwr = 1'b0;
                        DMwr = 1'b0;
                    end 

                    `OP_BEQ,`OP_BGEZ,`OP_BGTZ,
                    `OP_BLEZ,`OP_BLTZ,`OP_BNE: begin
                        NextState = EXE;
                        PCwr = 1'b0;
                        RFwr = 1'b0;
                        DMwr = 1'b0;
                        IRwr = 1'b0;
                    end

                    `OP_JAL: begin
                        NextState = IF;
                        PCwr = 1'b1;
                        IRwr = 1'b0;
                        RFwr = 1'b1;
                        DMwr = 1'b0;
                        Regin = 2'b10;
                        WBsel = 2'b11;
                    end

                    `OP_R:
                        case(Ins[`funct])
                            `FUNCT_JR: begin
                                NextState = IF;
                                PCwr = 1'b1;
                                IRwr = 1'b0;
                                RFwr = 1'b0;
                                DMwr = 1'b0;
                            end
                            default: begin
                                NextState = EXE;
                                PCwr = 1'b1;       // To make PC + 4 every time
                                RFwr = 1'b0;
                                DMwr = 1'b0;
                                IRwr = 1'b0;
                                MDUcoac = 1'b0; 
                            end
                        endcase
                    default: begin
                        NextState = EXE;
                        PCwr = 1'b1;
                        RFwr = 1'b0;
                        DMwr = 1'b0;
                        IRwr = 1'b0;
                    end
                endcase
            end

            EXE: begin
                is_JR = 1'b0;

                Regin = 
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_DIV) ? 2'b00 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_DIVU) ? 2'b00 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MULT) ? 2'b00 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MULTU) ? 2'b00 :
                2'b01;

                SEL_A = 
                (Ins[`op] == `OP_LUI) ? 1'b1 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLL) ? 1'b1 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRL) ? 1'b1 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRA) ? 1'b1 :
                1'b0;

                SEL_B = 
                (Ins[`op] == `OP_ADDIU || Ins[`op] == `OP_ANDI || Ins[`op] == `OP_ORI
                || Ins[`op] == `OP_XORI || Ins[`op] == `OP_SLTI || Ins[`op] == `OP_SLTIU);

                ALUop = 
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_ADDU) ? 4'b0000 :
                (Ins[`op] == `OP_ADDIU) ? 4'b0000 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_AND) ? 4'b0010 :
                (Ins[`op] == `OP_ANDI) ? 4'b0010 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_OR) ? 4'b0011 :
                (Ins[`op] == `OP_ORI) ? 4'b0011 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_XOR) ? 4'b0100 :
                (Ins[`op] == `OP_XORI) ? 4'b0100 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLL) ? 4'b0110 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLLV) ? 4'b0110 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRA) ? 4'b1000 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRAV) ? 4'b1000 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLT) ? 4'b1001 :
                (Ins[`op] == `OP_SLTI) ? 4'b1001 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLTU) ? 4'b1010 :
                (Ins[`op] == `OP_SLTIU) ? 4'b1010 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRL) ? 4'b0111 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRLV) ? 4'b0111 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SUBU) ? 4'b0001 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_NOR) ? 4'b0101 :
                (Ins[`op] == `OP_LUI) ? 4'b1011 :
                4'b1111;

                JORB = 
                (Ins[`op] == `OP_BEQ) ? 1'b1 :
                (Ins[`op] == `OP_BNE) ? 1'b1 :
                (Ins[`op] == `OP_BLEZ && Ins[`rt] == `RT_BLEZ) ? 1'b1 :
                (Ins[`op] == `OP_BGTZ && Ins[`rt] == `RT_BGTZ) ? 1'b1 :
                (Ins[`op] == `OP_BLTZ && Ins[`rt] == `RT_BLTZ) ? 1'b1 :
                (Ins[`op] == `OP_BGEZ && Ins[`rt] == `RT_BGEZ) ? 1'b1 :
                1'b0;

                NPCop = 
                (Ins[`op] == `OP_BEQ) ? 3'b000 :
                (Ins[`op] == `OP_BNE) ? 3'b001 :
                (Ins[`op] == `OP_BLEZ && Ins[`rt] == `RT_BLEZ) ? 3'b010 :
                (Ins[`op] == `OP_BGTZ && Ins[`rt] == `RT_BGTZ) ? 3'b011 :
                (Ins[`op] == `OP_BLTZ && Ins[`rt] == `RT_BLTZ) ? 3'b100 :
                (Ins[`op] == `OP_BGEZ && Ins[`rt] == `RT_BGEZ) ? 3'b101 :
                3'b111;

                MDUop = 
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MULT) ? 3'b000 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MULTU) ? 3'b001 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_DIV) ? 3'b011 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_DIVU) ? 3'b010 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MTLO) ? 3'b100 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MTHI) ? 3'b101 :
                3'b111;

                EXTop = 
                (Ins[`op] == `OP_ADDIU) ? 2'b00 :
                (Ins[`op] == `OP_ANDI) ? 2'b01 :
                (Ins[`op] == `OP_ORI) ? 2'b01 :
                (Ins[`op] == `OP_XORI) ? 2'b01 :
                (Ins[`op] == `OP_LUI) ? 2'b01 :
                2'b00;

                NPCOsel = 
                (Ins[`op] == `OP_BEQ) ? 1'b1 :
                (Ins[`op] == `OP_BNE) ? 1'b1 :
                (Ins[`op] == `OP_BLEZ && Ins[`rt] == `RT_BLEZ) ? 1'b1 :
                (Ins[`op] == `OP_BGTZ && Ins[`rt] == `RT_BGTZ) ? 1'b1 :
                (Ins[`op] == `OP_BLTZ && Ins[`rt] == `RT_BLTZ) ? 1'b1 :
                (Ins[`op] == `OP_BGEZ && Ins[`rt] == `RT_BGEZ) ? 1'b1 :
                1'b0;

                MDUcoac = 
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_DIV) ? 1'b1 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_DIVU) ? 1'b1 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MULT) ? 1'b1 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MULTU) ? 1'b1 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MTLO) ? 1'b1 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MTHI) ? 1'b1 :
                1'b0;

                case(Ins[`op])
                    `OP_R,`OP_ADDI,`OP_ADDIU,
                    `OP_ANDI,`OP_ORI,`OP_XORI,`OP_SLTI,`OP_SLTIU,`OP_LUI: begin
                        
                        if (Ins[`funct] == `FUNCT_DIV || Ins[`funct] == `FUNCT_DIVU || 
                            Ins[`funct] == `FUNCT_MULT || Ins[`funct] == `FUNCT_MULTU ||
                            Ins[`funct] == `FUNCT_MTLO || Ins[`funct] == `FUNCT_MTHI) begin
                            NextState = IF;
                            PCwr = 1'b0;
                            RFwr = 1'b0;
                            DMwr = 1'b0;
                            IRwr = 1'b0;
                        end
                        else begin
                            NextState = WB;
                            PCwr = 1'b0;
                            RFwr = 1'b0;
                            DMwr = 1'b0;
                            IRwr = 1'b0;
                        end
                    end

                    `OP_BEQ,`OP_BGEZ,`OP_BGTZ,
                    `OP_BLEZ,`OP_BLTZ,`OP_BNE: begin
                        NextState = IF;
                        PCwr = 1'b1;
                        RFwr = 1'b0;
                        DMwr = 1'b0;
                        IRwr = 1'b0;
                    end

                    default: begin
                        NextState = MEM;
                        PCwr = 1'b0;
                        RFwr = 1'b0;
                        DMwr = 1'b0;
                        IRwr = 1'b0;
                    end
                endcase
            end

            MEM: begin
                case(Ins[`op])
                    `OP_LW: begin
                        NextState = WB;
                        PCwr = 1'b0;
                        RFwr = 1'b1;
                        DMwr = 1'b0;
                        IRwr = 1'b0;
                        //Dtype = 1'b0;
                    end

                    default: begin
                        NextState = IF;
                        PCwr = 1'b0;
                        RFwr = 1'b0;
                        DMwr = 1'b1;
                        IRwr = 1'b0;
                        //Dtype = 1'b1;
                    end
                endcase
            end

            WB: begin
                Regin = 
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_ADDU) ? 2'b01 : 
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SUBU) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_AND) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_OR) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_XOR) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_NOR) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLL) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLLV) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRL) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRLV) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRA) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SRAV) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLT) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_SLTU) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MFLO) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MFHI) ? 2'b01 :
                (Ins[`op] == `OP_ADDIU) ? 2'b00 :
                (Ins[`op] == `OP_ANDI) ? 2'b00 :
                (Ins[`op] == `OP_ORI) ? 2'b00 :
                (Ins[`op] == `OP_XORI) ? 2'b00 :
                (Ins[`op] == `OP_LUI) ? 2'b00 :
                (Ins[`op] == `OP_SLTI) ? 2'b00 :
                (Ins[`op] == `OP_SLTIU) ? 2'b00 :
                (Ins[`op] == `OP_LW) ? 2'b00 :
                0;


                MDUressel = (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MFHI) ? 1'b1 : 1'b0;

                WBsel = 
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MFLO) ? 2'b01 :
                (Ins[`op] == `OP_R && Ins[`funct] == `FUNCT_MFHI) ? 2'b01 :
                (Ins[`op] == `OP_LW) ? 2'b10 :
                2'b00;

                NextState = IF;
                PCwr = 1'b0;
                RFwr = 1'b1;
                DMwr = 1'b0;
                IRwr = 1'b0;
            end
        endcase
    end

endmodule

###3.define

/*Instruction segmentation*/
`define op 31:26
`define funct 5:0
`define imm26 25:0
`define imm16 15:0
`define rs 25:21
`define rt 20:16
`define rd 15:11
`define s 10:6

/*ALU operation*/
`define ALUop_ADD     4'b0000
`define ALUop_SUB     4'b0001
`define ALUop_AND     4'b0010
`define ALUop_OR      4'b0011
`define ALUop_XOR     4'b0100
`define ALUop_NOR     4'b0101
`define ALUop_SLL     4'b0110
`define ALUop_SRL     4'b0111
`define ALUop_SRA     4'b1000
`define ALUop_SLT     4'b1001
`define ALUop_SLTU    4'b1010
`define ALUop_LUI     4'b1011

/*EXTop*/
`define EXT_SIGN      2'b00
`define EXT_ZERO      2'b01

/******* OP Operation code*******/
`define OP_R    6'b000000
/******* Store read instruction*******/
`define OP_LW   6'b100011
`define OP_LUI  6'b001111
`define OP_SW   6'b101011
/*******     I TYPE      *******/
`define OP_ADDI 6'b001000
`define OP_ADDIU 6'b001001
`define OP_ANDI 6'b001100
`define OP_ORI  6'b001101
`define OP_SLTI 6'b001010
`define OP_SLTIU 6'b001011
`define OP_XORI 6'b001110
/*******   BRANCH TYPE   *******/
`define OP_BEQ  6'b000100
`define OP_BGEZ 6'b000001
`define OP_BGTZ 6'b000111
`define OP_BLEZ 6'b000110
`define OP_BLTZ 6'b000001
`define OP_BNE  6'b000101
/*******     J TYPE      *******/
`define OP_J    6'b000010
`define OP_JAL  6'b000011


//Function code
`define FUNCT_ADD     6'b100000
`define FUNCT_SUB     6'b100010
`define FUNCT_ADDU    6'b100001
`define FUNCT_SUBU    6'b100011
`define FUNCT_AND     6'b100100
`define FUNCT_OR      6'b100101
`define FUNCT_NOR     6'b100111
`define FUNCT_XOR     6'b100110
`define FUNCT_SLL     6'b000000
`define FUNCT_SLLV    6'b000100
`define FUNCT_SRL     6'b000010
`define FUNCT_SRLV    6'b000110
`define FUNCT_SRA     6'b000011
`define FUNCT_SRAV    6'b000111
`define FUNCT_SLT     6'b101010
`define FUNCT_SLTU    6'b101011
`define FUNCT_JALR    6'b001001
`define FUNCT_JR      6'b001000
`define FUNCT_MULT    6'b011000
`define FUNCT_MULTU   6'b011001
`define FUNCT_DIV     6'b011010
`define FUNCT_DIVU    6'b011011
`define FUNCT_MFHI    6'b010000
`define FUNCT_MFLO    6'b010010
`define FUNCT_MTHI    6'b010001
`define FUNCT_MTLO    6'b010011
//B_type_opcode
`define RT_BGEZ    5'b00001
`define RT_BGTZ    5'b00000
`define RT_BLEZ    5'b00000
`define RT_BLTZ    5'b00000

###4.DMEM

module DMEM(
    input clk,                  // clock signal
    input DMwr,                 // DM write enable signal
    input [31:0]Din,            // Data to be written to DM
    input [31:0]Imm,            // The extended immediate number used to calculate the address
    input [31:0]Addr,           // The content of rs used to calculate the address
    output reg[31:0]Dout        // Data output from DM
);

    reg [31:0] RAM[1023:0];

    integer i;

    initial begin  // Initialize all memory cells initially
        for (i = 0; i < 1023; i = i + 1) RAM[i] = 32'b0;
    end

    always @(posedge clk) begin
        if (DMwr) begin
            RAM[Imm + Addr[11:2]] = Din;  // Write with mapped address
            //$display("%H",RAM[Addr[11:2]]);
        end
        else begin
            Dout = RAM[Imm + Addr[11:2]];  // Using mapped address readout
            //$display("%H",RAM[Addr[11:2]]);
        end
    end

endmodule

###5.EXT

module EXT(
    input [15:0] EXTin,    // 16 bit immediate that needs to be extended
    input EXTop,           // operation
    output reg[31:0]EXTout    // Extended 32-bit output
);

    always @(*) begin
        if (EXTop) begin       // Zero extension
            EXTout = EXTin;
        end
        else EXTout = $signed(EXTin);    // Symbol extension
    end

endmodule

###6.ICUT

module ICUT(
    input [31:0]Ins,
    output reg[4:0]rs,          // Incoming rs port
    output reg[4:0]rt,          // Incoming rt port
    output reg[4:0]rd,          // Incoming rd port
    output reg[15:0]Imm,        // Imm is passed into EXT
    output reg[25:0]Addr,       // Address fragment passed into NPC
    output reg[31:0]Insout      // Without segmentation, it is directly sent to Control for decoding
);

    initial begin
        rs = 5'b00000;
        rt = 5'b00000;
        rd = 5'b00000;
    end

    always @(Ins) begin
        rs = Ins[25:21];
        rt = Ins[20:16];
        rd = Ins[15:11];
        Imm = Ins[15:0];
        Addr = Ins[25:0];
        Insout = Ins;
    end

endmodule

###7.IMEM

module IMEM(
    input [31:0]Addr,
    output reg [31:0]Iout
);

    reg [31:0] IM [1023:0];

    initial
        $readmemh("F:/MIPS_MULTI_CYCLE_CPU/test_app/test_12.txt", IM);

    always@(*) begin
        Iout <= IM[Addr[11:2]];
    end

endmodule

###8.IR

module IR(
    input clk,
    input IRwr,
    input [31:0]IRin,
    output reg [31:0]IRout
);

    initial
        IRout = 0;

    always @(posedge clk) begin
        if (IRwr) begin
            IRout <= IRin;
        end
    end

endmodule

###9.MDU

module MDU(
    input clk,              // clock signal
    input rst,              // reset signal 
    input [31:0]A,          // Operand A
    input [31:0]B,          // Operand B
    input MDUressel,        // Result selection (HI/LO)
    input MDUcoac,          // MUD enable end
    input [2:0]MDUop,       // Operation selection
    output [31:0]MDUout     // Output results
);

    reg [31:0]HI;
    reg [31:0]LO;

    assign MDUout = (MDUressel == 0) ? LO : HI;

    always @(posedge clk) begin
        if (rst) begin
            HI = 0;
            LO = 0;
        end
        else begin
            if (MDUcoac) begin
                case(MDUop)
                    3'b000:  {HI,LO} = $signed(A) * $signed(B);
                    3'b001:  {HI,LO} = A * B;
                    3'b010:  if(B != 0) begin
                        LO = $signed(A) / $signed(B);
                        HI = $signed(A) % $signed(B);
                    end
                    3'b011:  if(B != 0) begin
                        LO = A / B;
                        HI = A % B;
                    end
                    3'b100: begin 
                        LO = A;
                    end
                    3'b101: begin
                        HI = A;
                    end 
                endcase
            end
        end
    end

endmodule

###10.mips

`timescale 1ns / 1ps
`include "define.v"
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/07/02 14:26:18
// Design Name: 
// Module Name: mips
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mips(
    input clk,
    input rst
);
    //Wire network part
    // PC module
    wire PCwr;
    wire [31:0]PCin;
    wire [31:0]PCout;

    // IMEM module
    wire [31:0]Iout;

    // Extender module
    wire EXTop;

    // IR module
    wire [31:0]IRout;
    wire IRwr;

    // ICUT module
    wire [4:0]rs;
    wire [4:0]rt;
    wire [4:0]rd;
    wire [15:0]Imm;
    wire [25:0]OutAddr;
    wire [31:0]Insout;

    // Data selector between ICUT and RF
    wire [1:0]Regin;
    wire [4:0]CUT_MUX_RF_out;

    // Regfile module
    wire [31:0]Wd;
    wire RFwr;
    wire [31:0]Raout;
    wire [31:0]Rbout;

    // NPC module
    wire JORB;
    wire is_JR;
    wire [2:0]NPCop;
    wire [31:0]NextPC;
    wire [31:0]NPCout;

    // Data selector between NPC and PC
    wire NPCOsel;

    // Operand A selector
    wire [31:0]SEL_A_out;
    wire [31:0]EXTout;
    wire Sel_A;

    // Operand B selector
    wire [31:0]SEL_B_out;
    wire Sel_B;

    // ALU module
    wire [3:0]ALUop;
    wire [31:0]ALUout;

    //  Data memory module
    wire DMwr;
    wire Dtype;
    wire [31:0]Dout;

    // Multiplier divider unit
    wire MDUressel;
    wire MDUcoac;
    wire [2:0]MDUop;
    wire [31:0]MDUout;

    // Selector for write back register
    wire [1:0]WBsel;

    

    // module instances 
    PC U_PC(.clk(clk), .rst(rst), .PCwr(PCwr), .PCin(PCin), .PCout(PCout));
    IMEM U_IMEM(.Addr(PCout), .Iout(Iout));
    EXT U_EXT(.EXTin(Imm), .EXTop(EXTop), .EXTout(EXTout));
    IR U_IR(.clk(clk), .IRwr(IRwr), .IRin(Iout), .IRout(IRout));
    ICUT U_ICUT(.Ins(IRout), .rs(rs), .rt(rt), .rd(rd), .Imm(Imm), .Addr(OutAddr), .Insout(Insout));
    MUX4#(5) CUT_MUX_RF(.In0(rt), .In1(rd), .In2(31), .Op(Regin), .Out(CUT_MUX_RF_out));
    Regfile U_Regfile(.clk(clk), .rst(rst), .Ra(rs), .Rb(rt), .Rw(CUT_MUX_RF_out), .Wd(Wd), .RFwr(RFwr), .Raout(Raout), .Rbout(Rbout));
    NPC U_NPC(.Immj(OutAddr), .ImmB(EXTout), .PC(PCout), .CmpA(Raout), .CmpB(Rbout), .is_JR(is_JR), .NPCop(NPCop), .JORB(JORB), .NPCout(NPCout), .NextPC(NextPC));
    MUX2 NPC_TO_PC(.In0(NextPC), .In1(NPCout), .Op(NPCOsel), .Out(PCin));
    MUX2 SEL_A(.In0(Raout), .In1(EXTout), .Op(Sel_A), .Out(SEL_A_out));
    MUX2 SEL_B(.In0(Rbout), .In1(EXTout), .Op(Sel_B), .Out(SEL_B_out));
    ALU U_ALU(.A(SEL_A_out), .B(SEL_B_out), .ALUop(ALUop), .Out(ALUout));
    DMEM U_DMEM(.clk(clk), .DMwr(DMwr), .Din(Rbout), .Imm(EXTout), .Addr(Raout), .Dout(Dout));
    MDU U_MDU(.clk(clk), .rst(rst), .A(Raout), .B(Rbout), .MDUressel(MDUressel), .MDUcoac(MDUcoac), .MDUop(MDUop), .MDUout(MDUout));
    MUX4 WB_MUX(.In0(ALUout), .In1(MDUout), .In2(Dout), .In3(NextPC), .Op(WBsel), .Out(Wd));
    Control U_Control(.clk(clk), .rst(rst), .Ins(Insout), .PCwr(PCwr), .IRwr(IRwr), .Regin(Regin), .RFwr(RFwr),
                      .SEL_A(Sel_A), .SEL_B(Sel_B), .ALUop(ALUop), .JORB(JORB), .NPCop(NPCop), .MDUressel(MDUressel), 
                      .MDUop(MDUop), .DMwr(DMwr), .EXTop(EXTop), .WBsel(WBsel), .NPCOsel(NPCOsel), .is_JR(is_JR), 
                      .Dtype(Dtype), .MDUcoac(MDUcoac));
endmodule

###11.MUX

module MUX2
#(parameter width = 32)(
    input [width-1:0] In0,
    input [width-1:0] In1,
    input Op,
    output reg [width-1:0] Out
    );
    
    

    always @(*) begin
        case (Op)
            1'b0: Out = In0;
            1'b1: Out = In1;
        endcase
    end

endmodule


module MUX4
#(parameter width = 32)(
    input [width-1:0] In0,
    input [width-1:0] In1,
    input [width-1:0] In2,
    input [width-1:0] In3,
    input [1:0] Op,
    output reg [width-1:0] Out
    );
    
    

    always @(*) begin
        case (Op)
            2'b00: Out = In0;
            2'b01: Out = In1;
            2'b10: Out = In2;
            2'b11: Out = In3;
        endcase
    end

endmodule


module MUX8
#(parameter width = 32)(
    input [width-1:0] In0,
    input [width-1:0] In1,
    input [width-1:0] In2,
    input [width-1:0] In3,
    input [width-1:0] In4,
    input [width-1:0] In5,
    input [width-1:0] In6,
    input [width-1:0] In7,
    input [2:0] Op,
    output reg [width-1:0] Out
    );
    

    always @(*) begin
        case (Op)
            3'b000: Out = In0;
            3'b001: Out = In1;
            3'b010: Out = In2;
            3'b011: Out = In3;
            3'b100: Out = In4;
            3'b101: Out = In5;
            3'b110: Out = In6;
            3'b111: Out = In7;
        endcase
    end

endmodule

###12.NPC

module NPC(
    input [25:0]Immj,           // Branch instruction immediate
    input [31:0]ImmB,           // Jump instruction immediate (offset)
    input [31:0]PC,             // Base address
    input [31:0]CmpA,           // Branch comparison number A
    input [31:0]CmpB,           // Branch comparison number B
    input [2:0]NPCop,           // Select branch
    input is_JR,                // Judge whether it is JR alone
    input JORB,                 // Select whether the output is Jump or Branch
    output reg [31:0]NPCout,    // Next instruction address selected by Jump and Branch
    output [31:0]NextPC         // PC + 4 under normal conditions
);

    assign NextPC = PC + 4;

    always @(*) begin
        if (JORB) begin  // JORB is 1 executive Branch
            case(NPCop)
                3'b000: NPCout = ($signed(CmpA) == $signed(CmpB)) ? (PC + (ImmB << 2) + 4) : (PC + 4);       // BEQ
                3'b001: NPCout = ($signed(CmpA) != $signed(CmpB)) ? (PC + (ImmB << 2) + 4) : (PC + 4);       // BNE
                3'b010: NPCout = ($signed(CmpA) <= 0) ? (PC + (ImmB << 2) + 4) : (PC + 4);                   // BLEZ
                3'b011: NPCout = ($signed(CmpA) > 0) ? (PC + (ImmB << 2) + 4) : (PC + 4);                    // BGTZ
                3'b100: NPCout = ($signed(CmpA) < 0) ? (PC + (ImmB << 2) + 4) : (PC + 4);                    // BLTZ
                3'b101: NPCout = ($signed(CmpA) >= 0) ? (PC + (ImmB << 2) + 4) : (PC + 4);                   // BGEZ
            endcase
        end
        else begin  // JORB is 0, execute Jump
            if (is_JR) begin
                NPCout = CmpA;
            end
            else NPCout = {PC[31:28], Immj, 2'b00};
        end
    end

endmodule

###13.PC

module PC(
	input clk,					// clock signal
	input rst,					// reset signal 
	input PCwr,					// PC write enable signal
	input [31:0]PCin,			// PC input port
	output reg [31:0]PCout		// PC output port
);

	always @(posedge clk or rst) begin
		if (rst) begin
			PCout <= 32'h0000_0000;
		end
		else if (PCwr) begin
			PCout <= PCin;
		end
	end

endmodule

###14.Regfile

module Regfile(
    input clk,                  // clock signal
    input rst,                  // reset signal 
    input [4:0]Ra,              // rs register read in
    input [4:0]Rb,              // rt register read in
    input [4:0]Rw,              // rd/rt register read in
    input [31:0]Wd,             // Data written to register
    input RFwr,                 // Write register enable signal
    output reg [31:0]Raout,         // Read from rs
    output reg [31:0]Rbout          // Read from rt
);

    initial begin
        Raout = 0;
        Rbout = 0;
    end

    // Register file
    reg [31:0] RF[31:0];
    integer i;
    initial begin
        for (i = 0; i < 32; i = i + 1) RF[i] = 32'b0;
    end

    always@(Ra or Rb) begin
        Raout <= RF[Ra];
        Rbout <= RF[Rb];
    end

    always @(posedge clk) begin
        if (rst) begin
            for (i = 0; i < 32; i = i + 1) RF[i] = 32'b0;
        end

        else if (RFwr && Rw != 0) begin
            RF[Rw] <= Wd;
            //$display("Wd = %8X", Wd);
            //$display("R[00-07]= %8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X", 0, RF[1], RF[2], RF[3], RF[4], RF[5], RF[6], RF[7]);
            //$display("R[08-15]= %8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X", RF[8], RF[9], RF[10], RF[11], RF[12], RF[13], RF[14], RF[15]);
            //$display("R[16-23]= %8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X", RF[16], RF[17], RF[18], RF[19], RF[20], RF[21], RF[22], RF[23]);
            //$display("R[24-31]= %8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X", RF[24], RF[25], RF[26], RF[27], RF[28], RF[29], RF[30], RF[31]);
        end
    end

endmodule

Added by BandonRandon on Sat, 22 Jan 2022 00:42:58 +0200