2015秋季硬件技术综合实习课程设计实验报告

更新时间:2024-05-16 19:56:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

华南农业大学信息学院

硬件技术综合实习实验报告

课程设计名称: 无cache 5级流水CPU设计

相关课程名称: 计算机组成原理 开 设 时 间: 2015学年第一学期 指 导 教 师: 万军洲

姓 名: 学 号:

班 级:

华南农业大学

《硬件技术综合实习》课程设计

设计起止日期:

2015.10 ~ 2015.12 2015学年 第一学期

系别 计算机 班级 学号 姓名 设 计 无cache 5级流水CPU设计 题 目 同学甲: 同学乙: 同学丙: 学工作量:同学甲XX%,同学乙XX%,同学丙XX% 生 自 我 评 价 能够实现实验要求的功能 □全部 □部分 算法描述清晰 □清晰 □一般 □杂乱 算法有新意 □有 □一般 程序运行通过 □有通过 □无通过 算法思想与程序设计参数等说明 □完善 □仅有功能说明 教 □缺 师 按期上交报告的文档资料及附源程序 □按期且资料全 □未按评 期 语 报告的整体结构 □合理 □不合理 问题的困难部分流畅解决 □解决的好 □解决不好 对算法的分析 □有且效率好 □一般 □忽视 有总结和体会 □有 □无 成 绩 教师签名:万军洲 批改日期:2016年 1 月

10 日

一、课程设计目的

1.本实验以计算机硬件为主,兼顾计算机软件和计算机应用技术。在教师指导下,灵活运用所学到的基础知识和主要专业知识,将一个16位的CPU修改成8位的CPU。 2.本实验需要自己设计并最终用FPGA实现一个CPU芯片。需要自己设计指令系统、指令格式、寻址方式、寄存器结构、数据表示方式、存储器系统,自己设计运算器、控制器和流水线结构等。用VHDL硬件语言进行逻辑设计,采用先进的工具软件进行模拟和测试,测试通过之后下载到FPGA芯片中,并在测试平台上通过规定测试程序的测试。

3.在完成实验的过程中锻炼和提高实际动手能力、创新思维、团队合作精神等方面的能力。

4.本实验作为一个重要的教学实践环节,安排在本科生在课程教学基本完成之后,在综合论文训练之前,具有承上启下的作用。

5.可能的应用前景:由于我们实现的是通用CPU,故大部分需使用CPU的场合都有可能使用,只不过目前只能用于对速度要求不高、对特殊指令要求不多(非专用CPU)的场合下。但由于其成本比较低,在低端市场也许有一定的竞争力。

二、课程设计内容

将一个16位的CPU修改成8位的CPU,具体步骤如下:

1.选取出需要实现的指令(不能超过16条)

2.修改代码中的CPU字长、主存字长和寄存器字长为8位。 3.根据选取出来的指令修改相应的译码和执行部分代码 4.编写CPU规则

三、 详细设计 (一)、代码修改 1.指令选取

a). ADD、SUBB、AND、SHL、SHR b). MOVI、MOV、LOAD、STORE c). JR、JRC、JRNC、JRZ、JRNZ d). HALT、NOP

5条ALU相关指令

4条寄存器/主存相关指令 5条跳转指令

停止运行和空操作指令

2.CPU字长和寄存器字长修改(unitpack.vhd)

subtype INDEXTYPE is INTEGER range 0 to 3; subtype WORD is std_logic_vector(7 downto 0); type REGISTERARRAY is array ( 0 to 3 ) of WORD; -- 4 reg, default is 16 其中寄存器的数量为4个,字长均为8

3.译码部分的修改(identity.vhd)

when ADD => ctrl:=d_IR(3 downto 0)&\when SUBB=> ctrl:=d_IR(3 downto 0)&\when ANDins => ctrl:=d_IR(3 downto 0)&\when CMP => ctrl:=d_IR(3 downto 0)&\when MOVI => ctrl:=d_IR(3 downto 0)&\ imm <= \when SHRIns => ctrl:=d_IR(3 downto 0)&\when MOV => ctrl:=d_IR(3 downto 0)&\when LOAD=> ctrl:=d_IR(3 downto 0)&\when STORE=> ctrl:=d_IR(3 downto 0)&\ when JR|JRZ|JRNZ|JRC|JRNC => ctrl:=DoNothing; --若是JR*指令,计算offset,并向Exe插入Bubble offset <= d_IR(3)&d_IR(3)&d_IR(3)&d_IR(3)&d_IR(3 downto 0); d_IR为当前译码的指令,其中d_IR(3 downto 0)包含寄存器DR和SR的索引(INDEX)

4.执行部分的修改(exentity.vhd)

when aluAdd=> ALUResult := opR + opS; tempV := ((not opR(7))and(not opS(7))and ALUResult(7)) or (opR(7)and opS(7)and (not ALUResult(7))); when aluSub => ALUResult := opR - opS; tempV := ( opS(7)and(not opR(7))and (not ALUResult(7))) or ((NOT opS(7))and opR(7)and ALUResult(7)); when aluAnd => ALUResult := opR and opS; when aluOr => ALUResult := opR or opS; when aluShl => ALUResult(7 downto 1) := opR(6 downto 0); ALUResult(0) := '0'; cx := opR(7); when aluShr => ALUResult(6 downto 0) := opR(7 downto 1); ALUResult(7) := '0'; cx := opR(0); when aluSar => ALUResult(6 downto 0) := opR(7 downto 1); ALUResult(7) := opR(7); cx := opR(0); when aluLOADH => ALUResult := opS(4 downto 0)&opR(3 downto 0); when aluLOADL => ALUResult := '0'&opR(7 downto 4)&opS(3 downto 0); ALU的两个输入均为8位,计算过程中为了方便判断进位或移除,引入9位的临时中间变量。最终的ALU输出为8位。

