MIPS流水线CPU的verilog实现 - 图文

更新时间:2024-01-20 17:33:01 阅读量: 教育文库 文档下载

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

一、 实验目的

1.

2. 3. 4.

了解提高CPU性能的方法。

掌握流水线MIPS微处理器的工作原理。

理解数据冒险、控制冒险的概念以及流水线冲突的解决方法。 掌握流水线MIPS微处理器的测试方法。

二、 实验任务

设计一个32位流水线MIPS微处理器,具体要求如下:

1. 至少运行下列MIPS32指令。

(1) 算术运算指令:ADD、ADDU、SUB、SUBU、ADDI、ADDIU。 (2) 逻辑运算指令:AND、OR、NOR、XOR、ANDI、ORI、XORI、SLT、SLTU、

SLTI、SLTIU。

(3) 移位指令:SLL、SLLV、SRL、SRLV、SRA。

(4) 条件分支指令:BEQ、BNE、BGEZ、BGTZ、BLEZ、BLTZ。 (5) 无条件跳转指令:J、JR。 (6) 数据传送指令:LW、SW。 (7) 空指令:NOP。

2. 采用5级流水线技术,对数据冒险实现转发或阻塞功能。

3. 在XUP Virtex-Ⅱ Pro 开发系统中实现MIPS微处理器,要求CPU的运行速度大于

25MHz。

三、 实验原理

1. 总体设计

流水线是数字系统中一种提高系统稳定性和工作速度的方法,广泛应用于高档CPU的架构中。根据MIPS处理器的特点,将整体的处理过程分为取指令(IF)、指令译码(ID)、执行(EX)、存储器访问(MEM)和寄存器会写(WB)五级,对应多周期的五个处理阶段。如图3.1所示,一个指令的执行需要5个时钟周期,每个时钟周期的上升沿来临时,此指令所代表的一系列数据和控制信息将转移到下一级处理。

图3.1 流水线流水作业示意图

由于在流水线中,数据和控制信息将在时钟周期的上升沿转移到下一级,所以规定流水线转移变量命名遵守如下格式:

名称_流水线级名称

例如:在ID级指令译码电路(Decode)产生的寄存器写允许信号RegWrite在ID级、

1

EX级、MEM级和WB级上的命名分别为RegWrite_id、RegWrite_ex、RegWrite_mem和RegWrite_wb。在顶层文件中,类似的变量名称有近百个,这样的命名方式起到了很好的识别作用。

1) 流水线中的控制信号

(1)IF级:取指令级。从ROM中读取指令,并在下一个时钟沿到来时把指令送到ID级的指令缓冲器中。该级控制信号决定下一个指令指针的PCSource信号、阻塞流水线的PC_IFwrite信号、清空流水线的IF_flush信号。

(2)ID级:指令译码器。对IF级来的指令进行译码,并产生相应的控制信号。整个CPU的控制信号基本都是在这级上产生。该级自身不需任何控制信号。

流水线冒险检测也在该级进行,冒险检测电路需要上一条指令的MemRead,即在检测到冒险条件成立时,冒险检测电路产生stall信号清空ID/EX寄存器,插入一个流水线气泡。

(3)EX级:执行级。该级进行算术或逻辑操作。此外LW、SW指令所用的RAM访问地址也是在本级上实现。控制信号有ALUCode、ALUSrcA、ALUScrB和RegDst,根据这些信号确定ALU操作、选择两个ALU操作数A、B,并确定目标寄存器。

另外,数据转发也在该级完成。数据转发控制电路产生ForwardA和ForwardB两组控制信号。

(4)MEM级:存储器访问级。只有在执行LW、SW指令时才对存储器进行读写,对其他指令只起到一个周期的作用。该级只需存储器写操作允许信号MemWrite。

(5)WB级:写回级。该级把指令执行的结果回写到寄存器文件中。该级设置信号MemtoReg和寄存器写操作允许信号RegWrite,其中MemtoReg决定写入寄存器的数据来自于MEM级上的缓冲值或来自于MEM级上的存储器。

2)流水线冒险

在流水线CPU中,多条指令通知执行,由于各种各样的原因,在下一个时钟周期中下一条指令不能执行,这种情况称为冒险。冒险分为三类:

①结构冒险:硬件不支持多条指令在同一个时钟周期内执行。MIPS指令集专为流水线设计,因此在MIPS CPU中不存在此类冒险。

