【五级流水线CPU】—— 1. 初始框架搭建

1. 基本知识

各模块文件

image-20210609102221169

(1)取指阶段

  • PC模块:给出指令地址,其中实现指令指针寄存器PC,该寄存器的值就是指令地址。
  • IF/ID模块:实现取指与译码阶段之间的寄存器,将取指阶段的结果(取得的指令、指令地址等信息)在下一个时钟传递到译码阶段。

(2)译码阶段

  • ID模块:对指令进行译码,译码结果包括运算类型、运算所需的源操作数、要写入的目的寄存器地址等。
  • Regfile模块:实现了32个32位通用整数寄存器,可以同时进行两个寄存器的读操作和一个奇存器的写操作
  • ID/EX模块:实现译码与执行阶段之间的寄存器,将译码阶段的结果在下一个时钟周期传递到执行阶段。

(3)执行阶段

  • EX模块:依据译码阶段的结果,进行指定的运算,给出运算结果。
  • DIV模块:进行除法运算的模块。
  • EX/MEM模块:实现执行与访存阶段之间的寄存器,将执行阶段的结果在下一个时钟周期传递到访存阶段。

(4)访存阶段

  • MEM模块:如果是加载、存储指令,那么会对数据存储器进行访问。此外,还会在该模块进行异常判断。对应memv文件。
  • MEM/WB模块:实现访存与回写阶段之间的寄存器,将访存阶段的结果在下一个时钟周期传递到回写阶段,对应 mem wb。v文件

(5)回写阶段

  • CP0模块:对应MIPS架构中的协处理器CPO。
  • LLbit模块:实现寄存器 Llbit,在链接加载指令Ⅱ、条件存储指令sc的处理过程中会使用到该寄存器,第9章会详述
  • HILO模块:实现寄存器HI、LO,在乘法、除法指令的处理过程中会使用到这两个寄存器,第7章会详述

另外,还有一个CTRL模块

数据通路

最终要搭建的数据通路👇

image-20210609110518546

最终的顶层模块

image-20210625215357866

image-20210620134435006

小知识点

通用寄存器
在MIPS32指令集架构中定义了32个通用寄存器S0-S31, 使用某一个通用寄存器只需要给出相应索引,这个索引占用5bit,ori指令中的rs、t就是通用寄存器的索引,例如:当rs为5b00011时,就表示通用寄存器S3

2. ori指令的实现

2.1 ori指令数据通路

image-20210609111604164 image-20210609111934800

2.2 具体实现

宏定义

2.2.1 PC模块(取指阶段)
image-20210609114000789
2.2.2 IF-ID模块

image-20210611194342924
只有一个时序电路,IF/ID模块只是简单地将取指阶段的结果在每个时钟周期的上升沿传递到译码阶段。

2.2.3 Regfile模块

image-20210611203324317image-20210611203338999

  1. 操作一:定义了32个32位寄存器
  2. 操作二:实现写寄存器(时序逻辑电路)
    • 在写使能有效,复位无效,写操作目的寄存器不为0的情况下,可以将输入写到目的寄存器(因为MIPS32架构规定$0只能为0,所以不要写入)
  3. 操作三:实现两个读寄存器(组合逻辑电路)
    • 复位信号无效或者读到的是$0,直接输出0
    • 如果要读的寄存器和写的寄存器是同一个,直接输出即可
    • 注意一点:读寄存器操作是组合逻辑电路,也就是一旦输入的要读取的寄存器地址 radar或者 radar2发生变化,那么会立即给出新地址对应的寄存器的值,这样可以保证在译码阶段取得要读取的寄存器的值。
2.2.4 ID模块(译码)

ID模块的作用是对指令进行译码,得到最终运算的类型、子类型、源操作数1、源操作数2,要写入的目的寄存器地址等信息,其中运算类型指的是逻辑运算、移位运算、算术运算等,子类型指的是更加详细的运算类型,比如:当运算类型是逻辑运算时,运算子类型可以是逻辑“或”运算、逻辑“与”运算、逻辑“异或”运算等。

image-20210611211948483

ID中都是组合逻辑电路
ID模块可以分为3个阶段:
(1)第一段:实现对指令的译码,依据特征字区段区分指令。

wire[5:0] op = inst_i[31:26];	//指令码
wire[4:0] op2 = inst_i[10:6];
wire[5:0] op3 = inst_i[5:0];	//功能码
wire[4:0] op4 = inst_i[20:16];

在这里,当op等于EXE_ORI(6’b001101),就是ori指令

  • 读取的寄存器:ori指令只需读取一个寄存器rs的值,设置reg1_read_o=1,即对应读端口1,另一个操作数是立即数,reg2_read_o=0。
  • 执行的运算:alusel_o给出运算类型:逻辑运算,aluop_o给出子类型:或运算
  • 写入的目的寄存器:写入寄存器rt

(2)第二段:给出参与运算的源操作数1的值:根据reg1_read_o的取值,为1从寄存器读,为0取立即数

(3)第三段:给出参与运算的源操作数2的值:原理与第二段类似

2.2.5 ID/EX模块(译码)

只有一个时序电路,ID/EX模块只是简单地将译码阶段的结果在时钟周期的上升沿传递到执行阶段。执行阶段将依据这些值进行运算。

image-20210615222149245
2.2.6 EX模块(执行)

EX模块会从ID/EX模块得到运算类型 alusel_i、运算子类型 aluop_i、源操作数 regi i、源操作数reg2i、要写的目的寄存器地址wdi。EX模块会依据这些数据进行运算,其接口描述如表4-7所示。

image-20210615214900278
2.2.7 EX/MEM(执行-访存)

只有一个时序逻辑电路,在时钟上升沿,将执行阶段的结果传递到访存阶段

image-20210616192355782
2.2.8 MEM模块(访存阶段)
image-20210616192633230
2.2.9
image-20210616192721165 image-20210616192751911

回写阶段

经过上面的传递,ori指令的运算结果已经进入回写阶段了,这个阶段实际上是在 Regfile模块中实现的,从图4-5可知, MEM/WB模块的输出 wb wreg、wb_wd、 wb_wdata连接到Regfile模块,分别连接到写使能端口we、写操作目的寄存器端口waddr、写入数据端口 wdata,所以会将指令的运算结果写入目的寄存器,具体代码可以参考 Regfile模块。

顶层模块OpenMIPS
image-20210616203519848

3. 验证

3.1指令存储器ROM的实现

ROM模块是只读的

image-20210616205919672

inst_rom.data里面存储的是指令,其每行存储一条32位宽度的指令(使用十六进制表示),系统函数
$readmemh会将 inst_rom.data中的数据依次填写到 inst_mem数组中。

image-20210625212034638

OpenMIPS从指令存储器中读取指令,指令进入 Openmips开始执行。

结果

image-20210617170925793

遇到的错误

  1. id模块立即数的问题

image-20210617163354402

ex阶段的wreg_o和wd_o应该是1、01

image-20210617165254414

原因:输入全写成一样的了,修改后解决问题

image-20210617165621340
  1. 如果没有output,vivado有时候会在优化时把这个模块无视掉,所以在顶层模块随便写一个output。
    image-20210626104417439
  • 7
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值