该项目将展示32位流水线的Verilog代码 MIPS处理器。在 part 2,我介绍了单周期MIPS数据路径的所有Verilog代码。
在这一部分中,添加了流水线寄存器以完成 流水线MIPS处理器. Verilog 将提供完整的32位流水线MIPS处理器的代码。
以下是32位5级流水线的完整数据路径 MIPS处理器 在添加流水线寄存器之后, 转寄 单元,失速控制单元和冲洗控制单元到单周期数据路径。转发,停转控制和冲洗控制单元旨在解决流水线MIPS处理器中的数据并控制危害。以下是对Verilog中的危害解决模块和完整的流水线MIPS处理器的详细说明。
![]() |
流水线式MIPS处理器数据路径 |
转发单位:
转发单元旨在解决流水线式MIPS处理器中的数据危险。当检测到数据危险时,ALU输出上的正确数据将转发到ALU输入。当当前指令的源寄存器(EX_rs或EX_rt)与上一条指令的目标寄存器(MEM_WriteRegister或EX_WriteRegister)相同时,将检测到数据危害。

转发单元的Verilog代码:
`timescale 1 ps / 100 fs // hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // 转寄 Unit module 转寄Unit(ForwardA,ForwardB,MEM_RegWrite,WB_RegWrite,MEM_WriteRegister,WB_WriteRegister,EX_rs,EX_rt); output [1:0] ForwardA,ForwardB; wire [1:0] ForwardA,ForwardB; input MEM_RegWrite,WB_RegWrite; input [4:0] MEM_WriteRegister,WB_WriteRegister,EX_rs,EX_rt; // a= 1 if ( MEM_WriteRegister != 0 ) or #(50) orMEM_WriteReg(a,MEM_WriteRegister[4],MEM_WriteRegister[3],MEM_WriteRegister[2],MEM_WriteRegister[1],MEM_WriteRegister[0]); CompareAddress CompMEM_WriteReg_EXrs(b,MEM_WriteRegister,EX_rs); and #(50) andx(x,MEM_RegWrite,a,b); // x=1 if ((MEM_RegWrite==1)&&(MEM_WriteRegister != 0)&&(MEM_WriteRegister==EX_rs)) // c= 1 if ( WB_WriteRegister != 0 ) or #(50) orWB_WriteReg(c,WB_WriteRegister[4],WB_WriteRegister[3],WB_WriteRegister[2],WB_WriteRegister[1],WB_WriteRegister[0]); CompareAddress CompWB_WriteReg_EXrs(d,WB_WriteRegister,EX_rs); and #(50) andy(y,WB_RegWrite,c,d); // y=1 if ((WB_RegWrite==1)&&(WB_WriteRegister != 0)&&(WB_WriteRegister==EX_rs)) // ForwardA[1] = x; va ForwardA[0] = (NOT x). y ; assign ForwardA[1] = x; not #(50) notxgate(notx,x); and #(50) NOTxANDy(ForwardA[0],notx,y); // ForwardB CompareAddress CompMEM_WriteReg_EXrt(b1,MEM_WriteRegister,EX_rt); CompareAddress CompWB_WriteReg_EXrt(d1,WB_WriteRegister,EX_rt); and #(50) andx1(x1,MEM_RegWrite,a,b1); and #(50) andy1(y1,WB_RegWrite,c,d1); assign ForwardB[1] = x1; not #(50) notx1gate(notx1,x1); and #(50) NOTx1ANDy1(ForwardB[0],notx1,y1); endmodule
添加转发单元以解决数据危险后,ALU输入处的2x32至32多路复用器将变为3x32至32多路复用器。
多路复用器的Verilog代码:
`timescale 1 ps / 100 fs // hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // mux3x32to32 module mux3x32to32(DataOut,A,B,C,Select); output [31:0] DataOut; input [1:0] Select; input [31:0] A,B,C; wire [31:0] DataOut1,DataOut2; mux2x32to32 muxAB(DataOut1,A,B, Select[1]); mux2x32to32 muxCA(DataOut2,C,A, Select[1]); mux2x32to32 muxABC(DataOut,DataOut1,DataOut2, Select[0]); endmodule
接下来,当发生数据危险时需要失速控制单元,并且需要延迟1个周期才能转发。
失速控制单元:
当前读取存储器指令的目标寄存器(EX_rt)发生需要暂停1个周期的数据危险 is the same as the ID阶段中即将到来的指令的源寄存器(ID_rs或ID_rt),XORI和LW指令的ID_rt除外(其中Rt是目标寄存器,不是XORI和LW的源寄存器)。