(二)、系统级设计

1.概念设计

指令流水的基本思路是把每条指令划分为几个执行步骤,这些步骤在执行过

程中使用不同的资源从而在时间上能重叠起来,提高了整体工作负载的吞吐率。 我们将每条指令划分为“取指”、“译码”、“执行”、“访存”、“写回”这五个执行步骤。

五级流水概念图取指(IF)译码(ID)执行(Ex)访存(MA)写回(WB) 2.时序设计

五级流水的时序设计相对两级流水要复杂。在两级流水中,由于我们对时序的精巧设计,避免了相关问题的出现,但五级流水单凭时序安排是无法解决所有相关问题的,必须综合考虑各种情况。 ? 结构相关的处理

由于我们的设计中不包含缓存,因此会有取指和访存的冲突,即结构相关(见下图)。

执行访存取指译码取指译码

当冲突发生时,必须先“访存”,将“取指”延后一个时钟周期,这样才能保证指令的正确执行。处理结构相关需要做两项工作:1)冲突检测 2)取指延后。 1) 冲突检测

只有执行访存指令(LOAD/STORE)时,才会出现冲突。因此,我们在译码时产生一个标志是否访存的信号wrMem。含义如下: wMem 意义 00 写内存(STORE) 01 读内存(LOAD) 1× 不占用内存 通过检查“访存阶段”的m_wrMem就可确定是否冲突。 2)取指延后

在每次取指时,若有冲突,则往IR中写入空指令(NOP),并保持PC不变,使取指延后一个节拍。

? 数据相关的处理

数据相关是指在执行本条指令的过程中,如果用到的操作数是前面指令的执行结果,则必须等待前面的指令执行完成,并把结果写回寄存器或主存之后,本条指令才能继续执行[3]。我们采用设置专用数据通路(即傍路技术)来解决数据相关问题。但旁路技术并非一劳永逸。

若前一指令为LOAD,而后一指令和它数据相关,如下图所示,当下一指令的执行阶段需要数据时,上一指令尚未给出,这种情况是无法用旁路技术来解决的。

ALUIMRegMemRegIMRegALUMemReg

图 五级流水LOAD数据相关示意图

针对上述情况的一般处理方法是通过插入bubble使LOAD之后的两条指令拖后一个节拍执行[4]。但我们感觉这种处理过于繁琐。我们发现,如果在LOAD译码时,后面自动加一条空指令,即增加冗余,就可以避免上述情况的出现。在这种简化处理后,我们将数据相关划分为以下三种情况。 1.相邻指令数据相关 举例: INC R0

INC R0

在此情形下,将上一指令的ALU输出经缓存后直接送回,作为ALU多路选择器的入口

之一,如下图所示。

ALUIMRegMemRegIMRegALUMemReg

图 五级流水相邻指令数据相关示意图

具体代码片段为(forwardingentity.vhd):

--The first ALU operand comes from the prior ALU result if m_wRegEn='1' and m_SA=e_SA then forwardA <= \ 其中m_SA为当前处于访问内存(MEM)中寄存器输出结果的索引,e_SA为处于当前执行阶段中ALU的输入寄存器A的索引,倘若两个索引值相等,则产生相邻指令数据相关

2.中间隔1条指令的两指令数据相关 举例: INC R0 INC R1 INC R0

在此情形下,将第1条指令的回写数据送回作为ALU多路选择器的入口之一供第3条指令使用,如下图所示。

IMRegALUMemRegIMRegALUMemRegIMRegALUMemReg

图 五级流水相隔1条指令的两指令数据相关示意图

具体代码片段如下(forwardingentity.vhd): elsif w_wRegEn='1' and w_SA=e_SA then forwardA <= \ 其中w_SA为当前处于回写阶段(WB)中寄存器输出结果的索引,e_SA为处于当前执行阶段中ALU的输入寄存器A的索引,倘若两个索引值相等,则产生中间隔1条指令的两指令数据相关

3.中间隔2条指令的两指令数据相关 举例: INC R0

INC R1 INC R2 INC R0

第1和第4条指令数据相关,有两种处理方法。

方法1:在第4条指令的译码阶段作旁路处理,将第1条指令的回写数据作为

运算器的输入送入下一级,如下图所示。

方法2:考虑到读写寄存器的时间较短,因此将写寄存器的时机改在时钟下

降沿。这样1、4指令就没有数据相关了。

IMRegALUMemRegIMRegALUMemRegIMRegALUMemRegIMRegALUMemReg

图 五级流水相隔2条指令的两指令数据相关示意图

由于方法2处理较简洁,因此我们在实现时使用了后者。

具体部分代码如下(ifentity.vhd):

