##No abnormal instructions (40 in total)
###1. Arithmetic instruction
- ADDIU
- ADDU
- SUBU
- MULU
- DIVU
- MUL
- DIV
###2. Logic instruction - AND
- ANDI
- NOR
- OR
- ORI
- XOR
- XORI
- LUI
###3. Shift instruction - SLLV
- SLL
- SRAV
- SRA
- SLT
- SLTI
- SLTIU
- SLTU
- SRL
- SRLV
###4. Branch jump instruction - J
- JAL
- JR
- BEQ
- BNE
- BGEZ
- BGTZ
- BLEZ
- BLTZ
###5. Read write instruction - LW
- SW
###6. Data movement
1.MFLO
2.MFHI
3.MTLO
4.MTHI
##Modules included
- 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.
- 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.
- 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.
- 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.
- 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.
- EXT (extension unit): the main function of EXT is to expand 16 bit data into 32-bit data.
- 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.
- IR (instruction register): the main function of IR is to buffer the instructions from IM.
- 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.
- 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.
- ICUT: the main function is to divide 32-bit instructions into several parts and transfer them to different places.
- MDU: unit for multiplication and division
- Define: macro define all names.
##Module
##1.PC
####Port description
Signal name | direction | describe |
---|---|---|
Clk | I | clock signal |
Rst | I | Reset signal 1: Set PC as initial value 0: invalid |
PCwr | I | PC read / write enable terminal signal 1: Can write 0: not writable |
PCin[31:0] | I | Address of the next instruction |
PCout[31:0] | O | Address of the current instruction (mapping) |
####Function definition
Serial number | function | describe |
---|---|---|
1 | reset | Set PC as initial value |
2 | count | When the PCWR is valid and the clock rising edge, the PC updates to the NPC output |
##2.IMEM
####Port description
Signal name | direction | describe |
---|---|---|
Addr | I | Address of the current instruction |
Iout | O | Current instruction |
####Function definition
Serial number | function | describe |
---|---|---|
1 | Fetch instruction | Output the current instruction represented by Addr address |
##3.IR
####Port description
Signal name | direction | describe |
---|---|---|
clk | I | clock signal |
IRin | I | Instructions from IMEM |
IRwr | I | Control the reading and writing of instruction register 1: Can write 0: not writable |
IRout | O | Current instruction |
####Function definition
Serial number | function | describe |
---|---|---|
1 | buffer | Buffering instructions from IMEM |
##4.Regfile
####Port description
Signal name | direction | describe |
---|---|---|
Clk | I | clock signal |
rst | I | reset signal |
Ra[4:0] | I | 5-bit address input signal to read the contents of the register to Raout |
Rb[4:0] | I | 5-bit address input signal to read the contents of the register to Rbout |
Rw[4:0] | I | The 5-bit address input signal takes the register as the target register |
Wd[31:0] | I | 32-bit data input signal |
IRwr | I | Control IR reading and writing 1: Writable 0: not writable |
Raout | O | Outputs 32-bit data in the register specified by Raout |
Rbout | O | Outputs 32-bit data in the register specified by Rbout |
####Function definition
Serial number | function | describe |
---|---|---|
1 | Read data | Read out the data of 1 in the register corresponding to Ra and Rb addresses to Raout and Rbout |
2 | Write data | When 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 name | direction | describe |
---|---|---|
A[31:0] | I | Operand A |
B[31:0] | I | Operand B |
ALUop[3:0] | I | See menu for details |
Out[31:0] | O | ALU output result is 32-bit data |
####Function definition
Serial number | function | describe |
---|---|---|
1 | Addition operation | 0000:Out = A + B |
2 | Subtraction operation | 0001:Out = A - B |
3 | And operation | 0010:Out = A & B |
4 | Or non operation | 0011:Out = ~(A | B) |
5 | XOR operation | 0100:Out = A ^ B |
6 | Or operation | 0101:Out = A | B |
7 | Logical shift left | 0110:Out = B << A[10:6] |
8 | Logical shift right | 0111:Out = B >> A[10:6] |
9 | Arithmetic shift right | 1000:Out = Signed(B) >>> A[10:6] |
10 | Less than 1 (signed) | 1001:Out = Signed(A) < Signed(B) ? 1 : 0 |
11 | Less than 1 (unsigned) | 1010:Out = A < B ? 1 : 0 |
12 | Shift the A operand to the left by 16 bits (LUI) | 1011:Out = A << 16 |
##6.DMEM
####Port description
Signal name | direction | describe |
---|---|---|
DMwr | I | Data memory write enable signal 1: Writable 0: invalid |
Addr[31:0] | I | 32-bit address input, specifying read or write address data |
Imm[31:0] | I | An expanded 32-bit immediate used to calculate the address |
Din[31:0] | I | 32 is data input |
Dout[31:0] | O | 32 is the data output, which is specified by the calculated address |
####Function definition
Serial number | function | describe |
---|---|---|
1 | Read data | Read the data specified by Addr to Dout |
2 | Calculate address | Calculate the address added by Addr and immediate |
3 | Write data | When 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 name | direction | describe |
---|---|---|
EXTin | I | 16 bit input data |
EXTop | I | Expansion mode selection signal 0: symbol extension 1: Zero extension |
EXTout | O | Output data extended to 32 bits |
####Function definition
Serial number | function | describe |
---|---|---|
1 | Symbol extension | The 16 bit input data is symbol extended to output 32-bit data |
2 | Zero extension | Zero extension of 16 bit input data to output 32-bit data |
##8.NPC
####Port description
Signal name | direction | describe |
---|---|---|
Immj[25:0] | I | Middle 26 bits of jump instruction destination address |
ImmB[31:0] | I | Offset 00 of branch instruction (added when branch is selected) |
PC[31:0] | I | Branch instruction base address |
CmpA | I | The first comparison number of the branch instruction, which is used as the address when the instruction is Jump |
CmpB | I | Second comparison number of branch instructions |
is_JR | I | Judge whether it is JR instruction alone |
NPCop[2:0] | I | See menu for details |
JORB | I | Select Jump and Branch 0:Jump 1:Branch |
NPCout[31:0] | O | Next instruction address selected from Jump and Branch |
NextPC | O | Normal PC + 4 |
####Function definition
Serial number | function | describe |
---|---|---|
1 | Calculate branch address | First 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 |
2 | Calculate jump address | The jump address is calculated by bit splicing |
##9.MDU
####Port description
Signal name | direction | describe |
---|---|---|
clk | I | clock signal |
rst | I | reset signal |
MDUressel | I | Read register selection signal 0: read LO register 1: Read HI register |
A[31:0] | I | The first value involved in the calculation |
B[31:0] | I | The second value involved in the calculation |
MDUcoac | I | MDU enable end |
MDUop[2:0] | I | MDU 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] | O | Output calculation results |
####Function definition
Serial number | function | describe |
---|---|---|
1 | Unsigned multiplication | {HI, LO} = A * B |
2 | Signed multiplication | {HI, LO} = $signed(A) * $signed(B) |
3 | Unsigned Division | LO = A / B, HI = A % B |
4 | Signed Division | LO = $signed(A) / $signed(B, HI = $signed(A) % $signed(B) |
5 | Write LO register | LO = A |
6 | Read LO register | MDUout = LO |
7 | Write HI register | HI = A |
8 | Read HI register | MDUout = HI |
##10.ICUT
####Port description
Signal name | direction | describe |
---|---|---|
Ins[31:0] | I | Incoming 32-bit instruction |
op[5:0] | O | rs register |
rt[4:0] | O | rt register |
rd[4:0] | O | rd register |
rs[4:0] | O | Operation code |
sa[4:0] | O | Displacement |
Imm[15:0] | O | Immediate number |
Addr[25:0] | O | J instruction address fragment |
Insout[31:0] | O | 32-bit instruction passed to control |
####Function definition
Serial number | function | describe |
---|---|---|
1 | division | The 32-bit instruction is divided into segments and transmitted to each port |
##11.Control
####Port description
Signal name | direction | describe |
---|---|---|
Rst | I | Reset |
Clk | I | clock signal |
Ins | I | 32-bit instruction for decoding |
PCwr | O | Controls whether the PC is writable 0: not writable 1: Writable |
IRwr | O | Controls whether the IR is writable 0: not writable 1: Writable |
Regin[1:0] | O | Select the address to write to Regfile 00: write to rt register 01: write to rd register 10: Write to 1F register |
RFwr | O | Controls whether Regfile can be written 0: not writable 1: Writable |
SEL_A | O | Select A operand 0: from Regfile 1: From EXT |
SEL_B | O | Select B operand 0: from Regfile 1: From EXT |
ALUop[3:0] | O | Control which operation ALU selects. See ALU function description for details |
JORB | O | Control NPCout to choose Jump or Branch 0:Jump 1:Branch |
NPCop[2:0] | O | Select the type of Branch. See NPC function description for details |
MDUressel | O | Read register selection signal 0: read LO register 1: Read HI register |
MDUop[2:0] | O | Select the function of MDU. See the function description for details |
DMwr | O | Controls whether DM is writable 0: not writable 1: Writable |
EXTop[1:0] | O | See the menu for the control extension mode |
WBsel[1:0] | O | Select where the data written back to the register comes from |
NPCOsel | O | Select whether to execute the next branch normally or jump to the branch |
is_JR | O | Determine whether CMPA is used as the address of JR |
MDUcoac | O | MDU 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