MIPS-CPU设计实验报告实验名称:32位单周期MIPS-CPU设计姓名学号:刘高斯11072205实验日期:2014年12月19日目录前言MIPS简介------------------------------------------------------------- 3 实验目的------------------------------------------------------------- 3第一部分VERILOG HDL 语言实现部分实验内容------------------------------------------------------------- 4 试验环境------------------------------------------------------------- 4 模块简介------------------------------------------------------------- 4 实验截图------------------------------------------------------------- 5 实验感想------------------------------------------------------------- 5 实验代码------------------------------------------------------------- 6第二部分LOGISIM 语言实现部分实验内容------------------------------------------------------------- 16 实验环境------------------------------------------------------------- 16模块设计------------------------------------------------------------- 16 试验感想------------------------------------------------------------- 23前言一、MIPS简介MIPS是世界上很流行的一种RISC处理器。
MIPS的意思“无内部互锁流水级的微处理器”(Microprocessor without interlocked piped stages),其机制是尽量利用软件办法避免流水线中的数据相关问题。
它最早是在80年代初期由斯坦福(Stanford)大学Hennessy教授领导的研究小组研制出来的。
MIPS公司的R系列就是在此基础上开发的RISC工业产品的微处理器。
这些系列产品为很多计算机公司采用构成各种工作站和计算机系统。
MIPS技术公司是美国著名的芯片设计公司,它采用精简指令系统计算结构(RISC)来设计芯片。
和英特尔采用的复杂指令系统计算结构(CISC)相比,RISC具有设计更简单、设计周期更短等优点,并可以应用更多先进的技术,开发更快的下一代处理器。
MIPS是出现最早的商业RISC架构芯片之一,新的架构集成了所有原来MIPS指令集,并增加了许多更强大的功能。
MIPS处理器是八十年代中期RISC CPU设计的一大热点。
MIPS是卖的最好的RISC CPU,可以从任何地方,如Sony,Nintendo的游戏机,Cisco的路由器和SGI超级计算机,看见MIPS产品在销售。
目前随着RISC体系结构遭到x86芯片的竞争,MIPS有可能是起初RISC CPU设计中唯一的一个在本世纪盈利的。
和英特尔相比,MIPS的授权费用比较低,也就为除英特尔外的大多数芯片厂商所采用。
MIPS的系统结构及设计理念比较先进,其指令系统经过通用处理器指令体系MIPS I、MIPS II、MIPS III、MIPS IV到MIPS V,嵌入式指令体系MIPS16、MIPS32到MIPS64的发展已经十分成熟。
在设计理念上MIPS强调软硬件协同提高性能,同时简化硬件设计。
二、实验目的我们通过VERILOG HDL 语言和LOGISIM 语言分别用语句和图形完成对32位MIPS-CPU的设计,通过前8周的学习我们基本掌握了MIPS的概念和原理,认识到RISC架构的特征和优缺点。
通过过老师的讲解,了解到每一条语句的从设计到硬件实现的全过程。
通过本次实验我们要更加深入的理解硬件组成的结构,语句逻辑实现的原理。
掌握硬件编程语言和硬件图形语言编程的方法。
透彻的理解MIPS的特征和优点。
VERILOG HDL 语言实现部分实验内容利用VERILOG设计一种32位单周期MIPS CPU。
首先设计各个子模块,并将已做好的各个模块进行模块合并,实现单周期CPU的各项指令。
实验环境Window Xp Quartus II各个子模块的简单介绍此程序将数据通路(SingleDataLoad)设定为顶层模块,下面的模块包括:算术逻辑运算单元(ALU)、数据存储器(DataStore)、数据寄存器(Registers)、取指令部件(GetCode)、总控制器(Control),通过顶层模块对各个子模块的调用从而实现了整个单周期CPU。
1)数据通路(SingleDataLoad):进行数据的运算、读取以及存储功能,通过总控制器产生的各个控制信号,进而实现对数据的各项操作。
2)算术逻辑运算单元(ALU):数据通路调用此模块,根据得到的控制信号对输入数据进行处理,处理功能有:addu、add、or、subu、sub、sltu、slt等。
3)数据存储器(DataStore):当WrEn控制信号为1时,此时就将输入数据存储到此存储器中,当WrEn为0时,则根据输入的地址,找到地址对应的单元将单元中的数据输出。
4)数据寄存器(Registers):在此程序中功能和实现基本和数据存储器相同,但在实际CPU当中使用的逻辑器件及获取数据的方式还是有所区别的。
5)取指令部件(GetCode):指根据PC所提供的地址从指令寄存器中取出要执行的指令,再根据各控制信号,得出下一次要执行的指令的地址。
(总控制器(Control):总控制器通过从取指令部件获得的指令,进而产生各个控制信号,并将控制信号返回个数据通路,就此实现各项功能。
程序截图及说明上图为执行下列指令产生的图像:Mem[0]<={6'b000100,5'b00001,5'b00010,5'b00000,5'b00000,6'b000001}; //beq $1,$2,1Mem[4]<={6'b000000,5'b00001,5'b00010,5'b00100,5'b00000,6'b101011}; //sltu $4,$1,$2Mem[8]<={6'b000010,5'b00000,5'b00000,5'b00000,5'b00000,6'b000010}; //j 2 当$1、$2所指的寄存器的值相同时,执行上述指令,得到的图如下:可以看出CPU跳过了第二条指令,直接执行了第三条,而上图执行了第一条指令后接着执行第二条,最后才执行第三条指令,区别就在于第一幅图表示的是$1、$2中的值不相等所执行的情况,第二幅图表示的是$1、$2中的值相等的情况,由此可以得知测试正确。
实验收获及感想VERILOG 语句将二进制元器件的原理整合到类汇编语言上,通过这次实验我从理解上从这语言本身理解到逻辑与函数不分家的道理,每一条连线和与、非、或都是一个个对应的函数。
任一个复杂的CPU 都是从一条条简单的逻辑一条一条实现的。
任何一条语句都是通过不同的函数和赋值分分合合直到被执行完毕。
实验代码:数据通路(SingleDataLoad)moduleSingleDataLoad(clk,RegWr,RegDst,ExtOp,ALUSrc,Branch,Jump,MemtoReg,MemWr,ALUct r);input clk;//input[31:0] Instruction;output RegWr,RegDst,ExtOp,ALUSrc,Branch,Jump,MemtoReg,MemWr;output[2:0] ALUctr;wire RegWr,RegDst,ExtOp,ALUSrc,Branch,Jump,MemtoReg,MemWr;wire[2:0] ALUctr;wire [31:0] Instruction;wire [4:0] Rd,Rt,Rs;wire [5:0] op,func;wire[4:0] Rx;wire P1,P2,Zero,Overflow;wire [31:0] busW,busA,busB,out1,dataout,busB1,busBo;wire [15:0] imm16;Controlcon(Instruction,RegWr,ExtOp,ALUSrc,ALUctr,Branch,Jump,RegDst,MemtoReg,MemWr);assign op=Instruction[31:26];assign func=Instruction[5:0];assign Rs=Instruction[25:21];assign Rt=Instruction[20:16];assign Rd=Instruction[15:11];assign imm16=Instruction[15:0];assign P1=P2&RegWr;MUX2 mux2(RegDst,Rt,Rd,Rx);assign busB1={{16{imm16[15] & ExtOp}},imm16[15:0]};MUX2TO1 mux1(ALUSrc,busB,busB1,busBo);Registers Reg(clk,busW,P1,Rx,Rs,Rt,busA,busB);ALU alu(busA,busBo,ALUctr,out1,Overflow,Zero);assign P2=!Overflow;DataStore datas(clk,busB,out1[4:0],MemWr,dataout);MUX2TO1 mux3(MemtoReg,out1,dataout,busW);GetCode get(Branch,Zero,Jump,clk,Instruction);endmodulemodule MUX2TO1(op,X,Y,Z);input op;input [31:0] X,Y;output[31:0] Z;reg [31:0] Z;always@(op)beginif(op==1)Z=Y;elseZ=X;endendmodulemodule MUX2(op,x,y,z);input op;input [4:0] x,y;output[4:0] z;reg [4:0] z;always@(op)beginif(op==1)z=y;elsez=x;endendmodule算数逻辑运算单元(ALU)module ALU(A,B,ALUctr,Result,Overflow,Zero);parameter n=32;input [n-1:0] A,B;input [2:0] ALUctr;output [n-1:0] Result;output Overflow,Zero;wire Zero,Overflow;wire [n-1:0] Result;wire SUBctr,OVctr,SIGctr;wire [1:0] OPctr;wire [n-1:0] H,M,N,Add_Result;wire K,G,I,Add_Sign,Add_Overflow,Add_carry;assign SUBctr=ALUctr[2];assign OVctr=!ALUctr[1] & ALUctr[0];assign SIGctr=ALUctr[0];assign OPctr[1]=ALUctr[2] & ALUctr[1];assign OPctr[0]=!ALUctr[2] & ALUctr[1] &!ALUctr[0];assign H=B^{n{SUBctr}};assign M=A|B;Adderk nbit_add(SUBctr,A,H,Add_carry,Add_Sign,Add_Result,Zero);//,Add_Overflowassign Add_Overflow= A[n-1] & H[n-1] & !Add_Result[n-1] | !A[n-1] & !H[n-1] & Add_Result[n-1];assign K=SUBctr ^ Add_carry;assign I=Add_Sign ^ Add_Overflow;assign Overflow=OVctr & Add_Overflow;IMUX2to1 YN(K,I,SIGctr,G);IMUX2to1 yn(0,1,G,N);MUX3to1 nbit_Result(Add_Result,M,N,OPctr,Result);endmodulemodule Adderk (Cin, X, Y,Add_carry,Add_sign,Add_result,Zero); //Add_Overflow,parameter k = 32;input [k-1:0] X, Y;input Cin;output [k-1:0] Add_result;output Add_carry,Add_sign,Zero; //,Add_Overflowreg [k-1:0] Add_result;reg Add_carry,Zero,Add_sign; //,Add_Overflowalways@(X or Y or Cin)begin{Add_carry, Add_result} = X + Y + Cin;if(Add_result==0)Zero=1;elseZero=0;if(Add_result[31]==1)Add_sign=1;elseAdd_sign=0;endendmodulemodule MUX3to1 (V,W,U,Selm,F);parameter k = 32;input [k-1:0] V,W,U;input [1:0] Selm;output [k-1:0] F;reg [k-1:0] F;always @(V or W or U or Selm)case(Selm)2'b00: F <= V;2'b01: F <= W;2'b10: F<=U;endcaseendmodulemodule IMUX2to1 (V,W,SIGctr,Less);input[31:0] V,W;input SIGctr;output[31:0] Less;reg[31:0] Less;always @(V or W or SIGctr)if (SIGctr == 0)Less <= V;elseLess <= W;Endmodule数据存储器(DataStore):module DataStore(clk,DataIn,Adr,WrEn,Out);input [31:0] DataIn;input [4:0] Adr;input WrEn,clk;output [31:0] Out;reg [31:0] Out;reg [31:0] Store [31:0];always@(negedge clk)beginif(WrEn==1)Store[Adr]=DataIn;endalways@(Adr or WrEn)if(WrEn==0)Out=Store[Adr];endmodule数据寄存器(Registers):module Registers(clk,busW,wr,Rw,Ra,Rb,busA,busB); input [31:0] busW;input clk,wr;input [4:0] Rw,Ra,Rb;output [31:0] busA,busB;reg [31:0] busA,busB;reg [31:0] Regist [31:0];always@(negedge clk)beginRegist[1]=32'd25;Regist[2]=32'd25;if(wr==0)Regist[Rw]=busW;endalways@(Ra or Rb or wr)beginif(wr==1)beginbusA=Regist[Ra];busB=Regist[Rb];endendendmodule取指令部件(GetCode):module GetCode(Branch,Zero,Jump,clk,Instruction); input Zero,Branch,Jump,clk;output[31:0] Instruction;reg[29:0] PC=25;wire[29:0] M,M2;wire [4:0] addmem;wire K;reg reset=1;assign addmem={PC[2:0],2'b00};wire[29:0] O1,O2,O3,O4;wire[15:0] imm16;instruct InsMem(addmem,Instruction);always@(negedge clk)beginif (reset==1)beginPC <=0;reset<=0;endelsebeginPC <= O4;endendassign imm16=Instruction[15:0];assign M=PC;assign K=Zero & Branch;Adder adder1(M,1,O1);assign M1={{14{imm16[15]}},imm16[15:0]};Adder adder2(O1,M1,O2);MUX2T1 mux1(K,O1,O2,O3);assign M2={M[29:26],Instruction[25:0]};MUX2T1 mux2(Jump,O3,M2,O4);endmodulemodule Adder(M,N,O);input[29:0] M;input[29:0] N;output[29:0] O;wire[29:0] M,N,O;assign O=M+N;endmodulemodule MUX2T1(op,X,Y,Z);input op;input [29:0] X,Y;output[29:0] Z;reg [29:0] Z;always@(op)beginif(op==1)Z=Y;elseZ=X;endendmodulemodule instruct(addr,inst);input [4:0] addr;output [31:0] inst;reg [31:0] inst;// Declare the RAM variablereg [31:0] Mem [31:0];// write instruction: add 3<=(1)+(2),sub 6<=(4)-(5),jump 0always @(*)begin//Mem[0]<={6'b000000,5'b00001,5'b00010,5'b00011,5'b00000,6'b100000}; //add $3,$1,$2// Mem[4]<={6'b000000,5'b00011,5'b00001,5'b00100,5'b00000,6'b100010}; //sub $4,$3,$1// Mem[0]<={6'b000000,5'b00001,5'b00010,5'b00011,5'b00000,6'b101010}; //slt $3,$1,$2// Mem[4]<={6'b000000,5'b00011,5'b00001,5'b00100,5'b00000,6'b100011}; //subu $4,$3,$1// Mem[0]<={6'b000000,5'b00001,5'b00010,5'b00011,5'b00000,6'b101010}; //slt $3,$1,$2// Mem[4]<={6'b000000,5'b00001,5'b00010,5'b00100,5'b00000,6'b101011}; //sltu $4,$1,$2//Mem[0]<={6'b001101,5'b00001,5'b00011,5'b10000,5'b00000,6'b000101}; //ori $3,$1,32773// Mem[4]<={6'b001001,5'b00010,5'b00100,5'b00000,5'b00000,6'b001000}; //addiu $4,$2, 8// Mem[4]<={6'b001001,5'b00010,5'b00100,5'b11111,5'b11111,6'b111000}; //addiu $4,$2, -8// Mem[0]<={6'b101011,5'b00001,5'b00011,5'b00000,5'b00000,6'b000101}; //sw $3,$1,5// Mem[4]<={6'b100011,5'b00001,5'b00100,5'b00000,5'b00000,6'b000101}; //lw $4,$1,5Mem[0]<={6'b000100,5'b00001,5'b00010,5'b00000,5'b00000,6'b000001}; //beq $1,$2,1Mem[4]<={6'b000000,5'b00001,5'b00010,5'b00100,5'b00000,6'b101011}; //sltu $4,$1,$2Mem[8]<={6'b000010,5'b00000,5'b00000,5'b00000,5'b00000,6'b000010}; //j 2 end// readalways @(addr)begininst <= Mem[addr];endendmodule总控制器(Control):moduleControl(Instruction,RegWr,ExtOp,ALUSrc,ALUctr,Branch,Jump,,RegDst,MemtoReg,Mem Wr);output RegWr,RegDst,ExtOp,ALUSrc,Branch,Jump,MemtoReg,MemWr;input[31:0] Instruction;reg RegWr,RegDst,ExtOp,ALUSrc,Branch,Jump,clk,MemtoReg,MemWr;output [2:0] ALUctr;reg [2:0] ALUctr;wire [5:0] op,func;assign op=Instruction[31:26];assign func=Instruction[5:0];parameterS0=6'b100000,S1=6'b100010,S2=6'b100011,S3=6'b101010,S4=6'b101011,S5=6'b001101,S6 =6'b001001,S7=6'b100011,S8=6'b101011,S9=6'b000100,S10=6'b000010;always@(op or func)beginif(op==6'b000000)begincase(func)S0:beginBranch=0;Jump=0;RegDst=1;ALUSrc=0;ALUctr=3'b001;MemtoReg=0;RegWr=1;MemWr=0;endS1:beginBranch=0;Jump=0;RegDst=1;ALUSrc=0;ALUctr=3'b101;MemtoReg=0;RegWr=1;MemWr=0;endS2:beginBranch=0;Jump=0;RegDst=1;ALUSrc=0;ALUctr=3'b100;MemtoReg=0;RegWr=1;MemWr=0;endS3:beginBranch=0;Jump=0;RegDst=1;ALUSrc=0;ALUctr=3'b111;MemtoReg=0;RegWr=1;MemWr=0;endS4:beginBranch=0;Jump=0;RegDst=1;ALUSrc=0;ALUctr=3'b110;MemtoReg=0;RegWr=1;MemWr=0;endendcaseendelsebegincase(op)S5:beginBranch=0;Jump=0;RegDst=0;ALUSrc=1;ALUctr=3'b010;MemtoReg=0;RegWr=1;MemWr=0;ExtOp=0;endS6:beginBranch=0;Jump=0;RegDst=0;ALUSrc=1;ALUctr=3'b000;MemtoReg=0;RegWr=1;MemWr=0;ExtOp=1;endS7:beginBranch=0;Jump=0;RegDst=0;ALUSrc=1;ALUctr=3'b000;MemtoReg=1;RegWr=1;MemWr=0;ExtOp=1;endS8:beginBranch=0;Jump=0;ALUSrc=1;ALUctr=3'b000;RegWr=0;MemWr=1;ExtOp=1;endS9:beginBranch=1;Jump=0;ALUSrc=0;ALUctr=3'b100;RegWr=0;MemWr=0;endS10:beginBranch=0;Jump=1;RegWr=0;MemWr=0;endendcaseend end endmoduleLOGISIM 实现部分实验内容利用LOGISIM软件,实现通过图形硬件语言完成对32位单周期MIPS-CPUD 设计工作。