process(reset,clk,PCStall) begin if reset = '0' then PC <= x\ elsif FALLING_EDGE(clk) and (PCStall='0') then PC <= PCnext; end if; end process; 可以看到更新PC的时机为FALLING_EDGE。

? 控制相关的处理

控制相关是指因为程序的执行方向可能改变而引起的相关。当执行跳转指令时,就会发生这种情况。除JR外,JRZ等条件跳转需要根据当前状态位来决定是否跳转,而当前状态位是由前面最近的会影响状态位的指令(如算术指令)决定。常规的也是比较简单的做法是在碰到JRX之类的跳转指令时,延迟后边流水线的进入。但我们通过分析,认为可以一点都不必延迟,通过旁路处理把控制相关转为数据相关来处理。这样处理,不必延迟,可以提高流水线的性能。按我们的方式解决控制相关需要做两项工作: 1)通过旁路,提供状态寄存器的值和临时状态位的值,为判断是否跳转作准备; 2)选择PC更新的时机

1.旁路处理

在每条指令译码时,会产生一个信号setFlag,它决定了在执行阶段是否根据ALU计算结果改变状态位。从下面的时序图中可以发现,只要我们在JRX指令译码时提供以下3个信号就可作出是否跳转的决定: 信号 含义 tFlag ALU计算出的临时状态位, Flag 状态寄存器输出, e_setFlag 状态寄存器写使能 表 处理控制相关信号 若e_setFlag要写状态寄存器,则说明前一条指令会影响状态位,这时根据tFlag决定是否跳转;若e_setFlag要保持状态寄存器,则说明前一条指令不会影响状态位,这时根据Flag决定是否跳转。

译码前一条指令取指JR×后一条指令译码PC更新取指译码执行

图 五级流水处理控制相关示意图

2.PC更新的时机

在最初设计时,我们考虑将PC放在时钟上升沿更新。若如此,不论JRX转移与否,都会顺序取下一指令。因此,在发生跳转时要清除已读取的指令。处理方法是,在译码时判断上一条指令是否要跳转,若是则产生doNothing信号。这样就清除了已读取的指令。如果把PC更新放在下降沿(若上图所示),则不存在上述问题。但我们担心这种处理在时间上可能会比较紧张。不过,实践表明这种处理是可行的。

? PC控制的总结:

按照我们的设计,PC是在取指之后的第一个时钟下降沿更新。但当访存和取指冲突时需要特殊处理,分两种情况讨论。 1.访存指令不接连出现

访存时更新PC,执行空指令时保持PC不变,见下图。

访存指令不接连出现时的PC更新时序图执行访存取指译码PC更新NOP译码PCStall正常取指译码PC更新Do Nothing取指延后

图 五级流水访存指令不接连出现时的PC更新示意图

2.访存指令接连出现

除第一个访存阶段外,其余访存阶段PC都保持不变。

访存指令接连出现时的PC更新时序图执行访存执行访存取指译码PC更新NOP译码PCStallNOP译码PCStall正常取指译码PC更新Do NothingDo Nothing取指延后 图 五级流水访存指令接连出现时的PC更新示意图

在解决了结构相关、控制相关、数据相关后,五级流水时序图最终设计如下:

取指译码PC更新执行访存写回取指译码执行访存写回取指译码执行访存写回取指译码执行访存写回取指译码执行访存写回

图 五级流水时序图

(二)、结构级设计

1. 总体逻辑结构计

五级流水CPU结构图IRFlushHazadrDetectUnitPCFlushtFlag Flag OperatorPCnextMUX1+IF_IDRegID_EXRege_ALUSrc, e_ALUOpr, e_SetFlagEX_MEMRegm_wrMemMEM_WBRegw_wrMem+offsetIMMNOPPCOuterDB1MUX0指令寄存器IRRegArrayAoutSASBBoutw_wRegEnw_SBWrite dataRegSelRegOutREGISTERSMUXALUaIntFlagAflagLALUOutUMUXALUbInREGISTERSm_ALUOutOuterDBREGISTERSw_MemToRegw_ALUOutw_MemOut0MUX1m_RBdataforwardAm_wRegEnm_SAw_wRegEnforwardBForwarding Unite_SAe_SBw_SAPCm_ALUOutw_wrMem“zzzz”MemOuterDBRead data MUX wrMAUnit1 MUX 0Write datawrMem_addr

图 五级流水整体结构图

整个CPU由以下几个模块组成: ? 取指模块(IF):给出内存地址,读取指令并送入指令寄存器,为下一级

准备数据。

由于PC控制模块处于取指模块中,因此控制相关的检测也置于取指模块。 ? 译码模块(ID):读取寄存器值和指令译码。我们采取一次译码,逐级传

递的方式,译出后几级流水所需的控制信号和数据(如立即数等),在每次时钟上升沿到来时送入下一级。实际上,结构相关、控制相关、数据相关的检测都可归入译码部分。考虑到“相关检测”涉及到的信号分属不同阶段以及整体结构的清晰性,我们将“相关检测”独立出来。 ? 执行模块(Ex):完成算术逻辑运算、计算有效地址和提供数据通道。 ? 访存模块(Ma):选择地址线的数据来源和数据线的流向。访存和取指在

