verilog.中的流水线MIPS处理器(第3部分)

该项目是为32位流水线提供fun88英超代码 MIPS处理器。在 part 2,我介绍了单周期MIPS数据路径的所有VeriLog代码。 

在这部分中,添加了流水线寄存器以完成 流水线MIPS处理器. verilog. 将呈现完整的32位流水线MIP处理器的代码。 

以下是32位5级流水线的完整数据路径 MIPS处理器 添加流水线寄存器后, 转发 单位,摊位控制单元和冲洗控制单元到单循环数据路径。转发,失速控制和冲洗控制单元旨在解决流水线MIPS处理器中的数据和控制危险。以下是危险求解模块和fun88英超中的完整流水线MIPS处理器的详细说明。

Pipelined MIPS处理器的fun88英超代码
流水线MIPS处理器DataPath
转发单位:
转发单元旨在解决流水线MIPS处理器中的数据危险。当检测到数据危险时,ALU输出端的正确数据被转发到ALU的输入。当前指令的源寄存器(ex_rs或ex_rt)与前一个指令的目标寄存器(MEM_WRITEREGISTER或EX_WRITERGISTER)相同时检测到数据危险。
Pipelined MIPS处理器的fun88英超代码

转发单元的fun88英超代码:

`timescale 1 ps / 100 fs
// yl315.net: FPGA projects, fun88英超 Projects, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// Forwarding Unit
module ForwardingUnit(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输入的2×32到32多路复用器变为3x32至32多路复用器。

verilog.代码为多路复用器:

`timescale 1 ps / 100 fs
// yl315.net: FPGA projects, fun88英超 Projects, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// 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  XORI和LW指令ID_RT的ID阶段的即将到来的指令的源寄存器(ID​​_RS或ID_RT)(其中RT是目的地寄存器与XORI和LW的源寄存器)。 
Pipelined MIPS处理器的fun88英超代码
Pipelined MIPS处理器的fun88英超代码

verilog. Code for Stall控制单元:

`timescale 1 ps / 100 fs
// yl315.net: FPGA projects, verilog.项目, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// 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阶段中的指令。

Flush控制单元的fun88英超代码:

// yl315.net: FPGA projects, fun88英超 Projects, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// 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
// yl315.net: FPGA projects, fun88英超 Projects, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// 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.
Pipelined MIPS处理器的fun88英超代码

WB_Forward单元的fun88英超代码:

`timescale 1 ps / 100 fs
// yl315.net: FPGA projects, fun88英超 Projects, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// Write Back Forwarding 
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);
// yl315.net: FPGA projects, fun88英超 Projects, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// 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处理器的所有必要部分的fun88英超代码。 

让我们来获取32位管道MIPS处理器的顶级fun88英超代码:

`timescale 1 ps / 100 fs
// yl315.net: FPGA projects, verilog.项目, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// Top level fun88英超 code for 32-bit 5-stage Pipelined MIPS Processor 
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);
//  Forwarding unit转发Unit Forwarding_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

verilog. TestBench代码为32位管道MIPS处理器:

`timescale 1 ps / 100 fs
module MIPSStimulus();
// yl315.net: FPGA projects, fun88英超 Projects, VHDL projects
// fun88英超 project: 32-bit 5-stage Pipelined MIPS Processor in fun88英超 
// Testbench fun88英超 code for 32-bit 5-stage Pipelined MIPS Processor 
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中运行仿真。 
Pipelined MIPS处理器的fun88英超代码
注意,指令需要转换为二进制数据并保存在其中"instr.txt..."文件。 I converted the above sample instructions into binary data and provided in part 1
之后,只需在ModelSIM中运行模拟,并检查模拟波形和内存编辑器。以下是24个时钟周期中的正确仿真波形。
Pipelined MIPS处理器的fun88英超代码
用于前12个循环的仿真波形

Pipelined MIPS处理器的fun88英超代码
用于接下来的12个周期的仿真波形
如果您对模拟有任何混淆或困难,请留下评论。