②数据冒险:在一个操作必须等待另一操作完成后才能进行时,流水线必须停顿,这种情况称为数据冒险。数据冒险分为两类:

ⅰ数据相关:流水线内部其中任何一条指令要用到任何其他指令的计算结果时,将导致数据冒险。通常可以用数据转发(数据定向)来解决此类冒险。

ⅱ数据冒险:此类冒险发生在当定向的目标阶段在时序上早于定向的源阶段时,数据转发无效。通常是引入流水线阻塞,即气泡(bubble)来解决。。

③控制冒险:CPU需要根据分支指令的结果做出决策,而此时其他指令可能还在执行中,这时会出现控制冒险,也称为分支冒险。解决此类冒险的常用方法是延迟分支。

2.1)数据相关与转发

下面通过具体例子来阐述数据相关。见图3.2

2

图3.2 数据相关性问题实例图

可见,后4条指令都依赖于第一条指令得到寄存器$2的结果,但sub指令要在第五周期才写回寄存器$2,但在第三、四、五个时钟周期$2分别要被and、or和add三个指令用到,所以这三个指令得到的是错误的未更新的数据,会引起错误的结果;而第六个时钟周期$2要被sw指令用到,此时得到的才是正确的已更新的数据。这种数据之间的互相关联引起的冒险就是数据相关。

可以看出,当一条依赖关系的方向与时间轴的方向相反时,就会产生数据冒险。 (1)一阶数据相关与转发(EX冒险) 首先讨论指令sub与and之间的相关问题。

sub指令在第五周期写回寄存器$2,而and指令在第四周期就对sub指令的结果$2提出申请,显然将得到错误的未更新的数据。像这类第I条指令的源操作寄存器与第I-1条指令(即上一条指令)的目标寄存器相重,导致的数据相关称为一阶数据相关。见图3.3中实线所示。

图3.3 一阶数据相关实例图

3

可以发现,sub指令的结果其实在EX级结尾,即第三周期末就产生了;而and指令在第四时钟周期向sub指令结果发出请求,请求时间晚于结果产生时间,所以只需要sub指令结果产生之后直接将其转发给and指令就可以避免一阶数据相关。如图3.3虚线所示。转发数据为ALUResult_mem

数据转发由Forwarding unit单元控制,判断转发条件是否成立。转发机制硬件实现见图3.4

图3.4 转发机制的硬件实现

转发条件ForwardA、ForwardB作为数据选择器的地址信号,转发条件不成立时,ALU操作数从ID/EX流水线寄存器中读取;转发条件成立时,ALU操作数取自数据旁路。

转发条件:

① MEM级指令是写操作,即RegWrite_mem=1;

② MEM级指令写回的目标寄存器不是$0,即RegWriteAddr_mem≠0;

③ MEM级指令写回的目标寄存器与在EX级指令的源寄存器是同一寄存器,即

RegWriteAddr_mem=RsAddr_ex 或 RegWriteAddr_mem=RtAddr_ex。

(2)二阶数据相关与转发(MEM冒险)

接下来讨论sub指令与or指令之间的相关问题。 sub指令在第5时钟周期写回寄存器,而or指令也在第5时钟周期对sub指令的结果提出了请求,很显然or指令读取的数据是未被更新的错误内容。这类第I条指令的源操作寄存器与第I-2条指令(即之上第二条指令)的目标寄存器相重,导致的数据相关称为二阶数据相关。见图3.5中实线所示。

4

图3.5 一阶数据相关实例图

如前所述,or指令在第五时钟周期向sub指令结果发出请求时,sub指令的结果已经产生。所以,我们同样采用“转发”,即通过MEM/WB流水线寄存器,将sub指令结果转发给or指令,而不需要先写回寄存器堆。如图3.5中虚线所示。转发数据为RegWriteData_wb

转发条件:

① WB级指令是写操作,即RegWrite_wb=1;

② WB级指令写回的目标寄存器不是$0,即RegWriteAddr_wb≠0;

③ WB级指令写回的目标寄存器与在EX级指令的源寄存器是同一寄存器,即

RegWriteAddr_wb=RsAddr_ex 或 RegWriteAddr_wb=RtAddr_ex; ④ EX冒险不成立,即RegWriteAddr_mem≠RsAddr_ex 或

RegWriteAddr_mem=RtAddr_ex。