功能上是独立的,但CPU对外只有一条地址线和数据线的事实决定了访存和取指是相互联系的。当执行LOAD/STORE指令时,地址线由ALU送入“访存段”的值提供;取指时,则由PC提供。当写内存时,CPU内部数据送数据线;当需要读内存时,CPU往数据线送高阻。 ? 回写模块(Wb):选择回写数据源和根据写使能信号wRegEn将数据回写到

寄存器堆;

? HazardDetectUnit模块:检测结构相关; ? ForwardingUnit模块:检测数据相关。

2. 关键分模块结构设计

? 执行模块(Ex)

执行模块的主要工作是完成算术逻辑运算、计算有效地址和提供数据通道。执行模块的主体部分是运算器,其总体结构和两级流水是相似的。主要不同之处在于增加了旁路模块,这是由于五级流水存在数据相关需要旁路处理。

五级流水CPU运算器结构图傍路模块e_RAoutforwardAMUXMUXw_RBdatam_ALUOute_RBoutforwardBALUaIn 010xFFFFIMMALUbInALUSrcMUXExtTo17bitsExtTo17bitsOperation MuxALUOpr-与门或门异或SHLSHRSARCXSetFlag+tFlagCXC,Z,V,SFLAGClkALUOut

图 五级执行模块结构图

? HazardDetectUnit模块

该模块通过检查“访存阶段”的m_wrMem来确定是否发生结构相关。具体请参阅上文中处理结构相关的部分。 结构图:

d_IRm_wrMemw_wrMemHazardDetectUnit

图 五级HazardDetectUnit模块结构图 信号说明 端口 输入 输出 信号 m_wrMem d_IR PCStall 含义 wrMem处于访存阶段的值 指令寄存器 ‘1’ : 保持PC不变 ‘0’: PC更新 信号 w_wrMem IFFlush 含义 wrMem处于回写阶段的值 ‘1’: NOP写入IR ‘0’: 内存输出写入IR PCStallIFFlush 表 HazardDetectUnit信号说明

? 回写模块(WB)

回写是一条指令执行过程中的最后一步。它的工作是选择回写数据源和根据写使能信号wRegEn将数据回写到寄存器堆。需要选择的数据源共有两项:运算器输出和内存输出。在执行算术逻辑、移位等指令时选择运算器输出;执行LOAD指令时选择内存输出。 结构图:

w_ALUOutw_memToRegw_MemOut0 MUX 1w_WBdata写使能目的寄存器号Write datawRegEndestRegCLKRegArray

图 五级回写模块结构图 信号说明: 信号 含义 w_memToR‘1’: 内存数据到寄存器 eg ‘0’: ALU输出到寄存器 wRegEn ‘1’: 允许写寄存器 ‘0’: 禁止写寄存器 表 五级回写模块信号说明

? 2.2.4 ForwaringUnit模块

在“时序设计”部分,我们已对“如何检测数据相关”作了详细叙述。具体实现由

ForwardingUnit模块完成。 结构图

e_SAe_SBm_SAw_SAm_wRegEnw_wRegEnForwarding UnitforwardAforwardB

图 五级Forwarding模块结构图 信号说明 端口 信号 含义 信号 含义 e_SA 寄存器A口选择信e_SB 寄存器B口选择信号 号处于执行阶段的处于执行阶段的值 输入 值 m_SA 寄存器A口选择信w_SA 寄存器A口选择信号号处于访存阶段的处于回写阶段的值 值 m_wRegE寄存器写使能处于w_wRegEn 寄存器写使能处于回n 访存阶段的值 写阶段的值 输出 forwradA 选择ALU的A口数forwradB 选择ALU的B口数据 据 表 五级Fowarding模块信号说明 四、 测试

我们通过使用DebugController和CPU的显示寄存器结果的接口来调试如下程序:

1.测试代码如下,通过移位相加模拟乘法的过程 ; 8bit x 8bit multiplier ; ; 测试指令:置立即数,AND, 条件跳转, 左移, 右移 ; MAIN: MOVI R0,3 ;被乘数 MOVI R1,2 ;乘数 MOVI R2,0 ;结果 LOOP: MOVI R3,1 AND R3,R1 JRZ YW ;r3=0时跳转 ADD R2,R0 ;否则加到部分积 YW: SHL R0 SHR R1 CMP R1,0 ;r1不为0则跳转 JRNZ LOOP HALT

;RESULT:R2=6

测试结果:R2=6。 2.

;MEMORY COPY ;内存读写测试 MAIN: MOVI R0,0 ;目的地址,选取0作为地址因为这里读完之后就没用了 MOVI R1,3 STORE R3,R1 ;r1数据,r3地址 LOAD R2,R3 ;R3地址,r2数据 HALT ;RESULT:R2=3

测试结果:R2=3。

五、 不足之处

由于我们在选取指令的时候,没有选取LOADH/LOADL指令,导致最终我们MOVI指令的立即数范围比较小,测试的时候不方便引入一个较大的数字。

六、 实验中遇到的困难记录

a) Quartus ii 9.0 在含有多网卡的笔记本上无法正常工作

b) Debugcontroller仅支持16、32字长的代码

七、实验总结

李杰:这本次实验中,我承担了比较小的一份任务,整个过程中都是在队友的带领下完成的。从这次实验中我们可以意识到自己的不足,在一边要完成任务一边又要复习相关知识的同时,我们的能力也有所提高。所以不管是学习什么东西,只有多次的反复复习,同时又能够应用到我们的生活中才可以更加的稳固我们的