失速控制单元的Verilog代码:
`timescale 1 ps / 100 fs // hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // Stall Control module StallControl(PC_WriteEn,IFID_WriteEn,Stall_flush,EX_MemRead,EX_rt,ID_rs,ID_rt,ID_Op); output PC_WriteEn,IFID_WriteEn,Stall_flush; wire PC_WriteEn,IFID_WriteEn,Stall_flush; input EX_MemRead,EX_rt,ID_rs,ID_rt; input [5:0] ID_Op; wire [4:0] EX_rt,ID_rs,ID_rt,xorRsRt,xorRtRt; wire [5:0] xoropcodelw,xoropcodexori; wire EX_MemRead; //wire xoropcode1,xoroprt; // write in behavior model /*always @(EX_MemRead or EX_rt or ID_rs or ID_rt) begin if ((EX_MemRead==1)&&((EX_rt==ID_rs)||((EX_rt==ID_rt)&&(Opcode!= 6'b001110)&&(Opcode!= 6'b100011))) begin PC_WriteEn=1'b0; IFID_WriteEn=1'b0; Stall_flush =1'b1; end else begin PC_WriteEn=1'b1; IFID_WriteEn=1'b1; Stall_flush =1'b0; end end */ // write in structural model xor #(50) xorRsRt4(xorRsRt[4],EX_rt[4],ID_rs[4]); xor #(50) xorRsRt3(xorRsRt[3],EX_rt[3],ID_rs[3]); xor #(50) xorRsRt2(xorRsRt[2],EX_rt[2],ID_rs[2]); xor #(50) xorRsRt1(xorRsRt[1],EX_rt[1],ID_rs[1]); xor #(50) xorRsRt0(xorRsRt[0],EX_rt[0],ID_rs[0]); or #(50) OrRsRt1(OrRsRt,xorRsRt[4],xorRsRt[3],xorRsRt[2],xorRsRt[1],xorRsRt[0]); not #(50) notgate1(notOrRsRt,OrRsRt); // neu EX_rt==ID_rs thi notOrRsRt = 1 xor #(50) xorRtRt4(xorRtRt[4],EX_rt[4],ID_rt[4]); xor #(50) xorRtRt3(xorRtRt[3],EX_rt[3],ID_rt[3]); xor #(50) xorRtRt2(xorRtRt[2],EX_rt[2],ID_rt[2]); xor #(50) xorRtRt1(xorRtRt[1],EX_rt[1],ID_rt[1]); xor #(50) xorRtRt0(xorRtRt[0],EX_rt[0],ID_rt[0]); or #(50) OrRtRt1(OrRtRt,xorRtRt[4],xorRtRt[3],xorRtRt[2],xorRtRt[1],xorRtRt[0]); not #(50) notgate2(notOrRtRt,OrRtRt); // neu EX_rt==ID_rt thi notOrRtRt = 1 xor #(50) xoropcode5(xoropcodelw[5],ID_Op[5],1'b1); xor #(50) xoropcode4(xoropcodelw[4],ID_Op[4],1'b0); xor #(50) xoropcode3(xoropcodelw[3],ID_Op[3],1'b0); xor #(50) xoropcode2(xoropcodelw[2],ID_Op[2],1'b0); xor #(50) xoropcode1(xoropcodelw[1],ID_Op[1],1'b1); xor #(50) xoropcode0(xoropcodelw[0],ID_Op[0],1'b1); or #(50) oropcode1(ec1,xoropcodelw[5],xoropcodelw[4],xoropcodelw[3],xoropcodelw[2],xoropcodelw[1],xoropcodelw[0]); // opcode != opcode[lw] xoropcodelw =1 xor #(50) xoropcod5(xoropcodexori[5],ID_Op[5],1'b0); xor #(50) xoropcod4(xoropcodexori[4],ID_Op[4],1'b0); xor #(50) xoropcod3(xoropcodexori[3],ID_Op[3],1'b1); xor #(50) xoropcod2(xoropcodexori[2],ID_Op[2],1'b1); xor #(50) xoropcod1(xoropcodexori[1],ID_Op[1],1'b1); xor #(50) xoropcod0(xoropcodexori[0],ID_Op[0],1'b0); or #(50) oropcode2(ec2,xoropcodexori[5],xoropcodexori[4],xoropcodexori[3],xoropcodexori[2],xoropcodexori[1],xoropcodexori[0]); // opcode != opcode[xori] xoropcodexori =1 and #(50) and1(xorop,ec1,ec2); and #(50) and2(xoroprt,xorop,notOrRtRt); or #(50) OrEXIDRsRt(OrOut,notOrRsRt,xoroprt); and #(50) AndCondition(Condition,EX_MemRead,OrOut); // Condition =1 when stall is satisfied not #(50) NotPC_WriteEn(PC_WriteEn,Condition); not #(50) NotIFID_WriteEn(IFID_WriteEn,Condition); buf #(50) bufStallflush(Stall_flush,Condition); endmodule
冲洗控制单元:
冲洗控制单元旨在解决控制危险,当执行跳转指令(J,JR或BNE)时,它将丢弃IF和ID阶段的指令。
冲洗控制单元的Verilog代码:
// hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // Flush control signals `timescale 1 ps / 100 fs module flush_block( ID_RegDst,ID_ALUSrc, ID_MemtoReg,ID_RegWrite,ID_MemRead,ID_MemWrite, ID_Branch,ID_ALUOp,ID_JRControl,flush,RegDst,ALUSrc,MemtoReg,RegWrite, MemRead,MemWrite,Branch,ALUOp,JRControl); output ID_RegDst,ID_ALUSrc,ID_MemtoReg,ID_RegWrite,ID_MemRead,ID_MemWrite,ID_Branch,ID_JRControl; output [1:0] ID_ALUOp; input flush,RegDst,ALUSrc,MemtoReg,RegWrite,MemRead,MemWrite,Branch,JRControl; input [1:0] ALUOp; not #50 (notflush,flush); and #50 and1(ID_RegDst,RegDst,notflush); and #50 and2(ID_ALUSrc,ALUSrc,notflush); and #50 and3(ID_MemtoReg,MemtoReg,notflush); and #50 and4(ID_RegWrite,RegWrite,notflush); and #50 and5(ID_MemRead,MemRead,notflush); and #50 and6(ID_MemWrite,MemWrite,notflush); and #50 and7(ID_Branch,Branch,notflush); and #50 and8(ID_JRControl,JRControl,notflush); and #50 and9(ID_ALUOp[1],ALUOp[1],notflush); and #50 and10(ID_ALUOp[0],ALUOp[0],notflush); endmodule `timescale 1 ps / 100 fs // hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // Discard instructions when needed module Discard_Instr(ID_flush,IF_flush,jump,bne,jr); output ID_flush,IF_flush; input jump,bne,jr; or #50 OR1(IF_flush,jump,bne,jr); or #50 OR2(ID_flush,bne,jr); endmodule
在同一地址进行写入和读取时,在回写阶段可能会发生另一种危险。读出的数据可能不是正确的写入数据。为了解决此问题,WB_Forward单元被设计为将正确的写入数据直接转发到输出 data.

