多周期CPU实验

来源:互联网 发布:性格被动 知乎 编辑:程序博客网 时间:2024/05/18 02:38

1.数据通路图

这里写图片描述
与单周期CPU设计相比,图上增加IR指令寄存器,目的是使指令代码保持稳定,pc写使能控制信号PCWre,是确保pc适时修改,原因都是和多周期工作的CPU有关。ADR、BDR、ALUoutDR、DBDR四个寄存器不需要写使能信号,其作用是切分数据通路,将大组合逻辑切分为若干个小组合逻辑,大延迟变为多个分段小延迟。

2.控制信号作用

这里写图片描述
这里写图片描述
这里写图片描述

3.ALU运算功能表

这里写图片描述

4.实验内容

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

5.设计思路

(1)模块化

根据数据通路图设计各个子模块,分别是:PC、PCAddFour、PCAddImm、PCJump、InsMem、ControlUnit、RegisterFile、Extend、ALU、DataMem、IR、ADR、BDR、ALUOut、ALUm2dr、DataSelect(总共有6出选择,分别是:data1的选择、data2的选择、ALUorMem的选择、RegDst的选择、pcNext的选择、writeData的选择)

(2)分阶段

分阶段通过控制信号和时钟信号的改变,使得在取指->译码->执行->存储->写回各个阶段的操作不同,从而与单周期CPU区分。一开始的时候令我困惑不解的是多周期难道不也是在译码的时候就知道所有的控制信号吗?后来思考发现,必须通过控制不同state下的不同控制信号,从而来实现在不同的state下执行不同的操作。我的主要控制是:在IF状态下,主要是控制PCWre、IRWre、InsMemDataRW、nextState,需要注意的是,对于nextState = IF的情况,必须控制PCWre = 1。ID状态下,主要控制PCSrc、ALUSrcA和ALUSrcB,保证在这一阶段读取数据为EXE状态做准备,对于不同的指令,进入不同的EXE状态,并且j、jr、jal、halt的下一状态是IF。EXE状态下,主要控制ExtSel、ALUop和PCSrc,特别是beq指令,需要通过判断zero来改变PCSrc,保证操作的正确执行。MEM状态下,主要控制DataMemRW。WB状态下,需要控制PCWre、RegDst、RegWre、DBDataSrc、WrRegDSrc。
这里写图片描述

6.指令测试表格

这里写图片描述

7.各个模块的设计

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

8.实验结果截图

例:
00001000 00000001 00000000 00001000 // addi 1,0,8
功能:rt<-rs + (sign-extend)immediate
最终得到$1 = 1000
(1)000状态
这里写图片描述
(2)001状态
这里写图片描述
(3)110状态
这里写图片描述
(4)111状态
这里写图片描述

9.CPU状态转移图

这里写图片描述

10.实验总结

本次实验有几个需要特别注意的点。第一、与单周期CPU相比,此处实验有主要的两个不同点,一个是需要控制每条指令的各个状态,以及各个状态下的控制信号的改变,从而达到不同状态执行不同操作的目的;另一个是增加了IR、ADR、BDR、ALUoutDR、DBDR。此次实验有多个子模块的设计与单周期CPU的设计相似,部分代码是直接采用上一次单周期CPU设计的实现,但依然有不同的地方。第二、重点和难点是ControlUnit的设计,在ControlUnit的设计中,因为涉及到很多的控制信号,以及不同指令对应不同控制信号的不同值,还有不同状态下不同指令的控制信号,在这一模块花费的时间比较多,但是,控制信号在某种程度上是非常好的调试代码,在本次实验中,我大部分的时间花在结合数据通路图理解每一条指令的执行过程,以及对应的控制信号的变化,然后修改ControlUnit,又根据ControlUnit来进一步理解指令的执行过程,知道每一条指令的执行结果正确。第三、本次实验需要重点注意的几条指令:sll、beq、slt、j、jr、jal。sll需要注意指令的存储格式以及sa的扩展从而选择ALUDataA;beq需要注意immediate表示的是pc+4和要跳转到的指令之间间隔的指令条数,因为同时需要读取rs,rt还有extendData,所以在控制信号的控制上需要区别对待;slt主要是要注意在ALU中操作的实现,因为涉及到符号数的比较;j表示的是跳转到的地址;jr表示的是子程序调用完成后跳转回主程序的下一条指令;jal表示的是子程序调用,首先是将pc+4即下一条指令存储到31号寄存器中,然后跳转到子程序的首地址。
本次实验因为有了单周期CPU的基础,所以在实现的时候对于每条指令的理解更加清晰。在实验的过程中遇到的主要问题有:
一开始的时候误以为不仅仅要实现多周期而且要用流水线,导致迟迟无法下手,后来发现并不需要实现流水线,相对难度降低了很多。并且一开始一直不理解IR、ADR等的作用,后来老师给的资料表明:增加IR指令寄存器,目的是使指令代码保持稳定,pc写使能控制信号PCWre,是确保pc适时修改,原因都是和多周期工作的CPU有关。ADR、BDR、ALUoutDR、DBDR四个寄存器不需要写使能信号,其作用是切分数据通路,将大组合逻辑切分为若干个小组合逻辑,大延迟变为多个分段小延迟。我还有另一个理解是:这些寄存器还有利于流水线的设计,当增加旁路的时候,也可以从寄存器中提前获得数据。
(1)在实现的初始阶段,一直苦苦思索到底多周期和单周期的区别在哪里?到底应该如何体现多周期与单周期的区别?难道仅仅是通过增加一个输出state?后来根据计组理论课的知识明白,必须在不同的阶段有不同的操作,即各个阶段的操作必须区分开,IFState阶段获取指令;IDState阶段译码,表现在得到data1、data2和extendData;EXEState阶段执行,表现在得到ALUop、ALUResult; MemState阶段访问存储器,表现在得到MemData并且内存中的数据发生改变;WBState写回寄存器,表现在writeData的改变,此时的writeData可能是来自于ALUresult也可能是来自于存储器,所以需要一个二路选择器进行选择。在确定了这种设计之后,我又思考另一个问题,即各个控制信号的值难道不是在ID阶段就都得到了吗?后来才明白虽然在ID阶段就可以知道各个控制信号的值,但是这与在后面的阶段才将某些信号值比如DataMemRW表现出来并不矛盾。
(2)在实验的过程中,一开始对j、jr、jal的理解不到位,导致执行的结果一直出错,表现在:在指令的设计时,没有将要跳转到的地址在存入指令的时候先右移两位,导致跳转的时候一直出错,后来思考并进一步理解才明白正是因为在存入指令的时候先右移了两位,所以在执行的时候才需要将得到的地址先左移两位然后再补充pc+4的高四位从而得到要跳转到的位置。
(3)此次实验过程中出现多次指令的设计出错导致执行结果出错,比如sll,一开始的时候我的指令是:01100001 01001010 00000000 00000001 // sll 10,10,1,后来才发现应该是:01100000 00001010 01010000 01000000 // sll 10,10,1
(4)本次实验还遇到比较多的小问题,比如拼写错误或者是不小心含有中文字符导致的错误,但是这些错误的改正相对控制单元的调试就简单了很多。还有比如开始的时候pcJump传入的是curPC,而不是pc+4,但是在实现的时候却是以pc+4实现。另外需要注意的是case语句块必须用begin…end,否则会出错。

原创粉丝点击