电子信息与通信学院实验报告实验名称微机原理实验课程名称类MIPS单周期微处理器设计姓名周乃鼎学号U201313768日期2015.11.13地点南一楼东203成绩教师左冬红一、实验目的1.了解微处理器的基本结构2.掌握哈佛结构的计算机工作原理3.学会设计简单的微处理器4.了解软件控制硬件工作的基本原理二、实验任务利用HDL语言,基于XilinxFPGAnexys4实验平台,设计一个能够执行以下MIPS指令集的单周期类MIPS处理器,要求完成所有支持指令的功能仿真,验证指令执行的正确性,要求编写汇编程序将本人学号的ASCII码存入RAM的连续内存区域–支持基本的内存操作如lw,sw指令–支持基本的算术逻辑运算如add,sub,and,or,slt,addi指令–支持基本的程序控制如beq,j指令三、基本原理addadd指令存储器地址总线指令PC4寄存器组读寄存器1地址读寄存器2地址写寄存器地址写数据寄存器1数据寄存器2数据符号扩展MUXALUMUX数据存储器数据总线数据总线地址总线左移两位+PC的高4位28位26位32位MUXMUXzero16位32位左移两位MUX指令[25:0]指令[5:0]指令[15:0]指令[15:11]指令[20:16]指令[25:21]ALU控制译码JumpBranchALUSrcMemToRegRegDstRegWriteMemWriteMemReadALUOp[1:0]01011001控制器指令[31:26]四、各个硬件模块设计1.寄存器组寄存器组是指令操作的主要对象,MIPS处理器里一共有32个32位的寄存器,故可以声明一个包含32个32位的寄存器数组。读寄存器时需要Rs,Rd的地址,得到其数据。写寄存器Rd时需要所写地址,所写数据,同时需要写使能。以上所有操作需要在时钟和复位信号控制下操作。故寄存器组设计如下:Verilog代码如下,细节见注释:moduleregFile(inputclk,inputreset,input[31:0]regWriteData,input[4:0]regWriteAddr,inputregWriteEn,output[31:0]RsData,output[31:0]RtData,input[4:0]RsAddr,input[4:0]RtAddr);reg[31:0]regs[0:31];//寄存器组//根据地址读出Rs、Rt寄存器数据assignRsData=(RsAddr==5'b0)?32'b0:regs[RsAddr];assignRtData=(RtAddr==5'b0)?32'b0:regs[RtAddr];integeri;always@(posedgeclk)//时钟上升沿操作inputclkinputresetinputRsAddr[4:0]inputRtAddr[4:0]inputregWriteData[31:0]inputregWriteAddr[4:0]inputregWriteEnoutputRsData[31:0]outputRtData[31:0]beginif(!reset)beginif(regWriteEn==1)//写使能信号为1时写操作beginregs[regWriteAddr]=regWriteData;//写入数据endendelsebeginfor(i=0;i32;i=i+1)regs[i]=0;//所有寄存器赋值为0,复位endendendmodule2.控制器模块:控制器模块输入为指令的操作码opCode段,输出各个复用器、存储器读写等的信号,控制数据通路的正常进行。根据指令的不同,输出不同的信号即可。Verilog代码如下,细节见注释:modulectr(input[5:0]opCode,outputregregDst,outputregaluSrc,outputregmemToReg,outputregregWrite,outputregmemRead,outputregmemWrite,outputregbranch,outputreg[1:0]aluop,outputregjmp);always@(opCode)//当opCode变化时输出不同信号begincase(opCode)6'b000010://J型指令beginregDst=0;aluSrc=0;memToReg=0;regWrite=0;memRead=0;inputopcode[5:0]outputregDstoutputaluSrcoutputmemToRegoutputregWriteoutputmemReadoutputmemWriteoutputbranchoutputaluop[1:0]outputjmpmemWrite=0;branch=0;aluop=2'b00;jmp=1;end6'b000000://R型指令beginregDst=1;aluSrc=0;memToReg=0;regWrite=1;memRead=0;memWrite=0;branch=0;aluop=2'b10;jmp=0;end6'b100011://lwbeginregDst=0;aluSrc=1;memToReg=1;regWrite=1;memRead=1;memWrite=0;branch=0;aluop=2'b00;jmp=0;end6'b101011://swbeginregDst=0;aluSrc=1;memToReg=0;regWrite=0;memRead=0;memWrite=1;branch=0;aluop=2'b00;jmp=0;end6'b000100:beq指令beginregDst=0;aluSrc=0;memToReg=0;regWrite=0;memRead=0;memWrite=0;branch=1;aluop=2'b01;jmp=0;end6'b001000://addi指令beginregDst=0;aluSrc=1;memToReg=0;regWrite=1;memRead=0;memWrite=0;branch=0;aluop=2'b00;jmp=0;enddefault://缺省值beginregDst=0;aluSrc=0;memToReg=0;regWrite=0;memRead=0;memWrite=0;branch=0;aluop=2'b00;jmp=0;endendcaseendendmodule3.ALU控制译码ALU主要执行5种操作:与,或,加,减,小于设置。这五种操作可以使用四位的编码表示:0000,0001,0010,01110,0111。指令不同,则对应的ALU运算不同,所以该模块需要根据指令来控制ALU进行正确的运算。由于lw,sw,addi指令均要求ALU执行加操作,则可分为一类,编码00;由于beq指令要求ALU执行减操作,则分为一类,编码01;最后一类是R型指令,可以编码为10;但不同的R型指令对应不同的ALU运算,故需要再通过指令的功能码进一步确定ALU的运算。最终该模块即实现2位操作码以及6位功能码输出4位ALU控制信号码。指令与ALU操作码及功能码的对应关系如下:Verilog代码如下,细节见注释:modulealuctr(input[1:0]ALUOp,input[5:0]funct,outputreg[3:0]ALUCtrinputALUOp[1:0]inputfunct[5:0]outputALUCtr[3:0]);always@(ALUOporfunct)//如果操作码或者功能码变化执行操作casex({ALUOp,funct})//拼接操作码和功能码便于下一步的判断8'b00xxxxxx:ALUCtr=4'b0010;//lw,sw,addi8'b01xxxxxx:ALUCtr=4'b0110;//beq8'b1xxx0000:ALUCtr=4'b0010;//add8'b1xxx0010:ALUCtr=4'b0110;//sub8'b1xxx0100:ALUCtr=4'b0000;//and8'b1xxx0101:ALUCtr=4'b0001;//or8'b1xxx1010:ALUCtr=4'b0111;//sltendcaseendmodule4.ALU模块ALU模块主要接受两个操作数,完成各类运算操作。包括加、减、与、或、小于设置。R型指令需要ALU进行运算,sw、lw需要ALU进行地址运算,beq需要ALU进行相等比较,以及指令地址运算。所以需要输入ALU控制信号判断ALU进行的操作,再进一步对两个操作数进行操作,操作完输出结果。inputinput1[31:0]inputinput2[31:0]inputaluCtr[3:0]outputaluRes[31:0]outputzeroALU输入信号与操作类型对应如下:Verilog代码如下,细节见注释:modulealu(input[31:0]input1,input[31:0]input2,input[3:0]aluCtr,outputreg[31:0]aluRes,outputregzero);always@(input1orinput2oraluCtr)//运算数或控制码变化时操作begincase(aluCtr)4'b0110://减beginaluRes=input1-input2;if(aluRes==0)zero=1;elsezero=0;end4'b0010://加aluRes=input1+input2;4'b0000://与aluRes=input1&input2;4'b0001://或aluRes=input1|input2;4'b1100://异或aluRes=~(input1|input2);4'b0111://小于设置beginif(input1input2)aluRes=1;enddefault:输入信号操作类型0000与0001或0010加0110减0111小于设置aluRes=0;endcaseendendmodule5.符号扩展模块将16位有符号数扩展成32位有符号数,只需要在16位数前面补足符号即可。Verilog代码如下,细节见注释:modulesignext(input[15:0]inst,//输入16位output[31:0]data//输出32位);//根据符号补充符号位//如果符号位为1,则补充16个1,即16’hffff//如果符号位为0,则补充16个0assigndata=inst[15:15]?{16'hffff,inst}:{16'h0000,inst};endmodule6.Rom及ram模块该模块由xilinx提供的IP核进行设计,其中ROM模块由地址线、数据线和时钟信号线组成。RAM模块由时钟线,地址线,读写使能线,数据线构成。inputinst[15:0]outputdata[31:0]romram7.顶层模块顶层模块需要将前面的多个模块实例化后,通过导线以及多路复用器将各个部件链接起来,并且在时钟的控制下修改PC的值,PC是一个32位的寄存器,每个时钟沿自动增加4。多路复用器MUX直接通过三目运算符实现:Assign𝑂𝑈𝑇=𝑆𝐸𝐿?𝐼𝑁𝑃𝑈𝑇1∶𝐼𝑁𝑃𝑈𝑇2;其中,OUT,SEL,INPUT1,INPUT2都是预先定义的信号。顶层模块需要输入时钟和复位信号,然后首先读取rom的机器指令,然后通过各个模块执行。示意图如下:Veilog代码如下,细节见注释:moduletop(inputclkin,inputreset);//指令寄存器pcreg[31:0]pc,add4;wirechoose4;//复用器信号线wire[31:0]expand2,mux2,mux3,mux4,mux5,address,jmpaddr,inst;wire[4:0]mux1;//CPU控制信号线wirereg_