- Verilog MIPS32 CPU(一)-- PC寄存器
- Verilog MIPS32 CPU(二)-- Regfiles
- Verilog MIPS32 CPU(三)-- ALU
- Verilog MIPS32 CPU(四)-- RAM
- Verilog MIPS32 CPU(五)-- CP0
- Verilog MIPS32 CPU(六)-- MDU
- Verilog MIPS32 CPU(七)-- DIV、DIVU
- Verilog MIPS32 CPU(八)-- 控制器
module CtrlUnit(input [31:0] instr,input [31:0] rdata1, rdata2,input [31:0] pc,ram_data,hi,lo,alu_r,cop_data,mul_out,input [31:0] exc_addr,input clk,output mtc0,eret,teq_exc,output reg [2:0] mdu,output reg reg_wena,output ram_wena,output reg [3:0] cause,output [4:0] rs,rt,rd,waddr,output reg [31:0] wdata,reg_data,output [31:0] ram_addr,output reg [31:0] pc_in,output reg [31:0] alu_a,alu_b,output reg [3:0] alu_op);//******MIPS-55*********// parameter //SPECIAL OP LIST 5-0ADDU = 6'b100001,SUBU = 6'b100011,ADD = 6'b100000,SUB = 6'b100010,AND = 6'b100100,OR = 6'b100101,XOR = 6'b100110,NOR = 6'b100111,SLT = 6'b101010,SLTU = 6'b101011,SRL = 6'b000010,SRA = 6'b000011,SLL = 6'b000000,SLLV = 6'b000100,SRLV = 6'b000110,SRAV = 6'b000111,JR = 6'b001000,JALR = 6'b001001,MULT = 6'b011000,MULTU = 6'b011001,DIV = 6'b011010,DIVU = 6'b011011,MFHI = 6'b010000,MFLO = 6'b010010,MTHI = 6'b010001,MTLO = 6'b010011,BREAK = 6'b001101,SYSCALL = 6'b001100,TEQ = 6'b110100,//SPECIAL 2 funcCLZ = 6'b100000,MUL = 6'b000010,//REGIMM OP LIST 20-16BLTZ = 5'b00000,BGEZ = 5'b00001,//COP0 OP LIST ERET = 6'b011000, //5-0&&25TH=1MFC0 = 5'b00000, //20-16MTC0 = 5'b00100,//OPCODE FIELD 31-26ADDI = 6'b001000,ADDIU = 6'b001001,ANDI = 6'b001100,ORI = 6'b001101,XORI = 6'b001110,LW = 6'b100011,SW = 6'b101011,BEQ = 6'b000100,BNE = 6'b000101,BLEZ = 6'b000110,BGTZ = 6'b000111,SLTI = 6'b001010,SLTIU = 6'b001011,LUI = 6'b001111,J = 6'b000010,JAL = 6'b000011,LB = 6'b100000,// Load Byte Function=6'h24 LBU = 6'b100100,// 1Load Byte Unsigned LH = 6'b100001,// Load high LHU = 6'b100101,// Load High UnsignedSB = 6'b101000,// Send ByteSH = 6'b101001,// Send High SPECIAL = 6'b000000,SPECIAL2= 6'b011100,REGIMM = 6'b000001,COP0 = 6'b010000; //ALU OPCODE parameter _ADDU = 4'b0000; //r=a+b unsignedparameter _ADD = 4'b0010; //r=a+b signedparameter _SUBU = 4'b0001; //r=a-b unsignedparameter _SUB = 4'b0011; //r=a-b signedparameter _AND = 4'b0100; //r=a&bparameter _OR = 4'b0101; //r=a|bparameter _XOR = 4'b0110; //r=a^bparameter _NOR = 4'b0111; //r=~(a|b)parameter _LUI = 4'b1000; //r={b[15:0],16'b0}parameter _SLT = 4'b1011; //r=(a-b<0)?1:0 signedparameter _SLTU = 4'b1010; //r=(a-b<0)?1:0 unsignedparameter _SRA = 4'b1100; //r=b>>>a parameter _SLL = 4'b1110; //r=b<<aparameter _SRL = 4'b1101; //r=b>>aparameter _SYSCALL= 4'b1000,_BREAK = 4'b1001,_TEQ = 4'b1101;wire [5:0] op = instr[31:26];assign rs = instr[25:21];assign rt = instr[20:16];assign rd = instr[15:11];wire [5:0] func = instr[5:0];wire [4:0] shamt = instr[10:6];wire [15:0] imm = instr[15:0];wire [25:0] addr = instr[25:0];parameter SIGN = 1'b1;parameter UNSIGN = 1'b0;wire imm_sign = (op==ANDI||op==ORI||op==XORI)?UNSIGN:SIGN;wire [31:0] shamt_ext = {27'b0,shamt};wire [31:0] imm_ext = imm_sign?{{(16){imm[15]}},imm}:{16'b0,imm};reg [31:0] load_data,clz_data;assign waddr = (op==SPECIAL||op==SPECIAL2)? rd: (op==JAL) ?5'b11111:rt;always@(*)begincase(op)SB: reg_data = {24'b0,rdata2[7:0]};SH: reg_data = {16'b0,rdata2[15:0]};SW: reg_data = rdata2;default:reg_data = rdata2;endcasecase(op)LB: load_data = {{24{ram_data[7]}},ram_data[7:0]};LBU: load_data = {24'b0,ram_data[7:0]};LH: load_data = {{16{ram_data[15]}},ram_data[15:0]};LHU: load_data = {16'b0,ram_data[15:0]};LW: load_data = ram_data;default:load_data = ram_data;endcaseif(op==SPECIAL)case(func)SYSCALL:cause = _SYSCALL;BREAK: cause = _BREAK;TEQ: cause = _TEQ;default:cause = 5'b0;endcaseelse cause = 5'b0;/*1 mult2 multu3 div 4 divu5 mthi6 mtlo7 mul*/if(op==SPECIAL)case(func)MULT: mdu = 3'h1;MULTU: mdu = 3'h2;DIV: mdu = 3'h3;DIVU: mdu = 3'h4;MTHI: mdu = 3'h5;MTLO: mdu = 3'h6;default:mdu = 3'h0;endcaseelse mdu = 3'h0;endwire [31:0] npc = pc+4;wire [31:0] pc_branch = npc + {{(14){imm[15]}},imm,2'b00};wire [31:0] pc_jmp = {npc[31:28],addr,2'b00};assign ram_addr = rdata1 + imm_ext;assign eret = op==COP0 && func==ERET;wire mfc0 = op==COP0 && rs==MFC0;assign mtc0 = op==COP0 && rs==MTC0;assign teq_exc = rdata1==rdata2;parameter ENA = 1'b1;parameter DIS = 1'b0;wire mem_load = op==LB || op==LH || op==LBU || op==LHU || op==LW;assign ram_wena = op==SW || op==SH || op==SB;integer i; always@(*)begincase(op)SPECIAL: case(func)MULTU,DIV,DIVU,JR,MTHI,MTLO,BREAK,SYSCALL:reg_wena = DIS;default:reg_wena = ENA; endcaseCOP0: reg_wena = rs==MFC0?ENA:DIS;SPECIAL2,LB,LBU,LH,LHU,ADDI,ADDIU,ANDI,ORI,XORI,LW,SLTI,SLTIU,LUI,JAL: reg_wena = ENA; default: reg_wena = DIS;endcasecase(op)SPECIAL:case(func)JALR: wdata = npc;MFHI: wdata = hi;MFLO: wdata = lo;default:wdata = alu_r;endcase SPECIAL2:beginif(func==CLZ) casez(rdata1)32'b1???????????????????????????????: wdata = 32'h0;32'b01??????????????????????????????: wdata = 32'h1;32'b001?????????????????????????????: wdata = 32'h2;32'b0001????????????????????????????: wdata = 32'h3;32'b00001???????????????????????????: wdata = 32'h4;32'b000001??????????????????????????: wdata = 32'h5;32'b0000001?????????????????????????: wdata = 32'h6;32'b00000001????????????????????????: wdata = 32'h7;32'b000000001???????????????????????: wdata = 32'h8;32'b0000000001??????????????????????: wdata = 32'h9;32'b00000000001?????????????????????: wdata = 32'ha;32'b000000000001????????????????????: wdata = 32'hb;32'b0000000000001???????????????????: wdata = 32'hc;32'b00000000000001??????????????????: wdata = 32'hd;32'b000000000000001?????????????????: wdata = 32'he;32'b0000000000000001????????????????: wdata = 32'hf;32'b00000000000000001???????????????: wdata = 32'h10;32'b000000000000000001??????????????: wdata = 32'h11;32'b0000000000000000001?????????????: wdata = 32'h12;32'b00000000000000000001????????????: wdata = 32'h13;32'b000000000000000000001???????????: wdata = 32'h14;32'b0000000000000000000001??????????: wdata = 32'h15;32'b00000000000000000000001?????????: wdata = 32'h16;32'b000000000000000000000001????????: wdata = 32'h17;32'b0000000000000000000000001???????: wdata = 32'h18;32'b00000000000000000000000001??????: wdata = 32'h19;32'b000000000000000000000000001?????: wdata = 32'h1a;32'b0000000000000000000000000001????: wdata = 32'h1b;32'b00000000000000000000000000001???: wdata = 32'h1c;32'b000000000000000000000000000001??: wdata = 32'h1d;32'b0000000000000000000000000000001?: wdata = 32'h1e;32'b00000000000000000000000000000001: wdata = 32'h1f;32'b00000000000000000000000000000000: wdata = 32'h20;endcaseelse if(func==MUL) wdata = mul_out;else wdata = alu_r;endJAL: wdata = npc;LW,LB,LH,LBU,LHU: wdata = load_data;COP0: if(rs==MFC0) wdata = cop_data;else wdata = alu_r;default: wdata = alu_r;endcase//Below is OKcase(op)SPECIAL: case(func)SLL,SRL,SRA:beginalu_a = shamt_ext;alu_b = rdata2;enddefault:beginalu_a = rdata1;alu_b = rdata2;endendcaseADDI,ADDIU,ANDI,ORI,XORI,SLTI,SLTIU,LUI:beginalu_a = rdata1;alu_b = imm_ext;enddefault:beginalu_a = rdata1;alu_b = rdata2;endendcase//PC Source case(op)SPECIAL: case(func)SYSCALL,TEQ,BREAK: pc_in = exc_addr;JALR,JR: pc_in = rdata1; default:pc_in = npc; endcaseCOP0: case(func)ERET: pc_in = exc_addr;default:pc_in = npc;endcaseREGIMM: case(rt)BLTZ:if(rdata1[31])pc_in = pc_branch;elsepc_in = npc;BGEZ:if(!rdata1[31])pc_in = pc_branch;elsepc_in = npc;default:pc_in = npc;endcaseJ,JAL: pc_in = pc_jmp;BEQ:if(rdata1==rdata2)pc_in = pc_branch;else pc_in = npc;BNE:if(rdata1!=rdata2)pc_in = pc_branch;else pc_in = npc;BLEZ:if(rdata1[31] || rdata1==32'b0)pc_in = pc_branch;else pc_in = npc;BGTZ:if(!rdata1[31] && rdata1!=32'b0)pc_in = pc_branch;else pc_in = npc;default: pc_in = npc; endcasecase(op)SPECIAL:case(func)ADDU: alu_op = _ADDU;SUBU: alu_op = _SUBU;ADD: alu_op = _ADD;SUB: alu_op = _SUB;AND: alu_op = _AND;OR: alu_op = _OR;XOR: alu_op = _XOR;NOR: alu_op = _NOR;SLT: alu_op = _SLT;SRL: alu_op = _SRL;SLL: alu_op = _SLL;SRA: alu_op = _SRA;SLTU: alu_op = _SLTU;SRLV: alu_op = _SRL;SLLV: alu_op = _SLL;SRAV: alu_op = _SRA;default: alu_op = _ADDU;endcase ORI: alu_op = _OR;XORI: alu_op = _XOR;BEQ: alu_op = _SUBU;BNE: alu_op = _SUBU;ANDI: alu_op = _AND;ADDIU: alu_op = _ADDU;ADDI: alu_op = _ADD;SLTI: alu_op = _SLT;SLTIU: alu_op = _SLTU;LUI: alu_op = _LUI;default: alu_op = _ADDU;endcaseend endmodule