有人指出,您需要通过所有必要的部分( Part 1, Part 2, 和 Part 3)为了充分了解设计流水线MIP处理器的过程,并收集所有所需的fun88英超代码,以便能够在仿真中运行流水线MIPS处理器。
你可能喜欢这个:
微控制器的fun88英超代码
VHDL中的完整8位微控制器
verilog.中的单周期MIPS处理器
16位RISC处理器的fun88英超代码
MIPS处理器的VHDL代码
什么是fpga编程? FPGA VS软件编程
推荐和经济实惠的学生Xilinx FPGA板
推荐和负担得起的Altera FPGA董事会为学生

推荐的 fun88英超 projects:
2. FIFO记忆的fun88英超代码
3. 16位单循环MIPS处理器的fun88英超代码
4. verilog. HDL中的可编程数字延迟计时器
5. 数字电路中基本逻辑组件的fun88英超代码
6. 32位无符号分频器的fun88英超代码
7. 用于固定点矩阵乘法的fun88英超代码
8. 在fun88英超 HDL中的板牌识别
9. 携带外观前方乘法器的fun88英超代码
10。 微控制器的fun88英超代码
11.  4x4乘法器的fun88英超代码
12. 停车系统的fun88英超代码
13。 使用fun88英超 HDL对FPGA的图像处理
14。 如何使用fun88英超 HDL将文本文件加载到FPGA中
15。 交通灯控制器的fun88英超代码
16。 FPGA闹钟的fun88英超代码
17。 比较器设计的fun88英超代码
18。 VERILOG代码D触发器
19。 完整加法器的fun88英超代码
20。 与测试台的计数器的fun88英超代码
21。 16位RISC处理器的fun88英超代码
22。 FPGA上的按钮的fun88英超代码
23。 如何为双向/ inout端口编写fun88英超 TestBench
30.  fun88英超中的n位加法器设计
31。 verilog. vs vhdl.:通过示例解释
32。 FPGA时钟分频器的fun88英超代码
33。 如何在fun88英超中生成时钟使能信号
34。 PWM生成器的fun88英超代码
35。 verilog.编码VS软件编程
36。 使用MOORE FSM的序列检测器的fun88英超代码
FPGA fun88英超 VHDL课程

10评论:

  1. 注意,指令需要转换为二进制数据并保存在其中"instr.txt"
    当我模拟时,ModelSim向我填充XXXXXXXXXXXXXXXXXX(不在乎)的内存,看起来像ISN'将任何东西加载到记忆中。我唐't know what I'做错了。可能不是.txt文件中的数字。也许是因为我'm打算在另一个不是测试禁止的模块中使用$ readmemb加载文件?

    回复删除
    答案
    1. 如果要初始化数据内存的内容,请创建"data.dat"文件并将ReadMem命令添加到数据存储器代码以初始化它。
      运行模拟一段时间才能查看结果。确保您了解的说明"instr.txt" file.

      删除
  2. 我没有'T看到PC模块,那么那呢?

    回复删除
    答案
    1. http://www.yl315.net/2017/06/32-bit-pipelined-mips-processor-in-verilog-1.html
      它设置在流水线MIPS处理器的第1部分中。

      删除
    2. 在DatameMory模块中,我看到了$ ReadMemh("data.dat".....),所以这个目的是什么?,你能为我解释一下吗?

      删除
    3. 它已经评论了。它用于从.dat文件读取数据存储器,以便您要从.dat或.txt文件从.dat或.txt文件输入到数据存储器的情况下。

      删除
  3. 我想在这个CPU中添加异常并中断,从头开始,我应该怎么做

    回复删除
    答案
    1. 我想知道。你对例外或中断做了什么?你可以帮助我。谢谢

      删除
  4. 我的波形不一样,它只有3个条目。 CLK,RESET和CLOCKDELAY。什么's the reason?

    回复删除
  5. 可以为给定的程序和指令提供一些人提供数据.DAT文件格式

    回复删除

趋势FPGA项目