WB_Forward单位的Verilog代码:
`timescale 1 ps / 100 fs // hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // Write Back 转寄 module WB_forward(ReadData1Out,ReadData2Out,ReadData1,ReadData2,rs,rt,WriteRegister,WriteData,RegWrite); // WB Hazard: Reading data while writing // Solve Hazard at the WriteBack Stage output [31:0] ReadData1Out,ReadData2Out; input [31:0] ReadData1,ReadData2,WriteData; input [4:0] rs,rt,WriteRegister; input RegWrite; wire ReadSourceRs,ReadSourceRt; wire compOut1,compOut2; // behavior model /* always @(rs or rt or WriteRegister or WriteData or RegWrite) begin if ((RegWrite==1)&&(WriteRegister != 0)&&(WriteRegister==rs)) ReadSourceRs = 1'b1; //Forwarding WriteData to ReadData1 else ReadSourceRs = 1'b0; if ((RegWrite==1)&&(WriteRegister != 0)&&(WriteRegister==rt)) ReadSourceRt = 1'b1; //Forwarding WriteData to ReadData2 else ReadSourceRt = 1'b0; end */ // Structural model or #(50) orWriteReg(orOut1,WriteRegister[4],WriteRegister[3],WriteRegister[2],WriteRegister[1],WriteRegister[0]); CompareAddress Compare1(compOut1,WriteRegister,rs); and #(50) andCondition1(ReadSourceRs,RegWrite,orOut1,compOut1); CompareAddress Compare2(compOut2,WriteRegister,rt); and #(50) andCondition2(ReadSourceRt,RegWrite,orOut1,compOut2); mux2x32to32 muxReadData1( ReadData1Out,ReadData1,WriteData, ReadSourceRs); mux2x32to32 muxReadData2( ReadData2Out,ReadData2,WriteData, ReadSourceRt); endmodule `timescale 1 ps / 100 fs module CompareAddress(equal,Addr1,Addr2); // hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // Compare Address output equal; wire equal; input [4:0] Addr1,Addr2; wire [4:0] Addr1,Addr2,xorAddress; xor #(50) xorAddress4(xorAddress[4],Addr1[4],Addr2[4]); xor #(50) xorAddress3(xorAddress[3],Addr1[3],Addr2[3]); xor #(50) xorAddress2(xorAddress[2],Addr1[2],Addr2[2]); xor #(50) xorAddress1(xorAddress[1],Addr1[1],Addr2[1]); xor #(50) xorAddress0(xorAddress[0],Addr1[0],Addr2[0]); or #(50) Orgate1(OrAddr,xorAddress[4],xorAddress[3],xorAddress[2],xorAddress[1],xorAddress[0]); not #(50) notgate1(equal,OrAddr); endmodule
现在,我们为整个32位流水线MIPS处理器的所有必要部分完成了Verilog代码。
让我们来看一下32位流水线MIPS处理器的顶级Verilog代码:
`timescale 1 ps / 100 fs // hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // Top level Verilog code for 32-bit 5-stage Pipelined MIPS处理器 module MIPSpipeline(clk, reset); input clk, reset; wire [31:0] PC, PCin; wire [31:0] PC4,ID_PC4,EX_PC4; wire [31:0] PCbne,PC4bne,PCj,PC4bnej,PCjr; // PC signals in MUX wire [31:0] Instruction,ID_Instruction,EX_Instruction; // Output of Instruction Memory wire [5:0] Opcode,Function; // Opcode, Function // Extend wire [15:0] imm16; // immediate in I type instruction wire [31:0] Im16_Ext,EX_Im16_Ext; wire [31:0] sign_ext_out,zero_ext_out; // regfile wire [4:0] rs,rt,rd,EX_rs,EX_rt,EX_rd,EX_WriteRegister,MEM_WriteRegister,WB_WriteRegister; wire [31:0] WB_WriteData, ReadData1, ReadData2,ReadData1Out,ReadData2Out, EX_ReadData1, EX_ReadData2; // ALU wire [31:0] Bus_A_ALU,Bus_B_ALU,Bus_B_forwarded; wire [31:0] EX_ALUResult,MEM_ALUResult,WB_ALUResult; wire ZeroFlag, OverflowFlag, CarryFlag, NegativeFlag,notZeroFlag; wire [31:0] WriteDataOfMem,MEM_ReadDataOfMem,WB_ReadDataOfMem; //Control signals wire RegDst,ALUSrc,MemtoReg,RegWrite,MemRead,MemWrite,Branch,Jump,SignZero,JRControl; wire ID_RegDst,ID_ALUSrc,ID_MemtoReg,ID_RegWrite,ID_MemRead,ID_MemWrite,ID_Branch,ID_JRControl; wire EX_RegDst,EX_ALUSrc,EX_MemtoReg,EX_RegWrite,EX_MemRead,EX_MemWrite,EX_Branch,EX_JRControl; wire MEM_MemtoReg,MEM_RegWrite,MEM_MemRead,MEM_MemWrite; wire WB_MemtoReg,WB_RegWrite; wire [1:0] ALUOp,ID_ALUOp,EX_ALUOp; wire [1:0] ALUControl; wire bneControl,notbneControl; wire JumpControl,JumpFlush; wire [1:0] ForwardA,ForwardB; //flush wire IF_flush,IFID_flush,notIFID_flush,Stall_flush,flush; //shift left wire [31:0] shiftleft2_bne_out,shiftleft2_jump_out; // shift left output // PC Write Enable, IF/ID Write Enable wire PC_WriteEn,IFID_WriteEn; //====== PC register====== register PC_Reg(PC,PCin,PC_WriteEn,reset,clk); Add Add1(PC4,PC,{29'b0,3'b100}); // PC4 = PC + 4 InstructionMem InstructionMem1(Instruction, PC); // register IF/ID register IFID_PC4(ID_PC4,PC4,IFID_WriteEn,reset,clk); register IFID_Instruction(ID_Instruction,Instruction,IFID_WriteEn,reset,clk); RegBit IF_flush_bit(IFID_flush,IF_flush, IFID_WriteEn,reset, clk); //========= ID STAGE=========== assign Opcode = ID_Instruction[31:26]; assign Function = ID_Instruction[5:0]; assign rs = ID_Instruction[25:21]; assign rt = ID_Instruction[20:16]; assign rd = ID_Instruction[15:11]; assign imm16= ID_Instruction[15:0]; // Main Control Control MainControl( RegDst, ALUSrc, MemtoReg, RegWrite, MemRead, MemWrite, Branch, ALUOp, Jump, SignZero, Opcode ); // Regfile regfile Register_File( ReadData1, ReadData2, WB_WriteData, rs, rt, WB_WriteRegister, WB_RegWrite, reset, clk); // forward Read Data if Write and Read at the same time WB_forward WB_forward_block(ReadData1Out,ReadData2Out,ReadData1,ReadData2,rs,rt,WB_WriteRegister,WB_WriteData,WB_RegWrite); // Sign-extend sign_extend sign_extend1(sign_ext_out,imm16); // Zero-extend zero_extend zero_extend1(zero_ext_out,imm16); // immediate extend: sign or zero mux2x32to32 muxSignZero( Im16_Ext,sign_ext_out,zero_ext_out, SignZero); JRControl_Block JRControl_Block1( JRControl, ALUOp, Function); Discard_Instr Discard_Instr_Block(ID_flush,IF_flush,JumpControl,bneControl,EX_JRControl); or #(50) OR_flush(flush,ID_flush,IFID_flush,Stall_flush); flush_block flush_block1(ID_RegDst,ID_ALUSrc,ID_MemtoReg,ID_RegWrite,ID_MemRead,ID_MemWrite,ID_Branch,ID_ALUOp, ID_JRControl,flush,RegDst,ALUSrc,MemtoReg,RegWrite,MemRead,MemWrite,Branch,ALUOp,JRControl); //==========EX STAGE========================= // thanh ghi ID/EX register IDEX_PC4(EX_PC4,ID_PC4,1'b1,reset,clk); register IDEX_ReadData1(EX_ReadData1,ReadData1Out,1'b1,reset,clk); register IDEX_ReadData2(EX_ReadData2,ReadData2Out,1'b1,reset,clk); register IDEX_Im16_Ext(EX_Im16_Ext,Im16_Ext,1'b1,reset,clk); register IDEX_rs_rt_rd(EX_Instruction[31:0],ID_Instruction,1'b1,reset,clk); assign EX_rs = EX_Instruction[25:21]; assign EX_rt = EX_Instruction[20:16]; assign EX_rd = EX_Instruction[15:11]; // 9 control signals via ID/EX RegBit IDEX_RegDst(EX_RegDst, ID_RegDst, 1'b1,reset, clk); RegBit IDEX_ALUSrc(EX_ALUSrc, ID_ALUSrc, 1'b1,reset, clk); RegBit IDEX_MemtoReg(EX_MemtoReg, ID_MemtoReg, 1'b1,reset, clk); RegBit IDEX_RegWrite(EX_RegWrite, ID_RegWrite, 1'b1,reset, clk); RegBit IDEX_MemRead(EX_MemRead, ID_MemRead, 1'b1,reset, clk); RegBit IDEX_MemWrite(EX_MemWrite, ID_MemWrite, 1'b1,reset, clk); RegBit IDEX_Branch(EX_Branch, ID_Branch, 1'b1,reset, clk); RegBit IDEX_JRControl(EX_JRControl, ID_JRControl, 1'b1,reset, clk); RegBit IDEX_ALUOp1(EX_ALUOp[1], ID_ALUOp[1], 1'b1,reset, clk); RegBit IDEX_ALUOp0(EX_ALUOp[0], ID_ALUOp[0], 1'b1,reset, clk); // 转寄 unit转寄Unit 转寄_Block(ForwardA,ForwardB,MEM_RegWrite,WB_RegWrite,MEM_WriteRegister,WB_WriteRegister,EX_rs,EX_rt); // mux 3 x32 to 32 to choose source of ALU (forwarding) mux3x32to32 mux3A(Bus_A_ALU,EX_ReadData1,MEM_ALUResult,WB_WriteData,ForwardA); mux3x32to32 mux3B(Bus_B_forwarded,EX_ReadData2,MEM_ALUResult,WB_WriteData,ForwardB); // mux 2x32 to 32 to select source Bus B of ALU mux2x32to32 muxALUSrc( Bus_B_ALU,Bus_B_forwarded,EX_Im16_Ext, EX_ALUSrc); // ALU Control ALUControl_Block ALUControl_Block1( ALUControl, EX_ALUOp, EX_Im16_Ext[5:0]); // EX_Im16_Ext[5:0] is function // ALU alu alu_block(EX_ALUResult, CarryFlag, ZeroFlag, OverflowFlag, NegativeFlag, Bus_A_ALU, Bus_B_ALU, ALUControl); // mux 2x5 to 5 choose shift register is Rd or Rt mux2x5to5 muxRegDst( EX_WriteRegister,EX_rt,EX_rd, EX_RegDst); //==============MEM STAGE================= // register EX/MEM register EXMEM_ALUResult(MEM_ALUResult,EX_ALUResult,1'b1,reset,clk); register EXMEM_WriteDataOfMem(WriteDataOfMem, Bus_B_forwarded,1'b1,reset,clk); RegBit EXMEM_MemtoReg(MEM_MemtoReg, EX_MemtoReg, 1'b1,reset, clk); RegBit EXMEM_RegWrite(MEM_RegWrite, EX_RegWrite, 1'b1,reset, clk); RegBit EXMEM_MemRead(MEM_MemRead, EX_MemRead, 1'b1,reset, clk); RegBit EXMEM_MemWrite(MEM_MemWrite, EX_MemWrite, 1'b1,reset, clk); RegBit EXMEM_WriteRegister4(MEM_WriteRegister[4], EX_WriteRegister[4], 1'b1,reset, clk); RegBit EXMEM_WriteRegister3(MEM_WriteRegister[3], EX_WriteRegister[3], 1'b1,reset, clk); RegBit EXMEM_WriteRegister2(MEM_WriteRegister[2], EX_WriteRegister[2], 1'b1,reset, clk); RegBit EXMEM_WriteRegister1(MEM_WriteRegister[1], EX_WriteRegister[1], 1'b1,reset, clk); RegBit EXMEM_WriteRegister0(MEM_WriteRegister[0], EX_WriteRegister[0], 1'b1,reset, clk); // Data Memory dataMem dataMem1(MEM_ReadDataOfMem, //data MEM_ALUResult, //address WriteDataOfMem, //writedata MEM_MemWrite, //writeenable MEM_MemRead, clk); //==========WB STAGE==================== // register MEM/WB register MEMWB_ReadDataOfMem(WB_ReadDataOfMem,MEM_ReadDataOfMem,1'b1,reset,clk); register MEMWB_ALUResult(WB_ALUResult,MEM_ALUResult,1'b1,reset,clk); RegBit MEMWB_WriteRegister4(WB_WriteRegister[4], MEM_WriteRegister[4], 1'b1,reset, clk); RegBit MEMWB_WriteRegister3(WB_WriteRegister[3], MEM_WriteRegister[3], 1'b1,reset, clk); RegBit MEMWB_WriteRegister2(WB_WriteRegister[2], MEM_WriteRegister[2], 1'b1,reset, clk); RegBit MEMWB_WriteRegister1(WB_WriteRegister[1], MEM_WriteRegister[1], 1'b1,reset, clk); RegBit MEMWB_WriteRegister0(WB_WriteRegister[0], MEM_WriteRegister[0], 1'b1,reset, clk); RegBit MEMWB_MemtoReg(WB_MemtoReg, MEM_MemtoReg, 1'b1,reset, clk); RegBit MEMWB_RegWrite(WB_RegWrite, MEM_RegWrite, 1'b1,reset, clk); // Select Data to WriteData for regfile mux2x32to32 muxMemtoReg( WB_WriteData, WB_ALUResult, WB_ReadDataOfMem,WB_MemtoReg); //Stalling StallControl StallControl_block(PC_WriteEn,IFID_WriteEn,Stall_flush,EX_MemRead,EX_rt,rs,rt,Opcode); //Jump,bne, JRs // bne: Branch if not equal shift_left_2 shiftleft2_bne(shiftleft2_bne_out, EX_Im16_Ext); Add Add_bne(PCbne,EX_PC4,shiftleft2_bne_out); not #(50) notZero(notZeroFlag,ZeroFlag); and #(50) andbneControl(bneControl,EX_Branch,notZeroFlag); mux2x32to32 muxbneControl( PC4bne,PC4, PCbne, bneControl); // jump shift_left_2 shiftleft2_jump(shiftleft2_jump_out, {6'b0,ID_Instruction[25:0]}); assign PCj = {ID_PC4[31:28],shiftleft2_jump_out[27:0]}; not #(50) notIFIDFlush(notIFID_flush,IFID_flush); and #(50) andJumpFlush(JumpFlush,Jump,notIFID_flush); not #(50) notbne(notbneControl,bneControl); and #(50) andJumpBNE(JumpControl,JumpFlush,notbneControl); mux2x32to32 muxJump( PC4bnej,PC4bne, PCj, JumpControl); // JR: Jump Register assign PCjr = Bus_A_ALU; mux2x32to32 muxJR( PCin,PC4bnej, PCjr, EX_JRControl); endmodule
用于32位流水线MIPS处理器的Verilog Testbench代码:
`timescale 1 ps / 100 fs module MIPSStimulus(); // hzgifts.cn: FPGA projects, Verilog项目, VHDL projects // Verilog project: 32-bit 5-stage Pipelined MIPS处理器 in Verilog // Testbench Verilog code for 32-bit 5-stage Pipelined MIPS处理器 parameter ClockDelay = 5000; reg clk,reset; MIPSpipeline myMIPS(clk, reset); initial clk = 0; always #(ClockDelay/2) clk = ~clk; initial begin reset = 1; #(ClockDelay/4); reset = 0; end endmodule
为了验证流水线式MIPS处理器的运行,我创建了一条指令,其中包括所有数据和控制危害。指令如下图所示添加到指令存储器中,然后在Modelsim中运行仿真。