知识。学习任何东西都是一个过程,没有人可以一蹴而就,只有反复积累才能成功。

李宗桓:同样是代码,但是VHDL的代码跟普通C、Java的代码有着很不一样的感觉。比如说,在时钟上升沿或者下降沿到来时,会触发多个模块同时开始工作。对于这份16位的CPU代码来说,一开始比较难理解的就是不同模块之间寄存器的传值。(同时这也是含有流水的CPU和不含有流水CPU的区别),此外,处理数据相关部分也是一大难点,最难理解的部分是结构相关部分。所幸的是,我们并不太需要代码中的太多逻辑。通过这次试验,最大的感触就是当我一开始去看这一份代码的时候,我感到很难和很不可思议。在我完全理解之后,我便感到豁然开朗。大概这就是我们作为学生最基本的涵义,学生学生,学习“生”疏的东西。只有学习和接触生疏的东西,才能熟悉之。

七、 附完整源代码

addr_muxentity.vhd

library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use work.unitpack.all; entity Addr_muxEntity is port( PC : in word; ALUOut : in word; addrSel: in std_logic; addr : out word ); end entity ; architecture Addr_muxArch of Addr_muxEntity is begin with addrSel select addr <= PC when '0', ALUOut when others; end architecture; cpuentity.vhd

library ieee;

use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;

use work.unitPack.all;

entity CPUEntity is port( reset :in std_logic; --复位 clk :in std_logic; --时钟 OuterDB :INOUT std_logic_vector(15 downto 0);--内存数据线 memAddr :out std_logic_vector(7 downto 0);--内存地址线 wr :out std_logic; --内存读写使能 flag :out std_logic_vector(3 downto 0); --状态位CZVS RegSel :in std_logic_vector(3 downto 0); --寄存器选择 RegOut :out std_logic_vector(7 downto 0) --寄存器值输出 ); end CPUEntity;

architecture CPUArch of CPUEntity is --*** to IF Unit signal s_i_PCPlusOffset : word; signal s_PCStall : std_logic; signal s_IFFlush : std_logic; signal s_tempZ,s_tempC : std_logic; --*** to ID Unit signal s_PCInc1 : word; signal s_d_IR : word; signal s_w_WBData : word; signal s_w_destReg : std_logic_vector(1 downto 0); signal s_w_wRegEn : std_logic; signal s_RegSel : std_logic_vector(1 downto 0); signal s_RegOut : word; --*** to Ex Unit signal s_e_SA : std_logic_vector(1 downto 0); signal s_e_SB : std_logic_vector(1 downto 0); signal s_e_RAOut : word; signal s_e_RBOut : word; signal s_e_IMM : word; signal s_e_ALUSrc : std_logic_vector(2 downto 0); signal s_e_ALUOpr : std_logic_vector(3 downto 0); signal s_e_SetFlag : std_logic_vector(2 downto 0); signal s_e_wrMem : std_logic_vector(1 downto 0); signal s_e_wRegEn : std_logic; signal s_e_destReg : std_logic_vector(1 downto 0); signal s_e_MemToReg : std_logic; signal s_forwardA : std_logic_vector(1 downto 0);

signal s_forwardB : std_logic_vector(1 downto 0); --*** to MemAccess Unit signal s_PCaddr : word; signal s_m_ALUOut : word; signal s_m_RBdata : word; signal s_m_wrMem : std_logic_vector(1 downto 0); signal s_m_wRegEn : std_logic; signal s_m_memToReg : std_logic; signal s_m_destReg : std_logic_vector(1 downto 0); --*** to Forwarding Unit signal s_w_ALUOut : word; signal s_m_SA : std_logic_vector(1 downto 0); signal s_w_SA : std_logic_vector(1 downto 0); --*** to WB Unit signal s_w_memToReg : std_logic; --选择回写的数据源(s_w_ALUOut、OuterDB) signal s_m_flag : std_logic_vector(3 downto 0); --*** to WB signal s_w_flag : std_logic_vector(3 downto 0); signal s_w_MemOut : word; signal s_w_wrMem : std_logic_vector(1 downto 0);

