单周期CPU功能 利用 Verilog 语言,基于 Xilinx FPGA nexys4 实验平台,设计一个能够执行以下MIPS指令集的单周期类MIPS处理器,要求完成所有支持指令的功能仿真,验证指令执行的正确性 支持基本的算术逻辑运算如 add,sub,and,or,slt 指令 支持基本的内存操作如 lw,sw 指令 支持基本的程序控制如 beq,j 指令
思路 按照逻辑框图实现每个组件的功能,再实现控制器,最后将控制器与功能组件连接,输入reset和clk信号
源代码文件 寄存器 PC.v 1 2 3 4 5 6 7 8 9 10 11 12 13 module PC( input [31 :0 ] D, input Clk, input Reset, output reg [31 :0 ] Q ); always @(posedge Clk or posedge Reset) begin if (Reset) Q =32'h0000000 ; else if (Clk && ~Reset) Q = D; end endmodule
指令存储器 InstrROM.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 module InstrROM( input [4 :0 ] Addr, input Clk, output reg [31 :0 ] Instr ); reg [31 :0 ] regs[0 :31 ]; always @(posedge Clk) begin if (Addr>=0 ) Instr = regs[Addr]; end initial begin regs[0 ] = 32'h00432020 ; regs[1 ] = 32'h8c440004 ; regs[2 ] = 32'hac450008 ; regs[3 ] = 32'h00831022 ; regs[4 ] = 32'h00831025 ; regs[5 ] = 32'h00831024 ; regs[6 ] = 32'h0083102a ; regs[7 ] = 32'h10630001 ; regs[8 ] = 32'h8c620000 ; regs[9 ] = 32'h10640001 ; regs[10 ] = 32'hac620000 ; regs[11 ] = 32'h08000000 ; end endmodule
控制器 Controller.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 module Controller( input [5 :0 ] OpCode, input [5 :0 ] Funct, output J, output B, output RegDst, output RegWr, output ALUSrc, output MemWr, output Mem2Reg, output [3 :0 ] ALUCtr ); wire [1 :0 ] ALUOp; MainCtr U0(OpCode, J, B, RegDst, RegWr, ALUSrc, MemWr, Mem2Reg, ALUOp); ALUCtr U1(ALUOp,Funct,ALUCtr);endmodule
主控制器 Mainctr.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 module MainCtr ( input [5 :0 ] OpCode, output J, output B, output RegDst, output RegWr, output ALUSrc, output MemWr, output Mem2Reg, output [1 :0 ] ALUOp ); reg [8 :0 ] outputtemp; assign RegDst = outputtemp[8 ]; assign ALUSrc = outputtemp[7 ]; assign Mem2Reg = outputtemp[6 ]; assign RegWr = outputtemp[5 ]; assign MemWr = outputtemp[4 ]; assign B = outputtemp[3 ]; assign J = outputtemp[2 ]; assign ALUOp = outputtemp[1 :0 ]; always @(OpCode) begin case (OpCode) 6'b000010 : outputtemp = 9'bxxx0001xx ; 6'b000000 : outputtemp = 9'b100100010 ; 6'b100011 : outputtemp = 9'b011100000 ; 6'b101011 : outputtemp = 9'bx1x010000 ; 6'b000100 : outputtemp = 9'bx0x001001 ; 6'b001100 : outputtemp = 9'b010100011 ; default : outputtemp = 9'b000000000 ; endcase end endmodule
ALU控制器 ALUControl.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 module ALUCtr ( input [1 :0 ] ALUOp, input [5 :0 ] Funct, output reg [3 :0 ] ALUCtr ); always @(ALUOp or Funct) begin casex ({ALUOp, Funct}) 8'b00xxxxxx : ALUCtr[3 :0 ] = 4'b0010 ; 8'b01xxxxxx : ALUCtr[3 :0 ] = 4'b0110 ; 8'b10xx0000 : ALUCtr[3 :0 ] = 4'b0010 ; 8'b10xx0010 : ALUCtr[3 :0 ] = 4'b0110 ; 8'b10xx0100 : ALUCtr[3 :0 ] = 4'b0000 ; 8'b11xxxxxx : ALUCtr[3 :0 ] = 4'b0000 ; 8'b10xx0101 : ALUCtr[3 :0 ] = 4'b0001 ; 8'b10xx1010 : ALUCtr[3 :0 ] = 4'b0111 ; default : ALUCtr[3 :0 ] = 4'b0000 ; endcase end endmodule
多路复用器 Mux2_1.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 module Mux2_1_32bit( input [31 :0 ] In1, input [31 :0 ] In2, input sel, output reg [31 :0 ] Out ); always @(*) begin if (sel == 0 ) Out[31 :0 ] = In1; else if (sel == 1 ) Out[31 :0 ] = In2; end endmodule module Mux2_1_5bit( input [4 :0 ] In1, input [4 :0 ] In2, input sel, output reg [4 :0 ] Out ); always @(*) begin if (sel == 0 ) Out[4 :0 ] = In1[4 :0 ]; else if (sel == 1 ) Out[4 :0 ] = In2[4 :0 ]; end endmodule
3选1多路复用器 Mux3_1.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 module Mux3_1( input [31 :0 ] In1, input [31 :0 ] In2, input [31 :0 ] In3, input [1 :0 ] sel, output [31 :0 ] Out ); wire [31 :0 ] Out1; Mux2_1_32bit U0(In1,In2,sel[0 ],Out1); Mux2_1_32bit U1(Out1,In3,sel[1 ],Out);endmodule
左移运算器 LeftShift.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 module LeftShift_32_32_2( input [31 :0 ] In, output reg [31 :0 ] Out ); always @(*) begin Out = {In[29 :0 ],2'b00 }; end endmodule module LeftShift_26_28_2( input [25 :0 ] In, output reg [27 :0 ] Out ); always @(*) begin Out = {In[25 :0 ],2'b00 }; end endmodule module LeftShift_26_29_3( input [25 :0 ] In, output reg [28 :0 ] Out ); always @(*) begin Out = {In[25 :0 ],3'b000 }; end endmodule
加法器 Adder.v 1 2 3 4 5 6 7 8 module Adder( input [31 :0 ] In1, input [31 :0 ] In2, output reg [31 :0 ] Out ); always @(*) Out = In1 + In2;endmodule
寄存器文件 RegFile.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 module RegFile( input [4 :0 ] RsAddr, input [4 :0 ] RtAddr, input [4 :0 ] WrAddr, input [31 :0 ] DataIn, input RegWr, input Clk, output [31 :0 ] RsData, output [31 :0 ] RtData ); reg [31 :0 ] regs[0 :31 ]; assign RsData = (RsAddr == 5'b0 ) ? 32'b0 : regs[RsAddr]; assign RtData = (RtAddr == 5'b0 ) ? 32'b0 : regs[RtAddr]; always @ (posedge Clk) begin if (RegWr == 1 ) begin regs[WrAddr] = DataIn; end end initial begin :loop integer i; for (i=0 ;i<32 ;i=i+1 ) regs[i] = 4 *i; end endmodule
符号扩展模块 SignedExtend.v 1 2 3 4 5 6 7 8 9 10 11 module SignedExtend( input [15 :0 ] In, output reg [31 :0 ] Out ); always @(*) begin if (In>=0 ) Out[31 :0 ] = {16'h0000 ,In}; else if (In<0 ) Out[31 :0 ] = {16'hffff ,In}; end endmodule
32位宽算术逻辑运算单元 ALU.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 module ALU( input signed [31 :0 ] in1, input signed [31 :0 ] in2, input [3 :0 ] ALUCtr, output reg [31 :0 ] Res, output reg Zero ); always @(in1 or in2 or ALUCtr) begin case (ALUCtr) 4'b0110 : begin Res = in1 - in2; end 4'b0010 : begin Res = in1 + in2; end 4'b0000 : begin Res = in1 & in2; end 4'b0001 : begin Res = in1 | in2; end 4'b0111 : begin Res = (in1<in2)?1 :0 ; end default : begin Res = 0 ; end endcase Zero = (Res==0 )?1 :0 ; end endmodule
位拼接器 Concat.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 module Concat_32( input [3 :0 ] In1, input [27 :0 ] In2, output reg [31 :0 ] Out ); always @(*) begin Out = {In1,In2}; end endmodule module Concat_2( input In1, input In2, output reg [1 :0 ] Out ); always @(*) begin Out = {In1,In2}; end endmodule
数据存储器 DataRAM.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 module DataRAM( input [4 :0 ] Addr, output [31 :0 ] DataOut, input [31 :0 ] DataIn, input MemWR, input Clk ); reg [31 :0 ] regs[0 :31 ]; assign DataOut = regs[Addr]; always @(posedge Clk) begin if ((Addr>=0 ) && MemWR) regs[Addr] = DataIn; end initial begin :loop integer i; for (i=0 ;i<32 ;i=i+1 ) regs[i] = 4 *i; end endmodule
整体实现简单指令集单周期MIPS微处理器 MIPSCPU.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 module MIPSCPU( input Clk, input Reset ); wire [31 :0 ] PC_D; wire [31 :0 ] PC_Q; PC U0(PC_D,Clk,Reset,PC_Q); wire [31 :0 ] Instr; InstrROM U1(PC_Q[6 :2 ],!Clk,Instr); wire J; wire B; wire RegDst; wire RegWr; wire ALUSrc; wire MemWr; wire Mem2Reg; wire [3 :0 ] ALUCtr; reg [5 :0 ] OpCode; always @(*) OpCode = Instr[31 :26 ]; Controller U2(OpCode,Instr[5 :0 ],J,B,RegDst,RegWr,ALUSrc,MemWr,Mem2Reg,ALUCtr); wire [31 :0 ] SignedExtendOut; SignedExtend U3(Instr[15 :0 ],SignedExtendOut[31 :0 ]); wire [4 :0 ] Mux2_1_5bitOut; Mux2_1_5bit U4(Instr[20 :16 ],Instr[15 :11 ],RegDst,Mux2_1_5bitOut); wire [27 :0 ] LeftShift_26_28_2_Out; LeftShift_26_28_2 U5(Instr[25 :0 ],LeftShift_26_28_2_Out); wire [31 :0 ] AdderOut1; Adder U6(32'h00000004 ,PC_Q,AdderOut1); wire [31 :0 ] Concat_32_Out; Concat_32 U7(AdderOut1[31 :28 ],LeftShift_26_28_2_Out,Concat_32_Out); wire [31 :0 ] RegFile_DataIn; wire [31 :0 ] RegFile_RsData; wire [31 :0 ] RegFile_RtData; RegFile U8(Instr[25 :21 ],Instr[20 :16 ],Mux2_1_5bitOut,RegFile_DataIn,RegWr,Clk,RegFile_RsData,RegFile_RtData); wire [31 :0 ] LeftShift_32_32_2_Out; LeftShift_32_32_2 U9(SignedExtendOut,LeftShift_32_32_2_Out); wire [31 :0 ] AdderOut2; Adder U10(AdderOut1,LeftShift_32_32_2_Out,AdderOut2); wire [31 :0 ] Mux2_1_32bitOut; Mux2_1_32bit U11(RegFile_RtData,SignedExtendOut,ALUSrc,Mux2_1_32bitOut); wire [31 :0 ] ALU_Res; wire Zero; ALU U12(RegFile_RsData,Mux2_1_32bitOut,ALUCtr,ALU_Res,Zero); wire [1 :0 ] Concat_2_Out; Concat_2 U13(J,B&Zero,Concat_2_Out); Mux3_1 U14(AdderOut1,AdderOut2,Concat_32_Out,Concat_2_Out,PC_D); wire [31 :0 ] DataRAM_DataOut; DataRAM U15(ALU_Res[6 :2 ],DataRAM_DataOut,RegFile_RtData,MemWr,Clk); Mux2_1_32bit U16(ALU_Res,DataRAM_DataOut,Mem2Reg,RegFile_DataIn);endmodule
仿真代码文件 寄存器 PCsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 module PCsim( output [31 :0 ] Q ); reg [31 :0 ] D; reg Clk; reg Reset; PC U0(D,Clk,Reset,Q); parameter PERIOD = 10 ; always begin Clk = 1'b0 ; #(PERIOD/2) Clk = 1'b1 ; #(PERIOD/2) ; end initial begin Reset = 0 ; D = 0 ; #10 D = 1 ; #10 D = 2 ; #10 D = 3 ; #10 D = 4 ; #20 Reset = 1 ; end endmodule
指令存储器 InstrROMsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 module InstrROMsim( output [31 :0 ] Instr ); reg [4 :0 ] Addr; reg Clk; InstrROM U0(Addr,Clk,Instr); parameter PERIOD = 10 ; always begin Clk = 1'b0 ; #(PERIOD/2) Clk = 1'b1 ; #(PERIOD/2) ; end initial begin :loop integer i; Addr = 0 ; for (i=1 ;i<31 ;i=i+1 )begin #10 Addr = i; end end endmodule
控制器 Controllersim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 module Controllersim( output J, output B, output RegDst, output RegWr, output ALUSrc, output MemWr, output Mem2Reg, output [3 :0 ] ALUCtr ); reg [5 :0 ] OpCode; reg [5 :0 ] Funct; Controller U0(OpCode, Funct, J, B, RegDst, RegWr, ALUSrc, MemWr, Mem2Reg, ALUCtr); initial begin OpCode = 6'h00 ; Funct = 6'h20 ; #10 Funct = 6'h22 ; #10 Funct = 6'h24 ; #10 Funct = 6'h25 ; #10 Funct = 6'h2a ; #10 OpCode = 6'h23 ; Funct = 6'h20 ; #10 Funct = 6'h22 ; #10 Funct = 6'h24 ; #10 Funct = 6'h25 ; #10 Funct = 6'h2a ; #10 OpCode = 6'h2b ; Funct = 6'h20 ; #10 Funct = 6'h22 ; #10 Funct = 6'h24 ; #10 Funct = 6'h25 ; #10 Funct = 6'h2a ; #10 OpCode = 6'h04 ; Funct = 6'h20 ; #10 Funct = 6'h22 ; #10 Funct = 6'h24 ; #10 Funct = 6'h25 ; #10 Funct = 6'h2a ; #10 OpCode = 6'h02 ; Funct = 6'h20 ; #10 Funct = 6'h22 ; #10 Funct = 6'h24 ; #10 Funct = 6'h25 ; #10 Funct = 6'h2a ; end endmodule
主控制器 MainCtrsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 module MainCtrsim( output J, output B, output RegDst, output RegWr, output ALUSrc, output MemWr, output Mem2Reg, output [1 :0 ] ALUOp ); reg [5 :0 ] OpCode; MainCtr U0(OpCode, J, B, RegDst, RegWr, ALUSrc, MemWr, Mem2Reg, ALUOp); initial begin OpCode = 8'h00 ; #10 OpCode = 8'h23 ; #10 OpCode = 8'h2b ; #10 OpCode = 8'h04 ; #10 OpCode = 8'h02 ; end endmodule
ALU控制器 ALUCtrsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 module ALUCtrsim( output [3 :0 ] ALUCtr ); reg [1 :0 ] ALUOp; reg [5 :0 ] Funct; ALUCtr U0(ALUOp,Funct,ALUCtr); initial begin ALUOp = 0 ; Funct = 6'h20 ; #10 Funct = 6'h22 ; #10 Funct = 6'h24 ; #10 Funct = 6'h25 ; #10 Funct = 6'h2a ; #10 ALUOp = 1 ; Funct = 6'h20 ; #10 Funct = 6'h22 ; #10 Funct = 6'h24 ; #10 Funct = 6'h25 ; #10 Funct = 6'h2a ; #10 ALUOp = 2 ; Funct = 6'h20 ; #10 Funct = 6'h22 ; #10 Funct = 6'h24 ; #10 Funct = 6'h25 ; #10 Funct = 6'h2a ; end endmodule
多路复用器 Mux2_1sim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 module Mux2_1sim( output wire [4 :0 ] Out0, output wire [31 :0 ] Out1 ); reg [31 :0 ] In1,In2; reg sel; reg [4 :0 ] In1_5bit,In2_5bit; always @(*)begin In1_5bit = In1[4 :0 ]; In2_5bit = In2[4 :0 ]; end Mux2_1_5bit U0(In1_5bit,In2_5bit,sel,Out0); Mux2_1_32bit U1(In1,In2,sel,Out1); initial begin In1 = 32'h12345678 ; In2 = 32'h87654321 ; sel = 0 ; #10 sel = 1 ; end endmodule
3选1多路复用器 Mux3_1sim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 module Mux3_1sim( output [31 :0 ] Out ); reg [31 :0 ] In1,In2,In3; reg [1 :0 ] sel; Mux3_1 U0(In1,In2,In3,sel,Out); initial begin In1 = 32'h12345678 ; In2 = 32'h87654321 ; In3 = 32'h33333333 ; sel = 2'h0 ; #10 sel = 2'h1 ; #10 sel = 2'h2 ; #10 sel = 2'h3 ; end endmodule
左移运算器 LeftShiftsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 module LeftShiftsim( output [31 :0 ] Out1, output [27 :0 ] Out2, output [28 :0 ] Out3 ); reg [31 :0 ] In; reg [31 :0 ] In1; reg [25 :0 ] In2; reg [25 :0 ] In3; always @(*)begin In1 = In; In2 = In[25 :0 ]; In3 = In[25 :0 ]; end LeftShift_32_32_2 U0(In1,Out1); LeftShift_26_28_2 U1(In2,Out2); LeftShift_26_29_3 U2(In3,Out3); initial begin In = 32'h22222222 ; end endmodule
加法器 Addersim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 module Addersim( output [31 :0 ] Out ); reg [31 :0 ] In1,In2; Adder U0(In1,In2,Out); initial begin In1 = 32'h00000004 ; In2 = 32'h00000008 ; #10 In1 = 32'h44444444 ; In2 = 32'h88888888 ; end endmodule
寄存器文件 RegFilesim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 module RegFilesim( output [31 :0 ] RsData, output [31 :0 ] RtData ); reg [4 :0 ] RsAddr; reg [4 :0 ] RtAddr; reg [4 :0 ] WrAddr; reg RegWr; reg [31 :0 ] DataIn; reg Clk; parameter PERIOD = 10 ; always begin Clk = 1'b0 ; #(PERIOD/2) Clk = 1'b1 ; #(PERIOD/2) ; end initial begin :loop integer i; RsAddr = 0 ; RtAddr = 0 ; WrAddr = 0 ; DataIn = 0 ; RegWr = 1 ; for (i=1 ;i<9 ;i=i+1 ) begin #10 WrAddr = i; DataIn = 4 *i; end #10 WrAddr = 9 ; DataIn = 36 ; #10 RtAddr = 9 ; RegWr = 0 ; for (i=0 ;i<9 ;i=i+1 )begin #10 RsAddr = i+1 ; RtAddr = 8 -i; end end RegFile U0(RsAddr,RtAddr,WrAddr,DataIn,RegWr,Clk,RsData,RtData); endmodule
符号扩展模块 SignedExtendsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 module SignedExtendsim( output [31 :0 ] Out ); reg [15 :0 ] In; SignedExtend U0(In,Out); initial begin In = 16'h1234 ; #10 In = 16'h8234 ; end endmodule
32位宽算术逻辑运算单元 ALUsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 module ALUsim( output [31 :0 ] Res, output Zero ); reg [31 :0 ] in1,in2; reg [3 :0 ] ALUCtr; ALU U0(in1,in2,ALUCtr,Res,Zero); initial begin in1 = 32'h00000004 ; in2 = 32'h00000008 ; ALUCtr = 0 ; #10 ALUCtr = 1 ; #10 ALUCtr = 2 ; #10 ALUCtr = 6 ; #10 ALUCtr = 7 ; #10 in1 = 32'h44444444 ; in2 = 32'h88888888 ; ALUCtr = 0 ; #10 ALUCtr = 1 ; #10 ALUCtr = 2 ; #10 ALUCtr = 6 ; #10 ALUCtr = 7 ; #10 in1 = 32'h99999999 ; in2 = 32'h88888888 ; ALUCtr = 0 ; #10 ALUCtr = 1 ; #10 ALUCtr = 2 ; #10 ALUCtr = 6 ; #10 ALUCtr = 7 ; end endmodule
位拼接器 Concatsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 module Concatsim( output [31 :0 ] Out0, output [1 :0 ] Out1 ); reg [31 :0 ] In1; reg [31 :0 ] In2; reg [4 :0 ] In11; reg [27 :0 ] In12; reg In21; reg In22; always @(*)begin In11 = In1[31 :28 ]; In12 = In2[27 :0 ]; In21 = In1[0 ]; In22 = In2[0 ]; end Concat_32 U0(In11,In12,Out0); Concat_2 U1(In21,In22,Out1); initial begin In1 = 32'h12345678 ; In2 = 32'h87654321 ; end endmodule
数据存储器 DataRAMsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 module DataRAMsim( output [31 :0 ] DataOut ); reg [4 :0 ] Addr; reg [31 :0 ] DataIn; reg Clk; reg MemWR; DataRAM U0(Addr,DataOut,DataIn,MemWR,Clk); parameter PERIOD = 10 ; always begin Clk = 1'b0 ; #(PERIOD/2) Clk = 1'b1 ; #(PERIOD/2) ; end initial begin MemWR = 1 ; Addr = 0 ; DataIn = 0 ; #10 Addr = 1 ; DataIn = 4 ; #10 Addr = 2 ; DataIn = 8 ; #10 Addr = 3 ; DataIn = 12 ; #10 Addr = 4 ; DataIn = 16 ; #10 Addr = 5 ; DataIn = 20 ; #10 Addr = 6 ; DataIn = 24 ; #10 Addr = 7 ; DataIn = 28 ; #10 Addr = 8 ; DataIn = 32 ; #10 Addr = 9 ; DataIn = 36 ; #10 MemWR = 0 ; Addr = 0 ; DataIn = 36 ; #10 Addr = 1 ; DataIn = 36 ; #10 Addr = 2 ; DataIn = 36 ; #10 Addr = 3 ; DataIn = 36 ; #10 Addr = 4 ; DataIn = 36 ; #10 Addr = 5 ; DataIn = 36 ; #10 Addr = 6 ; DataIn = 36 ; #10 Addr = 7 ; DataIn = 36 ; #10 Addr = 8 ; DataIn = 36 ; #10 Addr = 9 ; DataIn = 36 ; end endmodule
整体实现简单指令集单周期MIPS微处理器 MIPSCPUsim.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 module MIPSCPUsim( ); reg Clk; reg Reset; MIPSCPU U0(Clk,Reset); parameter PERIOD = 10 ; always begin Clk = 1'b0 ; #(PERIOD/2) Clk = 1'b1 ; #(PERIOD/2) ; end initial begin Reset = 0 ; #10 Reset = 1 ; #10 Reset = 0 ; end endmodule
仿真过程 InstrROM 从地址 0 开始的连续 11 个存储单元存放机器指令1 2 3 4 5 6 7 8 9 10 11 00432020 8c440004 ac420008 00831022 00831025 00831024 0083102a 10830001 08000000 8c620000 08000000
对应汇编指令如下:1 2 3 4 5 6 7 8 9 10 11 12 main: add $4 ,$2 ,$3 lw $4 ,4 ($2 ) sw $2 ,8 ($2 ) sub $2 ,$4 ,$3 or $2 ,$4 ,$3 and $2 ,$4 ,$3 slt $2 ,$4 ,$3 beq $4 ,$3 ,exit j main exit : lw $2 ,0 ($3 ) j main
前面 7 条指令都是顺序往下直行,到第七条指令时符合条件则跳转。$3 为复位时的初始值 0,$4 为从数据存储器装载的值,若数据存储器地址为 4 的存储字的初始值不为 0,则顺序执行所有指令之后在 0~8 号指令之间循环;
若数据存储器地址为 4 的存储字初始值为 0,则跳过第 8 条指令,进行到 9 号指令,再循环。
观察 PC 的变化可知,PC 先从 0,4,8,12,16,20,24,28,前 7 条指令顺序执行,数据存储器第 0 号地址的存储字初始值为 0,执行第 7 条指令的时候 Zero 的值为 1,说明两寄存器的值相等,符合跳转条件,故跳过了第 8 条指令,进入了第9 条指令,也就是地址变为 36。执行完 9,10 条指令后又返回原循环。
之后指令执行的过程中,由于 RegFile 以及 DataRAM 前 32 个存储单元存储的初始值为单元地址*4,都不为 0,所以程序在 0~7 条语句之间循环,PC 在 0,4,8,12,16,20,24,28 之间循环跳转。
第一条指令为 R 型指令,高 6 位为 000000,低 6 位功能码为 100000,译码译出的 ALUCtr 为 0010,即 2,执行加运算指令。
第二条指令为 I 型指令,高 6 位为 100011,译码译出的 ALUCtr 也为 0010,对应 lw 指令。低 16 位 Imm 域为常数地址 0x0004,符号扩展后也为 4,在 ALU中进行加运算,得到的地址在数据存储器中读到相应数据再写到寄存器文件中。
第三条指令为 I 型指令,高 6 位为 101011,译码译出的 ALUCtr 也为 0010,对应 sw 指令。 低 16 位 Imm 域为常数地址 0x0008,符号扩展后也为 8,在 ALU中进行加运算,得到地址,再在数据存储器把数据写到相应的地址中。
第 4,5,6 条指令也为 R 型指令,低 6 位功能码不同,分别执行 sub,or,and,slt不同功能。
第七条指令为 I 型指令,因为 zero 为 1,所以跳转到 exit 语句的位置。
第八条指令为 J 型指令,无条件跳转到 main 语句也就是第 0 条语句的位置,所以 PC 又恢复为 0。
第一条指令的 Rs 对应$2,Rt 对应$3,RsData=8=24,符合地址都是 2 的整数倍, RtData=0xc=12=3 4,相加后的结果为 0x14=20=8+12;
第二、三条指令的 Rs 都是$2,二的偏移地址为 4,三的偏移地址为 8,对应的SignExtended 分别为 4 和 8。
之后的 sub,or,and,slt 都为 R 型指令,由于$4 与$3 对应的值相等,都为 0xc,他们相减后为 0,相与、相或之后的结果相同,左移之后右边补 0,所以最终得到的是 0。
再执行 beq 指令,$4,$3 寄存器对应的值相等,Zero 输出的值为 1,跳转到exit 指令处,再往下执行一条 j main ,之后回到第 0 条指令。