流水线CPU设计(不考虑相关冲突)
所谓流起水来,就是理想情况下,流水线每一级都有指令且每个时钟周期都能处理完一条指令。
2.1 添加流水级间缓存
电路流水线化的主要初衷是为了缩短时序器件之间组合逻辑关键路径的时延,在不降低电路处理吞吐率的情况下提升电路的时钟频率。
2.1.1 流水线的划分
单发射五级流水划分:取值(IF),译码(ID),执行(EXE)、访存(MEM)、写回(WB)
取指阶段的主要功能是将指令取回,
译码阶段的主要功能是解析指令生成控制信号并读取通用寄存器堆生成源操作数,
执行阶段的主要功能是对源操作数进行算术逻辑类指令的运算操作或者访存指令的地址计算操作,
访存阶段的主要功能是取回访存的结果,
写回阶段的主要功能是将结果写入到通用寄存器堆。
我们就可以将之前设计的单发射 CPU 的数据通路拆分为五段,并在各段之间加入触发器作为流水线缓存。
我们将触发器归到它的输出对应的那一个流水阶段。因此位于取指阶段和译码阶段的触发器记 ID reg
。
2.1.2 流水线缓存中存放的内容
流水线缓存的内容分为控制内容和数据内容。
控制内容(暂时只需要1bit缓存有效位valid,0为无效,1为无效)
数据内容:包含将被隔断的信号。
一根信号可能会被多级流水线缓存多次隔断
举例:指令在 ID 阶段得到其对通用寄存器的写使能信号和写地址信号,但是这些信号直到指令位于 WB
阶段才被使用,即这些信号被 EXE、MEM、WB 三级流水线缓存隔断,所以这些信号在这三级流水线的
缓存中都要存放。
插入流水线缓存后,任何信号从其产生的流水线阶段开始到它使用的流水线阶段,途径的各级流水线缓存中都要存放该信号。
2.2 同步 RAM 的引入
首先我们来看看同步读CPU和异步读在时序特性上的区别:
同步RAM一次读数操作需要跨越两个时钟周期,第一个时钟周期向RAM发出读使能和读地址,第二个时钟RAM才返回
使用异步RAM时,CPU在IF阶段向指令RAM发出读使能和读地址,当拍就能得到指令RAM的返回结果(指令码),可以再时
钟上升沿到来时将指令码写入到ID阶段流水线缓存中
但我们可以明显的看出来,换成同步读后,时钟上升沿到来时还无法得到指令码,因此我们需要调整
一种设计考虑:流水线缓存的触发器都采用时钟上升沿触发,指令RAM采用时钟下降沿触发。
这个设计听起来很不错,但通过FPGA实现我们会发现,实现电路的频率会大幅度下降,这貌似与FPGA的底层电路实现有关,这里笔者与不是很清楚了。
最终我们考虑将指令RAM的访问分不到流水线中连续的两个阶段。
在不增加流水线级数的情况下,只有两种方案:
1.将指令RAM的读请求放在IF阶段,使指令RAM输出在指令ID阶段完成
2.在“更新PC的阶段”发起指令RAM的读请求(以nextPC为指令RAM的读地址,而不是以PC为指令RAM的读地址)这样输出在IF阶段便完成。
采用 ASIC方式实现,则第2种方案更好:对AISC实现来说,同步的RAM的clk-to-Q(响应延迟)延迟远比它输入端口的Setup延迟要大也远远大于触发器的clk-to-Q延迟
采用FPGA方式实现时由于 FPGA 上同步时序行为的 RAM 是用所谓的“block RAM”来实现的,这些 RAM 对应的底层电路就是 RAM。此时 RAM的 clk-to-Q 所引入的电路时延不再是主要矛盾了
同步 RAM 的读保持功能
含义:从采样到上一个有效的读命令的时钟沿开始,RAM的Q端将保持这个读操作对应数据,知道采样到下一条有效的命令,例如:
读命令只有在 RAM的片选使能信号有效的情况下才可能有效,所以当 RAM 的片选使能信号无效时,即
使 RAM 的地址不停地发生变化,RAM 也没有接收到任何新的读命令
2.3 调整更新 PC 的数据通路
2.3.1 调整转移指令更新 PC 的数据通路
原先:在处理转移指令的时候,将是否跳转的结果以及跳转目标地址计算所需的信息都保存在触发器中,等到处理转移延迟槽指令的时候,才能利用存储的信息最终完成对于 PC 的更新。
调整后:在转移指令在ID阶段计算出跳转信息后,正好IF是转移延迟槽指令,则ID阶段得到的跳转信息正好可以传递到IF计算即将更新的PC值,而不需要在流水线缓存中浪费资源。(不考虑取值堵塞)
2.3.2调整复位更新PC的数据通路
在复位信号有效期间会将 PC 寄存器复位成 0xBFBFFFFC 而不是 MIPS 指令系统规范中规定的规定的 0xBFC00000
2.4 流水线控制信号的设计(不考虑相关冲突)
这里我们结合不考虑相关冲突的流水线的实际情况,对电路中与流水线相关的控制信号进行调整
IF阶段:
由于目前只从指令RAM中取回指令,所以IF阶段的ready_go信号恒为1
ID阶段:
不考虑转移指令在ID阶段等待延迟槽指令取回,则ready_go信号恒为1
EXE阶段:
由于目前处理的所有指令在这一阶段均只需要一拍就可以完成,所以ready_go信号恒为 1。
MEM阶段:
由于目前只从数据RAM中取回数据,一定成功,则ready_go信号恒为1
WB阶段:
由于写回寄存器堆在一拍之内一定可以完成,所以WB阶段的ready_go信号恒为 1
虽然说了半天,五级流水的ready_go恒为1,但这样做是有自己的考虑在内的
一:是我们对于为什么这些信号是恒置1,要做到心中有数;
二:是我们不要着急把这些常值1带入到生成其它控制信号的逻辑中进行化简,因为随着设计复杂,信号也会极为复杂!