------------------------------------- component IFEntity is --取指模块 port ( reset : in STD_LOGIC; clk : in STD_LOGIC; Z : in std_logic; --状态位 C : in std_logic; tempZ : in std_logic; --临时状态位,傍路处理 tempC : in std_logic; e_setFlag : in std_logic_vector(2 downto 0); PCPlusOffset: in word; --PC + Offset PCStall : in std_logic; --'1' : PC 保持不变 IFFlush : in std_logic; --'1' : NOP->IR OuterDB : in word; PC_addr : out word; --PC作为内存地址输出,用于下一节拍的取指 d_PCInc1 : out word; --PC + 1 d_IR : out word --指令寄存器输出 ); end component IFEntity; component IDEntity is --译码模块 port( reset : in std_logic; clk : in std_logic; d_IR : in word;

d_PCInc1 : in word; --*** for Regs Bank w_WBData : in word; w_destReg : in std_logic_vector(1 downto 0); -- Destination Reg index w_wRegEn : in std_logic; -- '1' enable e_SA,e_SB : out std_logic_vector(1 downto 0); i_PCPlusOffset : out word; --*** for ALU e_RAOut,e_RBOut : out word; e_IMM : out word; e_ALUSrc : out std_logic_vector(2 downto 0); e_ALUOpr : out std_logic_vector(3 downto 0); e_SetFlag: out std_logic_vector(2 downto 0); --*** for Memory e_wrMem : out std_logic_vector(1 downto 0); --\nothing --*** for Regs e_wRegEn : out std_logic; --寄存器写使能 e_destReg : out std_logic_vector(1 downto 0); e_MemToReg : out std_logic; --内存写入寄存器使能 --Cpu Interface --------------------------------- RegSel : in std_logic_vector(1 downto 0); RegOut : out word ); end component ; component ExEntity is --执行模块 port( reset,clk : in std_logic; --*** Input for ALU e_RAOut,e_RBOut : in word; e_ALUSrc : in std_logic_vector(2 downto 0); e_ALUOpr : in std_logic_vector(3 downto 0); e_SetFlag : in std_logic_vector(2 downto 0); e_IMM : in word; forwardA,forwardB : in std_logic_vector(1 downto 0); --*** for Forwarding e_SA : in std_logic_vector(1 downto 0); m_SA : out std_logic_vector(1 downto 0); e_ALUOut : in word; w_WBdata : in word; m_ALUOut : out word; m_RBdata : out word;

i_tempZ : out std_logic; i_tempC : out std_logic; --*** Control Signal for Ex_MemReg & Mem_WBReg m_flag : out std_logic_vector(3 downto 0); e_wRegEn : IN std_logic; m_wRegEn : out std_logic; e_memToReg : in std_logic; m_memToReg : out std_logic; e_destReg : IN std_logic_vector(1 downto 0); m_destReg : out std_logic_vector(1 downto 0); e_wrMem : IN std_logic_vector(1 downto 0); --\do nothing m_wrMem : out std_logic_vector(1 downto 0) --\do nothing ); end component; component MemAccessEntity is --访存模块 port( reset,clk : in std_logic; m_wrMem : in std_logic_vector(1 downto 0); w_wrMem : out std_logic_vector(1 downto 0); m_ALUOut : in word; -- Memory addr m_RBdata : in word; wr : out std_logic; --内存读写控制 '1':read , '0':write OuterDB : inout word; w_ALUOut : out word; w_MemOut : out word; ----------------- m_flag : in std_logic_vector(3 downto 0); w_flag : out std_logic_vector(3 downto 0); ---------- PC : in word; addr : out word; ---------- --*** for Forwarding m_SA : in std_logic_vector(1 downto 0); w_SA : out std_logic_vector(1 downto 0); --*** for WB Reg m_wRegEn : in std_logic; m_destReg : in std_logic_vector(1 downto 0); m_memToReg : in std_logic; --*** for WB Reg

w_wRegEn : out std_logic; w_destReg : out std_logic_vector(1 downto 0); w_memToReg : out std_logic ); end component; component ForwardingEntity is --数据相关检测及傍路处理模块 port( m_wRegEn : in std_logic; w_wRegEn : in std_logic; m_SA : in std_logic_vector(1 downto 0); w_SA : in std_logic_vector(1 downto 0); e_SA : in std_logic_vector(1 downto 0); e_SB : in std_logic_vector(1 downto 0); forwardA : out std_logic_vector(1 downto 0); forwardB : out std_logic_vector(1 downto 0) ); end component ; component HazardDetectEntity is --控制相关检测及处理模块 port( m_wrMem : in std_logic_vector(1 downto 0); w_wrMem : in std_logic_vector(1 downto 0); d_IR : in word; IFFlush : out std_logic; PCStall : out std_logic ); end component; begin --一级流水,取指 IFUnit: IFEntity port map (reset=>reset, clk=>clk, Z=>s_m_flag(2), C=>s_m_flag(3), tempZ=>s_tempZ, tempC=>s_tempC, e_setFlag=>s_e_SetFlag, PCPlusOffset=>s_i_PCPlusOffset, PCStall=>s_PCStall, IFFlush=>s_IFFlush, OuterDB=>OuterDB(7 downto 0), PC_addr=>s_PCaddr, d_PCInc1=>s_PCInc1, d_IR=>s_d_IR );

