您的位置:首页 > 其它

16位MIPS指令集RISC结构简单CPU实现

2012-04-28 16:25 609 查看
自己的wordpress站shutdown了,还好保存了文章xml,迁移到CSDN,有空补上图。

组成原理的课程设计,最后被老师保留了实验台,辛辛苦苦做了一周,不容易啊,这里就介绍一下。全部使用FPGA设计,老师不让用HDL语言,只好用原理图的方式(虽然还是偷偷用了些HDL)。

1.理论知识

精简指令集,是计算机中央处理器的一种设计模式,也被称为RISC(ReducedInstructionSetComputing的缩写)。这种设计思路对指令数目和寻址方式都做了精简,使其实现更容易,指令并行执行程度更好,编译器的效率更高。常用的精指令集微理器包括DECAlpha、ARC、ARM、AVR、MIPS、PA-RISC、PowerArchitecture(包括PowerPC)和SPARC等 。大部分RISC具有以下特点:

优先选取使用频率最高的一些简单指令,以及一些很有用但不复杂的指令。避免使用复杂指令。
大多数指令在一个机器周期内完成。
采用LOAD/STORE结构。由于访问主存指令花费的时间较长,因此在指令系统中应尽量减少访问主存指令,而只保留不能再减掉的LOAD(取数)和STORE(存数)两种防存指令
采用简单的指令格式和寻址方式,指令长度固定。
固定的指令格式。指令字长、格式固定,可简化指令的译码逻辑,有利于提高流水的执行效率。
面向寄存器的结构。为减少访问贮存期,CPU内应设大量的通用寄存器。
采用硬布线控制逻辑。由于指令系统的精简,控制部件可由组合逻辑实现,不用或减少微程序控制,这样可使控制部件的速度大大提高。
注重编译的优化,力求有效的支撑高级语言程序。

MIPS CPU是一种RISC结构的CPU。MIPS提供了32个32位的通用寄存器,各寄存器的编号、名称和功能如表1.1所示。
[table id=1 /]
MIPS将寻址方式与指令的操作码相关联,因此不再独立设置寻址方式特征位字段。所有指令都是32位,分为R型、I型和J型3种指令类型,其结构如表1.2所示。
[table id=2 /]
其中R型指令中funct字段常用编码见表1.3。
[table id=3 /]

2.总体设计方案

2.1硬件设计

本次我们采用的方案是16位MIPS CPU,数据与指令分开存放,采用硬布线控制逻辑,运算中的数据均存放于寄存器中。同时在实施的过程中,采用FPGA全下载方式、自己设计时序电路及寄存器和控制逻辑。

2.1.1数据通路

数据通路采用的书上的单周期方案数据通路(教材为秦磊华主编的计算机组成原理,清华大学出版社),基本功能部件包括:程序寄存器、多路选择器、寄存器堆、数据存储器、指令存储器、符号扩展单元、加法器和ALU。高层视图如图2.1.1所示。


图2.1.1 单周期方案数据通路高层视图

2.1.2ALU

运算器部分电路是下载到FPGA中完成的,由于我们实现的是16位的指令和数据系统,故需要设计16位的运算器。运算器采用181和182拼接实现,输入为A、B16位输入及控制位输入,输出为16位结果及比较相等输出。

2.1.3指令存储器

此部分通路中,主要为一片ROM做指令存储器,在程序运行之前,所有的指令都已经事先存储在这里,运行程序时,从指令存储器中读出指令执行。基本框图如图2.1.3所示。


图2.1.3指令存储器

2.1.4数据存储器

数据存储器用来保存运算结果,可读可写,运算中提供数据及地址。基本框图如图2.1.4所示。


图2.1.4数据存储器

2.1.5程序寄存器

程序计数器由一个寄存器组成,可读可写,在运算中提供指令的地址。基本框图如图2.1.5所示。


图2.1.5程序寄存器

2.1.6寄存器堆

寄存器堆是RISC CPU的特色,主要用来存放运算的中间结果,以此来加快运行的速度。基本框图如图2.1.6所示。


图2.1.6寄存器堆

2.1.7时序控制器

时序控制电路用于产生CPU工作所需的时序,为了实现流水线的处理机,时序有特定的要求,主要靠触发器完成。基本框图如图2.1.7所示。