注意,指令需要转换成二进制数据并保存在"instr.txt"文件。 I converted the above sample instructions into binary data and provided in part 1.
之后,只需在Modelsim中运行仿真,并检查仿真波形和内存编辑器即可。以下是24个时钟周期内正确的仿真波形。
![]() |
前12个周期的仿真波形 |
![]() |
接下来的12个周期的仿真波形 |
如果您对模拟有任何困惑或困难,请发表评论。
请注意,您需要仔细阅读所有必要的部分( Part 1, Part 2和 Part 3),以全面了解流水线MIPS处理器的设计过程,并收集所有必需的Verilog代码,以便能够在仿真中运行流水线MIPS处理器。
您可能会这样:微处理器的Verilog代码
VHDL中的完整8位微控制器
Verilog中的单周期MIPS处理器
用于16位RISC处理器的Verilog代码
MIPS处理器的VHDL代码
什么是FPGA编程? FPGA与软件编程
面向学生的推荐且价格合理的Xilinx FPGA板
面向学生的推荐且价格合理的Altera FPGA板
推荐的 Verilog projects:
2. FIFO存储器的Verilog代码
3. 用于16位单周期MIPS处理器的Verilog代码
4. Verilog HDL中的可编程数字延迟计时器
5. 用于数字电路中基本逻辑组件的Verilog代码
6. 用于32位无符号除法器的Verilog代码
7. 用于定点矩阵乘法的Verilog代码
8. Verilog HDL中的车牌许可证识别
9. 提前进位乘法器的Verilog代码
10。 微处理器的Verilog代码
11。 4x4乘法器的Verilog代码
12 停车场系统的Verilog代码
13 使用Verilog HDL在FPGA上进行图像处理
14。 如何使用Verilog HDL将文本文件加载到FPGA中
15 交通信号灯控制器的Verilog代码
16。 FPGA上的闹钟的Verilog代码
17。 比较器设计的Verilog代码
18岁 D触发器的Verilog代码
19 Full Adder的Verilog代码
20 带testbench的计数器的Verilog代码
21 16位RISC处理器的Verilog代码
22 用于在FPGA上反跳按钮的Verilog代码
23。 如何为双向/输入端口编写Verilog Testbench
3. 用于16位单周期MIPS处理器的Verilog代码
4. Verilog HDL中的可编程数字延迟计时器
5. 用于数字电路中基本逻辑组件的Verilog代码
6. 用于32位无符号除法器的Verilog代码
7. 用于定点矩阵乘法的Verilog代码
8. Verilog HDL中的车牌许可证识别
9. 提前进位乘法器的Verilog代码
10。 微处理器的Verilog代码
11。 4x4乘法器的Verilog代码
12 停车场系统的Verilog代码
13 使用Verilog HDL在FPGA上进行图像处理
14。 如何使用Verilog HDL将文本文件加载到FPGA中
15 交通信号灯控制器的Verilog代码
16。 FPGA上的闹钟的Verilog代码
17。 比较器设计的Verilog代码
18岁 D触发器的Verilog代码
19 Full Adder的Verilog代码
20 带testbench的计数器的Verilog代码
21 16位RISC处理器的Verilog代码
22 用于在FPGA上反跳按钮的Verilog代码
23。 如何为双向/输入端口编写Verilog Testbench
24 Verilog和LogiSim中的Tic Tac Toe游戏
25岁 Verilog中的32位5级流水线MIPS处理器(第1部分)
26 Verilog中的32位5级流水线MIPS处理器(第2部分)
27。 Verilog中的32位5级流水线MIPS处理器(第3部分)
25岁 Verilog中的32位5级流水线MIPS处理器(第1部分)
26 Verilog中的32位5级流水线MIPS处理器(第2部分)
27。 Verilog中的32位5级流水线MIPS处理器(第3部分)
28。 解码器的Verilog代码
29。 复用器的Verilog代码
30岁 Verilog中的N位加法器设计31。 Verilog和VHDL:通过示例解释
32。 FPGA上时钟分频器的Verilog代码
33。 如何在Verilog中生成时钟使能信号
34。 用于PWM发生器的Verilog代码
35岁 Verilog编码与软件编程
36。 使用Moore FSM的序列检测器的Verilog代码
注意,指令需要转换成二进制数据并保存在"instr.txt"
回复删除当我模拟时,modelsim向我显示了充满xxxxxxxxxxxxxxxxx(不要在意)的内存,看起来好像不是'不要将任何东西加载到内存中。't know what I'我做错了。 .txt文件中的数字可能不存在。也许是因为我'm打算在不是testbench的另一个模块中用$ readmemb加载文件?
如果要初始化数据存储器的内容,请创建"data.dat"文件并将readmem命令添加到数据存储代码以对其进行初始化。
删除运行模拟一段时间以查看结果。确保您了解"instr.txt" file.
我没有'看不到PC模块,那又如何呢?
回复删除http://www.hzgifts.cn/2017/06/32-bit-pipelined-mips-processor-in-verilog-1.html
删除它在流水线MIPS处理器的第1部分中提供。
在datamemory模块中,我看到了$ readmemh("data.dat".....),这是什么目的?您能为我解释一下吗?
删除已经有评论了。它用于从.dat文件中读取数据存储器,以防万一您要将存储器内容从.dat或.txt文件输入到数据存储器中的情况。
删除我想在此CPU中添加异常和中断,从一开始我该怎么办
回复删除我想知道。您是否做过异常或中断?你可以帮助我。谢谢
删除我的波形不一样,只有3个条目。时钟,复位和时钟延迟。什么's the reason?
回复删除Can some one give the 数据。dat file format for the given program and instructions
回复删除