--二级流水,译码 IDUnit: IDEntity port map ( reset=>reset, clk=>clk, d_IR=>s_d_IR, d_PCInc1=>s_PCInc1, w_WBData=>s_w_WBData, w_destReg=>s_w_destReg, w_wRegEn=>s_w_wRegEn, i_PCPlusOffset=>s_i_PCPlusOffset, e_SA=>s_e_SA, e_SB=>s_e_SB, e_RAOut=>s_e_RAOut, e_RBOut=>s_e_RBOut, e_IMM =>s_e_IMM, e_ALUSrc=>s_e_ALUSrc, e_ALUOpr=>s_e_ALUOpr, e_SetFlag=>s_e_SetFlag, e_wrMem=>s_e_wrMem, e_wRegEn=>s_e_wRegEn, e_destReg=>s_e_destReg, e_MemToReg=>s_e_MemToReg, RegSel=>s_RegSel, RegOut=>s_RegOut ); --三级流水,执行/计算有效地址 ExUnit: ExEntity port map( reset=>reset, clk=>clk, e_RAOut=>s_e_RAOut, e_RBOut=>s_e_RBOut, e_ALUSrc=>s_e_ALUSrc, e_ALUOpr=>s_e_ALUOpr, e_SetFlag=>s_e_SetFlag, e_IMM =>s_e_IMM, e_wrMem=>s_e_wrMem, e_wRegEn=>s_e_wRegEn, e_destReg=>s_e_destReg, e_MemToReg=>s_e_MemToReg, forwardA=>s_forwardA, forwardB=>s_forwardB, e_ALUOut=>s_m_ALUOut, e_SA=>s_e_SA, m_SA=>s_m_SA, m_ALUOut=>s_m_ALUOut,

w_WBData=>s_w_WBData, m_flag=>s_m_flag, i_tempZ=>s_tempZ, i_tempC=>s_tempC, m_RBdata=>s_m_RBdata, m_wrMem =>s_m_wrMem, m_wRegEn=>s_m_wRegEn, m_memToReg=>s_m_memToReg, m_destReg=>s_m_destReg ); --四级流水,访问内存 MemAccessUnit: MemAccessEntity port map (reset=>reset, clk=>clk, m_wrMem=>s_m_wrMem, w_wrMem=>s_w_wrMem, m_ALUOut=>s_m_ALUOut, m_RBdata=>s_m_RBdata, wr=>wr, OuterDB=>OuterDB(7 downto 0), w_ALUOut=>s_w_ALUOut, w_MemOut=>s_w_Memout, m_flag=>s_m_flag, w_flag=>s_w_flag, -- PC=>s_PCaddr, addr=>memAddr, -- m_SA=>s_m_SA, w_SA=>s_w_SA, m_wRegEn=>s_m_wRegEn, m_destReg=>s_m_destReg, m_memToReg=>s_m_memToReg, w_wRegEn=>s_w_wRegEn, w_destReg=>s_w_destReg, w_memToReg=>s_w_memToReg ); --*************************************** --五级流水,回写寄存器

with s_w_memToReg select --选择回写的数据源 s_w_WBData <= s_w_ALUOut when '1', s_w_MemOut when others; process(clk) begin

if FALLING_EDGE(clk) then flag <= s_w_flag; end if; end process; --*************************************** --傍路处理 ForwardUnit: ForwardingEntity port map( m_wRegEn=>s_m_wRegEn, w_wRegEn=>s_w_wRegEn, m_SA=>s_m_SA, w_SA=>s_w_SA, e_SA=>s_e_SA, e_SB=>s_e_SB, forwardA=>s_forwardA, forwardB=>s_forwardB ); --结构、控制相关的处理 HDUnit: HazardDetectEntity port map ( m_wrMem=>s_m_wrMem, w_wrMem=>s_w_wrMem, d_IR=>s_d_IR, IFFlush=>s_IFFlush, PCStall=>s_PCStall ); -- debug process(RegSel,s_d_IR,s_PCAddr,s_RegOut) begin case RegSel is when \ when \ when others => s_RegSel <= RegSel(1 downto 0); RegOut <= s_RegOut; end case; end process; ------- end architecture ;

exentity.vhd

library ieee;

use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use work.unitPack.all;

entity ExEntity is port( reset,clk : in std_logic; --*** Input for ALU e_RAOut,e_RBOut : in word; e_ALUSrc : in std_logic_vector(2 downto 0); e_ALUOpr : in std_logic_vector(3 downto 0); e_SetFlag : in std_logic_vector(2 downto 0); e_IMM : in word; forwardA,forwardB : in std_logic_vector(1 downto 0);--傍路选择 --*** for Forwarding e_SA : in std_logic_vector(1 downto 0); m_SA : out std_logic_vector(1 downto 0); e_ALUOut : in word; w_WBdata : in word; m_ALUOut : out word; m_RBdata : out word; i_tempZ : out std_logic; i_tempC : out std_logic; --*** Control Signal for Ex_MemReg & Mem_WBReg m_flag : out std_logic_vector(3 downto 0); e_wRegEn : IN std_logic; m_wRegEn : out std_logic; e_memToReg : in std_logic; m_memToReg : out std_logic; e_destReg : IN std_logic_vector(1 downto 0); m_destReg : out std_logic_vector(1 downto 0); e_wrMem : IN std_logic_vector(1 downto 0); --\read, \ m_wrMem : out std_logic_vector(1 downto 0) --\read, \ ); end entity ;

architecture ExArch of ExEntity is signal ALUaIn,ALUbIn : word; signal dout : word; signal C,Z,V,S : STD_LOGIC; signal tempFlag : std_logic_vector(3 downto 0); begin --选择运算器A,B口数据来源 ****************** with forwardA select ALUaIn <= e_RAOut when \ e_ALUOut when \ w_WBdata when \

w_flag : out std_logic_vector(3 downto 0); PC : in word; --PC输入 addr : out word; --输出到内存地址线 --*** for Forwarding m_SA : in std_logic_vector(1 downto 0); w_SA : out std_logic_vector(1 downto 0); --*** for WB Reg m_wRegEn : in std_logic; m_destReg : in std_logic_vector(1 downto 0); m_memToReg : in std_logic; --*** for WB Reg w_wRegEn : out std_logic; w_destReg : out std_logic_vector(1 downto 0); w_memToReg : out std_logic ); end entity ;

