BUAA-CO-p5-课下
命名规范
首先确定元件、线的命名方式
- 流水级名称采用教程的简称,以此为:
F D E M W
- 元件命名,采用
流水级简称_元件名
命名;实例化时采用小写元件名
- 流水线寄存器,采用
两端流水级简称_REG
命名;实例化时采用_小写两端简称_reg
- 每级CTRL采用
流水级简称_CTRL
(采用分布式译码) - 每级控制信号采用
流水级简称_信号名
结构
F级
input: D_NPC
(我的设计将NPC的选择放在了D级)
output: F_PC
, F_Instr
F_IFU
信号名 | I/O | 功能 |
---|---|---|
clk | I | 时钟信号 |
reset | I | 同步复位 |
PCEn | I | PC使能 |
NPC[31:0] | I | 选好了的NPC |
PC[31:0] | O | 当前PC |
Instr[31:0] | O | 指令 |
D级
元件:GRF, EXT, CMP, NPC
input: F_PC
, F_Instr
output: D_rs_data
, D_rt_data
; D_imm32
; D_NPC
; D_PC
, D_Instr
;
FD_REG
信号名 | I/O | 功能 |
---|---|---|
clk | I | 时钟信号 |
reset | I | 同步复位 |
FD_REG_En | I | 写使能(用于冻结) |
F_PC[31:0] | I | F级输入PC |
F_Instr[31:0] | I | F级输入Instr |
D_PC[31:0] | O | D级使用的PC |
D_Instr[31:0] | O | D级使用的Instr |
D_GRF
- 参考学长的博客,删除RegWr信号,改为“若不写入,则写入地址为0”
- 删除P4中GRFWrite模块,直接在顶层模块中进行多路选择
其他接口与P4无区别,这里不列表格了
D_EXT
信号名 | I/O | 功能 |
---|---|---|
EXTOp | I | 接收来自D_CTRL的控制信号 |
Imm16[15:0] | I | 16位立即数 |
Imm32[31:0] | O | 32位扩展后的立即数 |
D_CMP
去除P4 ALU中的eq_zero端口,改为D级中的此模块
信号名 | I/O | 功能 |
---|---|---|
CMP_rs[31:0] | I | 转发后的$rs |
CMP_rt[31:0] | I | 转发后的$rt |
CMPOp[1:0] | I | 比较方式的选择信号,可拓展 |
Branch | O | 是否跳转 |
D_NPC
信号名 | I/O | 功能 |
---|---|---|
NPCOp[2:0] | I | NPC控制信号 |
D_PC[31:0] | I | D级PC,用于branch型跳转 |
F_PC[31:0] | I | F级PC,用于default |
NPC_rs[31:0] | I | 转发后的$rs, 用于jr型 |
Branch | I | 是否进行branch |
NPC[31:0] | O | 处理后的NPC |
E级
元件:ALU
input: D_rs_data
, D_rt_data
, D_imm32
; D_PC
, D_Instr
output: E_ALU_result
, E_rt_data
, E_PC
, E_Instr
DE_REG
信号名 | I/O | 功能 |
---|---|---|
clk | I | 时钟信号 |
reset | I | 同步复位 |
D_rs_data[31:0] | I | D级$rs |
D_rt_data[31:0] | I | D级$rt |
D_imm32[31:0] | I | 扩展后32位立即数 |
D_PC[31:0] | I | D级PC |
D_Instr[31:0] | I | D级指令 |
E_rs_data[31:0] | O | E级使用的$rs |
E_rt_data[31:0] | O | E级使用的$rt |
E_imm32[31:0] | O | E级使用的32位立即数 |
E_PC[31:0] | O | E级PC |
E_Instr[31:0] | O | E级指令 |
E_ALU
信号名 | I/O | 功能 |
---|---|---|
A[31:0] | I | A端口 |
B[31:0] | I | B端口 |
ALUOp[2:0] | I | 计算模式选择 |
ALUresult[31:0] | O | 计算结果 |
M级
元件:DM
input: E_ALUresult
, E_rt_data
; E_PC
, E_Instr
output: M_ALUresult
, M_RD
; M_PC
, M_Instr
EM_REG
信号名 | I/O | 功能 |
---|---|---|
clk | I | 时钟信号 |
reset | I | 同步复位 |
E_ALUresult[31:0] | I | E级ALU计算结果 |
E_rt_data[31:0] | I | E级接收转发后的$rt |
E_PC[31:0] | I | E级PC |
E_Instr[31:0] | I | E级指令 |
M_ALUresult[31:0] | O | M级使用的ALU计算结果 |
M_rt_data[31:0] | O | M级使用的$rt |
M_PC[31:0] | O | M级PC |
M_Instr[31:0] | O | M级指令 |
M_DM
信号名 | I/O | 功能 |
---|---|---|
clk | I | 时钟信号 |
reset | I | 同步复位 |
MemWr | I | 写使能 |
Addr[31:0] | I | 写入地址 |
Data[31:0] | I | 写入数据 |
RD[31:0] | O | 读出数据 |
后续可增加DMOp
接口,对更多种类的load指令进行扩展
W级
input: M_ALUresult
, M_RD
; M_PC
, M_Instr
WM_REG
信号名 | I/O | 功能 |
---|---|---|
clk | I | 时钟信号 |
reset | I | 同步复位 |
M_RD[31:0] | I | M级DM读出数据 |
M_ALUresult[31:0] | I | M级传递的ALU计算结果 |
M_PC[31:0] | I | M级PC |
M_Instr[31:0] | I | M级指令 |
W_RD[31:0] | O | W级使用的DM读出 |
W_ALUresult[31:0] | O | W级使用的ALU计算结果 |
W_PC[31:0] | O | W级PC |
W_Instr[31:0] | O | W级指令 |
冒险的解决
AT法
:经过多少个时钟周期就必须要使用相应的数据
注意,一条指令可以有多条。如 和
:某个流水级中的某条指令,还需要多少个周期才能将结果写入流水级寄存器
对于不产生新数据的指令,我们认为 始终为0
数据冒险
旁路转发
X_AN == Y_AM && X_AN != 5'b0 && M_T_NEW == 2'b00 && RegWrite_Y == 1
读寄存器编号和写寄存器编号相同 && 寄存器编号不为0 && 转发流水级的 && GRF写使能为1
若GRF写使能为0,YA置0即可
为解决同一时钟周期写和读同一寄存器的问题,将GRF改为下跳沿写入
回传:根据GRFWDOp选择每一级的回传数据
- jal旁路转发:
- A1 = A2 = 31
阻塞一级
- 冻结
FD_REG
,即将FD_REG_En
置0 - 清除
DE_REG
,全部置0(同步复位即可) - 禁止PC继续计数,即将
PCEn
置0
阻塞第二级:
- 冻结
FD_REG
- 清除
DE_REG
PCEn
置0
(让E级的nop往下传,给E级一个新的nop)
BUAA-CO-p5-课下