图2.1.7时序控制器

2.1.8OP字段控制

OP字段控制器主要根据指令的OP字段对相应部件的控制为进行置位的操作。控制器采用硬布线逻辑进行实现。基本框图如图2.1.8所示。


图2.1.8OP字段控制器

2.1.9ALU控制器

ALU控制器根据OP控制器的输出以及指令的funct字段来控制ALU做何种算术逻辑运算。基本框图如图2.1.9所示。


图2.1.9ALU控制器

2.1.10启停控制器

启停控制器用来控制CPU的启动和停止逻辑,只有设置启动后,CPU才能开始正常工作。当程序运行结束后,便自动触发停止逻辑,CPU停止工作。基本框图如图2.1.10所示。


图2.1.10启停控制器

2.2软件设计

2.2.1指令设计

指令的格式设计是根据32位MIPS指令格式,结合我们自己的设计需要,将指令长度缩减为16位,指令类型保持R、I、J三种类型不变。另外根据流水线实现的需要,增加了空指令和停机指令两个特殊指令。采用定长指令每条指令的长度为16位,总共有3种类型,如表2.2.1.1所示。
[table id=4 /]
表中OP字段决定是何种类型指令。下面分别对5种指令进行说明。1)R型指令R型指令的操作数只能来自寄存器,运算结果也只能存入寄存器中,属于RR型指令。对于R型指令的OP字段为0000,具体的操作由FUNCT字段指定,该字段的编码与具体R型运算的关系如表3.2所示。RS和RT字段分别是第一和第二源操作数,RD字段指明存放结果的寄存器。
[table id=5 /]
2)I型指令I型指令是立即数指令,若是双目运算,则将RS的内容和立即数字段的值分别作为第一操作数和第二操作数,结果送RT指定的寄存器中;若是Load/Store指令,则将RS的内容和立即数字段的值经符号扩展后的内容相加作为读/写(Load/Store)的存储单元地址;若是条件转移(分支)指令,则对RS和RT寄存器中的数据进行操作码规定的运算,并根据运算结果据顶是否转移。当发生转移时,转移的目标地址采用相对寻址方式获得,即将PC的内容和立即数字段经符号扩展后的内容相加得到。3)J型指令J型指令主要是无条件跳转指令,指令中给出的是12位直接地址,无条件转移的目标地址由12位直接地址经符号扩展后得到。4)NOP指令NOP指令主要用于产生流水线中的气泡进而消除流水线中可能产生的冲突。NOP的指令的OP字段为0000,实际为特殊的R型指令。其所作的操作为将0号寄存器与自身相加结果送自身。由于设计中将0号寄存器设置为固定值0不可更改,所以所做的操作毫无意义,可作为空指令。5)HALT指令HALT指令为停机指令,当计算机执行完代码后,产生一个停机型号,使得计算机停止运行并将所有寄存器及数据存储器清零。HALT指令的OP字段为1111,剩下的12位可以为任意值。 对于寄存器的编号,由于我们的系统总共有8个寄存器,故使用3位二进制码将它们编号(如1号寄存器编号为001),另外按照MIPS寄存器的功能,我们将0号寄存器设置为常量0的只读寄存器。

2.2.2OP字段控制状态设计

OP字段控制是根据指令的OP字段来设置各个部件的工作状态,具体控制见表2.2.2。
[table id=6 /]
2.2.3ALU字段控制状态设计ALU控制器根据OP控制器的输出以及指令的funct字段来控制ALU做何种算术逻辑运算。具体控制见表2.2.3。
[table id=7 /]
3.详细设计与实现设计工具为QuartusⅡ9.1 build222,老师提供的FPGA为Cyclone的EP1C3T144C8,2910逻辑门,59904存储位,1个PLL,TQFP封装144个引脚。

3.1硬件

3.1.1ALU




图3.1.1ALU

3.1.2PC寄存器




图3.1.2PC寄存器

3.1.3寄存器堆




图3.1.3.1寄存器堆
其中单个寄存器如图3.1.3.2。


图3.1.3.2单个寄存器

3.1.4ALU控制器