(3)三阶数据相关与转发

最后讨论sub指令与add指令之间的相关问题。

sub指令与add指令在第五时钟周期内同时读写同一个寄存器。这类同一周期内同时读写同一个寄存器的数据相关称之为三阶数据相关。如图3.6中实线所示。

图3.6 三阶数据相关实例图

假设寄存器的写操作发生在时钟周期的上升沿,而读操作发生在时钟周期的下降沿,那么读操作将读取到最新写入的内容。在这种假设条件下将不会发生数据冒险。这就要求流水线中的寄存器具有“先写后读(Read After Write)”的特性。

这类“写操作发生在时钟周期的上升沿,读操作发生在时钟周期的下降沿”的寄存器虽然在理论上是可实现的,但是不适合应用于同步系统,因为它不但影响系统的运行速度,而且影响系统的稳定性,是不可取的。

因此,我们采用“转发”机制来解决三阶数据相关冒险。该部分转发电路我们放在寄存器堆的设计中完成。如图3.6中虚线所示。转发数据为RegWriteData_wb。

转发条件为:

5

ID级设计符合要求。

2. EX级仿真

(1) ALU子模块仿真

对照ALU功能表,仿真结果正确。说明ALU子模块设计符合要求。

(2) EX模块仿真

ALU子模块功能已测试完毕,只需确认数据选择器与转发电路Forwarding的功能。

26

先观察Forwarding转发电路的信号:

信号之间的逻辑关系符合ForwardingA与ForwardingB的定义关系式。

然后观察操作数A与B的数据选择器的信号: 操作数A:

其中TempA为数据选择器输出信号;A为RsData。 操作数B:

其中TempB为数据选择器输出信号;B为RTData。 波形满足Forwarding的功能要求。

27

观察ALU_A与ALU_B数据选择器功能:

TempA与TempB分别是操作数A与B。从波形上可看出选择器符合设计要求。

EX级设计符合要求。

3. IF级仿真

JR、J、Z都为0,PC输入只 为NextPC=PC+4,符合要求。 {JR、J、Z}=100 PC=JrAddr {JR、J、Z}=010 PC=JumpAddr {JR、J、Z}=001 PC=branchAddr 符合设计要求

IF级符合设计要求。

PC_IFWrite=0,PC保持。 符合设计要求 28

4. 顶层仿真

测试指令为:

dout=32'h0800000b ; // j later

dout=32'h20080042 ; //earlier: addi $t0,$0,42 dout=32'h20090004 ; // addi $t1,$0,4

dout=32'h01095022 ; // sub $t2,$t0,$t1 (操作B一阶相关,操作A二阶相关) dout=32'h01485825 ; // or $t3,$t2,$t0 (操作A一阶相关,操作B三阶相关) dout=32'hac0b000c ; // sw $t3,0c($0) dout=32'h8d2c0008 ; // lw $t4,08($t1)

dout=32'h000c4080 ; // sll $t0,$t4,2 (数据冒险) dout=32'h8d2b0008 ; // lw $t3,08($t1) dout=32'h012a582b ; // sltu $t3,$t1,$t2 dout=32'h0800000a ; //done: j done

dout=32'h14000001 ; //later: bne $0,$0,end (分支条件不成立) dout=32'h1000fff4 ; // beq $0,$0,earlier (分支条件成立) dout=32'h00000000 ; //end: nop

JumpFlag={JR、J、Z}

初始指令为J指令,J=1, 所以IF_flash=1 ,清空IF/ID级寄存器,下一周 期指令=0.

J=1,使PC跳转 bne分支不成立 beq分支成立,Z=1,IF_flash=1,清空IF/ID级寄存器,下一周期指令=0. 29

加立即数4,下一周期操作数B=4,$0始终寄存0,操作数A=0,故ALUResult=4 数据相关,可以看到前两个指令的结果正确转发到操作数A与B 加立即数42,下一周期 $0始终寄操作数B=42,存0,操作数 A=0,故 ALUResult=42 没有跳转,可以看到PC正常增加 LW指令,$t1寄存4,即为操作数A,操作数B为立即数8 Sll位移运算,操作数为Sa=2 同样的LW指令,下一周期不存在数据冒险 $t3 SW指令,操作数B为立即数0c。储存$t3=0000007e,在两周期后存入DataRAM

数据冒险,阻塞信号Stall=1,流水线被阻塞 30

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

Top