architecture MemAccessArch of MemAccessEntity is begin --内存读写控制*************************** process(clk,m_wrMem,m_ALUOut,m_RBdata,PC) begin case m_wrMem is when \ => addr <= m_ALUout; wr <= '0'; -- write Memory OuterDB <= m_RBdata; when \ => wr <= '1'; addr <= m_ALUout; OuterDB <= Z8; --MODIFY PRE:M_RBDATA when others => wr <= '1'; addr <= PC; OuterDB <= Z8; end case; end process; --*************************************** --控制信号Mem to WB process(reset,clk) begin if reset='0' then w_wRegEn <= '0'; w_wrMem <= \

AT 09_04_20_45

elsif RISING_EDGE(clk) then w_flag <= m_flag; w_ALUOut <= m_ALUOut; w_SA <= m_SA; w_wRegEn <= m_wRegEn; w_destReg<= m_destReg; w_memToReg<= m_memToReg; w_memOut <= OuterDB; w_wrMem <= m_wrMem; end if; end process; --*************************************** end architecture ;

unitpack.vhd

library ieee;

use ieee.std_logic_1164.all; PACKAGE unitPack IS constant ZERO8 : STD_LOGIC_VECTOR(7 DOWNTO 0) := \ constant ZERO9 : STD_LOGIC_VECTOR(8 DOWNTO 0) := \ constant Z8 : STD_LOGIC_VECTOR(7 DOWNTO 0) := \ -- ALU: select data source constant selA0 : std_logic_vector(2 downto 0) := \ constant selAB : std_logic_vector(2 downto 0) := \ constant selA1 : std_logic_vector(2 downto 0) := \ constant sel0B : std_logic_vector(2 downto 0) := \ constant selAF : std_logic_vector(2 downto 0) := \ constant selAD : std_logic_vector(2 downto 0) := \ constant sel0D : std_logic_vector(2 downto 0) := \ -- ALU: Select operation constant aluAdd : std_logic_vector(3 downto 0) := \ constant aluSub : std_logic_vector(3 downto 0) := \ constant aluAnd : std_logic_vector(3 downto 0) := \ constant aluOr : std_logic_vector(3 downto 0) := \ constant aluXor : std_logic_vector(3 downto 0) := \ constant aluShl : std_logic_vector(3 downto 0) := \ constant aluShr : std_logic_vector(3 downto 0) := \ constant aluSar : std_logic_vector(3 downto 0) := \ constant aluLOADH : std_logic_vector(3 downto 0) := \ constant aluLOADL : std_logic_vector(3 downto 0) := \ -- 状态位的控制信号 constant flag_hold : std_logic_vector(2 downto 0) := \

constant flag_update : std_logic_vector(2 downto 0) := \ constant flag_InnerDB : std_logic_vector(2 downto 0) := \ constant flag_C0 : std_logic_vector(2 downto 0) := \ constant flag_C1 : std_logic_vector(2 downto 0) := \ constant flag_clear : std_logic_vector(2 downto 0) := \ -- 指令操作码 constant ADD : std_logic_vector(3 downto 0):=\ constant SUBB : std_logic_vector(3 downto 0):=\ --constant DEC : std_logic_vector(7 downto 0):=\ --constant INC : std_logic_vector(7 downto 0):=\ constant CMP : std_logic_vector(3 downto 0):=\ constant ANDins : std_logic_vector(3 downto 0):=\ constant MOVI : std_logic_vector(3 downto 0):=\ --constant ORins : std_logic_vector(3 downto 0):=\ --constant XORins : std_logic_vector(7 downto 0):=\ --constant TEST : std_logic_vector(7 downto 0):=\ constant SHLIns : std_logic_vector(3 downto 0):=\ constant SHRIns : std_logic_vector(3 downto 0):=\ --constant SAR : std_logic_vector(7 downto 0):=\ constant MOV : std_logic_vector(3 downto 0):=\ constant LOAD : std_logic_vector(3 downto 0):=\ constant STORE : std_logic_vector(3 downto 0):=\ --constant PUSH : std_logic_vector(7 downto 0):=\ --constant POP : std_logic_vector(7 downto 0):=\ constant JR : std_logic_vector(3 downto 0):=\ constant JRC : std_logic_vector(3 downto 0):=\

constant JRNC : std_logic_vector(3 downto 0):=\ constant JRZ : std_logic_vector(3 downto 0):=\ constant JRNZ : std_logic_vector(3 downto 0):=\ constant NOP : std_logic_vector(3 downto 0):=\--15 --constant LOADH : std_logic_vector(7 downto 0):=\ --constant LOADL : std_logic_vector(7 downto 0):=\ constant NOPIns : std_logic_vector(7 downto 0):=\ -- 空操作控制信号 constant DoNothing :std_logic_vector(17 0):=\ -- Type definition subtype INDEXTYPE is INTEGER range 0 to 3; subtype WORD is std_logic_vector(7 downto 0);

type REGISTERARRAY is array ( 0 to 3 ) of WORD; -- 4 reg, default is 16 END unitPack;

downto

本文来源:https://www.bwwdw.com/article/dun7.html

Top