ALU控制器的原理图是用Verilog HDL写的,然后转化为原理图,算是偷了个懒。要照老师的要求就得老老实实的用数字逻辑的方法进行设计,首先建立函数与变量的逻辑关系,用真值表法或分析法获得逻辑表达式,然后花间逻辑函数,再选择逻辑门类型今夕逻辑函数变换,最后画出逻辑电路(不得累死-_-!)。


图3.1.4ALU控制器

3.1.5OP字段控制器

OP字段控制器同样用Verilog HDL写,然后转化为原理图。


图3.1.5OP字段控制器

3.1.6启停控制器

启停控制器的设计参考了书本,但去掉了触发器。


图3.1.6启停控制器

3.1.7时序控制器




图3.1.7时序控制器

3.2软件

3.2.1具体指令

1)R型指令指令格式见表2.2.1.1。
[table id=8 /]
2)I型指令
[table id=9 /]
3)J型指令
[table id=10 /]
4)NOP指令
[table id=11 /]
5)HALT指令
[table id=12 /]

3.2.2指令周期流程图




图3.2.2指令周期图

3.2.3流水线

流水线的工作方式能够大大提高CPU执行指令的速度,但设计也较为困难,在课程设计要求中作为额外指标。我们的设计方案为单周期,每个周期由5个机器周期构成,理论上加速比为5,但由于数据冲突和结构冲突等情况的存在,要调整指令执行的流程并且加入适当的气泡来避免以上情况的发生。另外的设计流水线方法可以是在每个执行部件之间加入寄存器来暂存结果,这样就可以避免部分冲突。表3.2.3是一段代码的时空图。
[table id=13 /]

3.2.4测试代码

最终测试程序以及说明:测试程序为一个累加1到50的累加程序,汇编代码如下,其中空指令为为了实现流水线避免数据冲突和结构冲突而插入的气泡。由于设计中存在的不足,使得跳转指令执行后,虽然PC的内容改变,但还是执行顺序的下一条指令,直到3步后才真正跳转,所以通过软件的方式在跳转指令后添加跳转处开始的三条相同的代码。在停机指令前,一定要有三条空操作指令,原因是由于启停控制器中去掉了D触发器,当产生停止信号时会马上停止,而不是等待到最后一个时序信号的下降沿才停止,所以为了确保指令的正确执行,要在停机指令前添加三条空指令以确保安全停机。具体汇编代码如下:[codesyntax
lang="asm"]LUI $S1, 1LUI $S2, 1LUI $S3, 50LUI $S7, 0BEQ $S3, $S2, 6ADD $S7, $S7, $S2ADD $S2, $S2, $S1J 6BEQ $S3, $S2, 5ADD $S7, $S7, $S2ADD $S2, $S2, $S1ADD $S7, $S7, $S0J 13ADD $S7, $S7, $S0J 13NOPNOPNOPHALT[/codesyntax]

3.仿真与调试及汇编器

3.1波形仿真

3.1.1时序发生器仿真

为满足流水线的要求,时序发生器需产生特定的时序。PC的时钟最先产生,接下来是ROM,然后是寄存器堆,再是RAM,最后是寄存器堆写回的时钟。但由于FPGA中存储器的工作需要多产生一个时钟信号,所以PC与ROM的时钟为同时产生。具体仿真波形如图3.1.1所示。


图3.1.1时序发生器仿真波形

3.1.2启停控制器仿真

启停控制器在start为高时,正常工作,输入的时钟信号能够输出,当出现stop信号为高,start为低时,停止工作,即输出无时钟信号,清零信号为高,即为把所有的清零输入都设置为有效,将所有能够清零的存储器都清零。具体仿真波形如图3.1.2所示。(好像有问题,但实际工作没问题)


图3.1.2启停控制器仿真

3.1.3ALU控制器仿真




图3.1.3ALU控制器仿真

3.1.4整体功能仿真

较长,分两张图片显示。


图3.1.4.1整体仿真波形上



图3.1.4.2整体仿真波形下

3.2汇编器

为了程序设计的方便,以及从实际CPU应用考虑出发,我们根据自己的指令系统编写了汇编器程序。这样在运行程序时,我们只需要写出汇编级的代码,然后通过汇编器汇编生成机器指令运行就可以。而不必参照指令格式,一条条的手动编写机器代码,这大大地提高了效率,也更接近实际CPU的运作方式。汇编器用了200多行的代码,主要就是case语句。代码就不贴了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: