P6 用verilog描述支持 MIPS-C3 指令集的较为复杂的流水线 CPU的学习笔记和总结

 

1 教程中的设计要求和测试说明

1.1 设计要求

  • 处理器应支持 MIPS-C3 指令集。

    • MIPS-C3={LB、LBU、LH、LHU、LW、SB、SH、SW、ADD、ADDU、 SUB、 SUBU、 MULT、 MULTU、 DIV、 DIVU、 SLL、 SRL、 SRA、 SLLV、 SRLV、SRAV、AND、OR、XOR、NOR、ADDI、ADDIU、ANDI、ORI、 XORI、LUI、SLT、SLTI、SLTIU、SLTU、BEQ、BNE、BLEZ、BGTZ、 BLTZ、BGEZ、J、JAL、JALR、JR、MFHI、MFLO、MTHI、MTLO}

    • 所有运算类指令均暂不考虑因溢出而产生的异常。

指令名编号D_Tuse_GRF_A1D_Tuse_GRF_A2产生回写值最先保存回写值得级寄存器E_TnewM_TnewW_Tnew
LB01不需要M_DM_outWREG210
LBU11不需要M_DM_outWREG210
LH21不需要M_DM_outWREG210
LHU31不需要M_DM_outWREG210
LW41不需要M_DM_outWREG210
SB512不回写000
SH612不回写000
SW712不回写000
ADD811E_ALU_CMREG100
ADDU911E_ALU_CMREG100
SUB1011E_ALU_CMREG100
SUBU1111E_ALU_CMREG100
MULT1211不回写
MULTU1311不回写
DIV1411不回写
DIVU1511不回写
SLL16不需要1E_ALU_CMREG100
SRL17不需要1E_ALU_CMREG100
SRA18不需要1E_ALU_CMREG100
SLLV1911E_ALU_CMREG100
SRLV2011E_ALU_CMREG100
SRAV2111E_ALU_CMREG100
AND2211E_ALU_CMREG100
OR2311E_ALU_CMREG100
XOR2411E_ALU_CMREG100
NOR2511E_ALU_CMREG100
ADDI261不需要E_ALU_CMREG100
ADDIU271不需要E_ALU_CMREG100
ANDI281不需要E_ALU_CMREG100
ORI291不需要E_ALU_CMREG100
XORI301不需要E_ALU_CMREG100
LUI31不需要不需要E_ALU_CMREG100
SLT3200D_cmp_dataEREG000
SLTI330不需要D_cmp_dataEREG000
SLTIU340不需要D_cmp_dataEREG000
SLTU3500D_cmp_dataEREG000
BEQ3600不回写000
BNE3700不回写000
BLEZ380不需要不回写000
BGTZ390不需要不回写000
BLTZ400不需要不回写000
BGEZ410不需要不回写000
J42不需要不需要不回写000
JAL43不需要不需要D_PC+8DREG000
JALR440不需要D_PC+8DREG000
JR450不需要不回写000
MFHI46不需要不需要E_MDU_outMREG100
MFLO47不需要不需要E_MDU_outMREG100
MTHI481不需要不回写000
MTLO491不需要不回写000

2 模块定义

2.1 F级

2.1.1 PC

  • PC的主要功能是完成输出位于F级指令的地址

  • 同步复位后,PC指向0x0000_3000

端口名端口输入/输出信号名端口描述
input clkclk时钟信号
input resetreset同步复位信号,复位到0x0000_3000
input PC_enStall用于暂停操作,PC的使能端 当PC_en为0时,PC不工作,在时钟上升沿不改变值
input [31:0] F_NextPCF_NextPC下一条指令所在地址
output reg [31:0] F_PCF_PC当前F级指令所在地址

2.1.2 MUX_F_NextPC选择器(其实没什么用,懒得删了)

  • 同步复位时选择32'h0000_3004

模块端口名端口对应信号名对输入信号的描述
input [31:0] AD_NextPC当前D级计算的Next_PC
input [31:0] B32'h0000_3004
input Selreset同步复位信号
output [31:0] YF_NextPC当前F级的Next_PC

2.2 D级

2.2.1 DCTRL

  • D级控制器

  • 输出当前D级指令需要的控制信号

信号名描述
input [5:0] D_op当前D级指令的6位op码
input [4:0] D_rt当前D级指令的5位rt码,用于判定bgez和bltz
input [5:0] D_func当前D级指令的6位func码
input D_cmp_sign当前D级指令的1位比较输出信号
input [5:0] E_order当前E级指令的编号(用于生成转发需求者信号)
input [5:0] M_order当前M级指令的编号(用于生成转发需求者信号)
output [4:0] D_EXTop当前D级指令EXT模块功能选择信号 00000:符号扩展 00001:0扩展 00010:加载至最高位,低位补0
output [4:0] D_CMPop当前D级指令CMP模块功能选择信号 00000:相等判断
output [4:0] D_NPCop当前D级指令NPC模块功能选择信号 00000:PC+4 00001:PC+4+sign_extend(imm16) 00010:PC[31:28]||imm26||00 00011:reg_data
output [2:0] D_GRF_A1_Sel当前D级指令GRF_A1数据来源选择信号 000:D_rs
output [2:0] D_GRF_A2_Sel当前D级指令GRF_A2数据来源选择信号 000:D_rt
output [2:0] D_GRF_A3_Sel当前D级指令GRF_A3数据来源信号(本来应该在W级输出,但是由于转发需求) 000:D_rt 001:D_rd 010:31(jal)
output [2:0] D_CMP_A_Sel当前D级指令CMP_A数据来源选择信号 000:D_TR_GRF_RD1
output [2:0] D_CMP_B_Sel当前D级指令CMP_B数据来源选择信号 000:D_TR_GRF_RD2
output [2:0] D_TR_GRF_RD1_Sel转发数据来源选择信号
output [2:0] D_TR_GRF_RD2_Sel转发数据来源选择信号
output [1:0] D_Tuse_GRF_A1当前D级指令的GRF_A1的Tuse信号
output [1:0] D_Tuse_GRF_A2当前D级指令的GRF_A2的Tuse信号
output D_NPC_PC_Sel当前D级NPC的PC输入选择信号 确定要跳转的指令为1(D_PC);顺序执行的指令为0(F_PC)
output [5:0] D_order当前D级指令的6位编号

2.2.2 DREG

  • D级寄存器

  • 保存当前D级指令(正在取操作数的指令)的信息

端口名端口输入/输出信号名描述
input clkclk时钟信号
input resetreset同步复位信号,清空寄存器
input DREG_en~Stall用于暂停操作
input [31:0] F_IM_instrF_IM_instr当前F级32位指令,在时钟上升沿写入DREG
input [31:0] F_PCF_PC当前F级指令的PC,在时钟上升沿写入DREG
output [31:0] D_IM_instrD_IM_instr当前D级32位指令
output [31:0] D_PCD_PC当前D级指令的PC

2.2.3 GRF(支持内部转发)

  • 端口定义

信号名描述
input clk时钟信号
input reset同步复位信号
input [4:0] D_GRF_A1D级指令的5位地址输入信号,指定32个寄存器中的一个,将其中的数据输出到RD1
input [4:0] D_GRF_A2D级指令的5位地址输入信号,指定32个寄存器中的一个,将其中的数据输出到RD2
input [31:0] W_PC当前W级指令所在的IM地址
input [4:0] W_GRF_A3W级指令的5位地址输入信号,指定32个寄存器中的一个作为写入目标寄存器
input [31:0] W_GRF_WDW级指令的32位写入数据
input W_RegWriteW级指令的GRF写使能信号
output reg [31:0] D_GRF_RD1D级指令输出A1指定寄存器的32位数据
output reg [31:0] D_GRF_RD2D级指令输出A2指定寄存器的32位数据
  • 功能定义

功能描述
读出数据组合逻辑:读出D级指令D_GRF_A1和D_GRF_A3地址所对应的寄存器的值通过D_GRF_RD1和D_GRF_RD2读出。支持内部转发:将W级即将在下一个时钟周期写入的数据读出。(数据转发)
写入数据时序逻辑:当W_RegWrite为1且时钟上升沿来临时,将W级指令的W_GRF_WD写入W_GRF_A3(非0)所对应的寄存器中。0号寄存器的值始终为0。
同步复位当reset为1且时钟上升沿来临时,将所有寄存器的值清零。

2.2.4 EXT

  • EXT功能是位扩展,将16位立即数扩展为32位立即数。

信号名描述
input [15:0] D_EXT_imm16D级指令的16位立即数输入
input [4:0] D_EXTopEXT功能选择信号
output reg [31:0] D_EXT_imm32D级指令的32位扩展后的立即数输出
  • EXT功能选择信号表

D_EXTop编码对应运算
5'd0(00000)符号扩展
5'd1(00001)零扩展
5'd2(00010)加载至最高位,低位补0
5'd3(00011)新扩展功能

2.2.5 mux_D_TR_GRF_RD1

  • GRF_RD1数据转发选择器

  • EREG,MREG

  • 没有WREG(WREG采用GRF内部转发)

模块端口名端口对应信号名对输入信号的描述
input [31:0] in_032'd0摆烂
input [31:0] in_1D_GRF_RD1当前D级的GRF_RD1(待更新)
input [31:0] in_2M_TR_data当前M级的转发数据(可能不存在)
input [31:0] in_3W_TR_data当前W级的转发数据(可能不存在)
input SelD_TR_GRF_RD1_Sel转发需求者数据选择信号
output [31:0] YD_TR_GRF_RD1新的转发需求者数据D

2.2.6 mux_D_TR_GRF_RD2

  • GRF_RD2数据转发选择器

模块端口名端口对应信号名对输入信号的描述
input [31:0] in_032'd0摆烂
input [31:0] in_1D_GRF_RD2
input [31:0] in_2M_TR_data
input [31:0] in_3W_TR_data
input SelD_TR_GRF_RD2_Sel
output [31:0] YD_TR_GRF_RD2

2.2.7 mux_CMP_A

  • D_CMP_A的数据来源选择器

模块端口名端口对应信号名描述
input [31:0] in_0D_TR_GRF_RD1
input [2:0] SelD_CMP_A_Sel
output [31:0] YD_CMP_A

2.2.8 mux_CMP_B

  • D_CMP_B的数据来源选择器

模块端口名端口对应信号名描述
input [31:0] in_0D_TR_GRF_RD2
input [31:0] in_1D_EXT_imm32
input [2:0] SelD_CMP_B_Sel
output [31:0] YD_CMP_B

2.2.9 CMP

  • CMP的功能是输出条件比较的结果,可用于NPC跳转控制信号。

信号名描述
input [31:0] D_CMP_AD级指令的32位比较数A的输入
input [31:0] D_CMP_BD级指令的32位比较数B的输入
input [4:0] D_CMPopD级功能选择信号
output [31:0] D_cmp_signD级指令的比较结果输出
  • CMP功能选择信号表

D_CMPop编码编码对应运算
5'd0(00000)D_CMP_A==D_CMP_B(BEQ)
5'd1(00001)D_CMP_A!=D_CMP_B(BNE)
5'd2(00010)D_CMP_A<=0(BLEZ)
5'd3(00011)D_CMP_A>0(BGTZ)
5'd4(00100)D_CMP_A<0(BLTZ)
5'd5(00101)D_CMP_A>=0(BGEZ)
5'd6(00110)D_CMP_A<D_CMP_B(SLT,SLTI) 有符号比较
5'd7(00111)D_CMP_A<D_CMP_B(SLTU,SLTIU)无符号比较
5'd8(01000)新比较运算

2.2.10 mux_D_NPC_PC

模块端口名端口对应信号名描述
input [31:0] F_PCF_PC
input [31:0] D_PCD_PC
input SelD_NPC_PC_Sel 0:顺序执行 1:需要跳转(J指令,D_cmp_sign==1的B指令)
output [31:0] D_NPC_PCD级NPC模块的32位D_NPC_PC输入

2.2.11 NPC

  • NPC的作用是计算转移指令的下一条指令的地址,当前转移指令(b类或j类)在D级

信号名描述
input [31:0] D_NPC_PCNPC输入 确定跳转的指令为D_PC 不跳转的指令为F_PC
input [15:0] D_imm16当前D级指令的16位立即数
input [25:0] D_imm26当前D级指令的26位立即数
input [31:0] D_reg_data当前D级指令跳转寄存器地址的寄存器数据
input [4:0] D_NPCop当前D级指令NPC控制信号
output reg [31:0] D_NextPC当前D级指令的下一条指令地址

2.2.12 mux_D_cmp_data

模块端口名端口对应信号名描述
input [31:0] in_032'd0
input [31:0] in_132'd1
input SelD_cmp_sign
output [31:0] YD_cmp_data

2.3 E级

2.3.1 EREG

模块端口名端口对应信号名对输入信号的描述
input clkclk
input resetreset|Stall
input [31:0] D_IM_instrD_IM_instr
input [4:0] D_GRF_A1D_GRF_A1
input [4:0] D_GRF_A2D_GRF_A2
input [31:0] D_GRF_RD1D_TR_GRF_RD1
input [31:0] D_GRF_RD2D_TR_GRF_RD2
input [4:0] D_GRF_A3D_GRF_A3
input [31:0] D_EXT_imm32D_EXT_imm32
input D_cmp_signD_cmp_sign
input [31:0] D_cmp_dataD_cmp_data
input [31:0] D_PCD_PC
output reg [31:0] E_IM_instrE_IM_instr
output reg [4:0] E_GRF_A1E_GRF_A1
output reg [4:0] E_GRF_A2E_GRF_A2
output reg [31:0] E_GRF_RD1E_TR_GRF_RD1
output reg [31:0] E_GRF_RD2E_TR_GRF_RD2
output reg [4:0] E_GRF_A3E_GRF_A3
output reg [31:0] E_EXT_imm32E_EXT_imm32
output reg E_cmp_signE_cmp_sign
output reg [31:0] E_cmp_dataE_cmp_data
output reg [31:0] E_PCE_PC

2.3.2 ECTRL

信号名描述
input [5:0] E_op
input [4:0] E_rt
input [5:0] E_func
input [4:0] E_GRF_A1
input [4:0] E_GRF_A2
input [4:0] M_GRF_A3
input [4:0] W_GRF_A3
input [5:0] M_order
input [5:0] W_order
output reg [4:0] E_ALUop
output reg [4:0] E_MDUop
output [2:0] E_ALU_A_Sel
output reg [2:0] E_ALU_B_Sel
output [2:0] E_ALU_S_Sel
output [2:0] E_MDU_A_Sel
output [2:0] E_MDU_B_Sel
output [2:0] E_TR_GRF_RD1_Sel
output [2:0] E_TR_GRF_RD2_Sel
output [2:0] E_TR_data_Sel
output [1:0] E_Tnew
output [5:0] E_order

2.3.3 ALU

  • 端口定义

信号名描述
input [31:0] E_ALU_A
input [31:0] E_ALU_B
input [4:0] E_ALU_S
input [4:0] E_ALUop
output reg [31:0] E_ALU_C
  • ALU功能选择信号表

E_ALUop编码编码对应运算
5'd0(00000)E_ALU_A&E_ALU_B
5'd1(00001)E_ALU_A|E_ALU_B
5'd2(00010)E_ALU_A+E_ALU_B(无符号加)
5'd3(00011)符号加
5'd4(00100)E_ALU_A-E_ALU_B(无符号减)
5'd5(00101)符号减
5'd6(00110)E_ALU_A 或非 E_ALU_B
5'd7(00111)逻辑左移
5'd8(01000)算术右移
5'd9(01001)逻辑右移
5'd10(01010)E_ALU_A 异或 E_ALU_B
5'd11(01011)E_ALU_B
5'd12(01100)新运算

2.3.4 MDU

  • 端口定义

信号名描述
input clk时钟信号
input reset同步复位信号
input [31:0] E_MDU_A乘除模块输入的第一个32位运算数
input [31:0] E_MDU_B乘除模块输入的第二个32位运算数
input [4:0] E_MDUop乘除模块功能选择信号
output E_MDU_busyE_MDU_busy为1时说明乘除模块在工作
output reg [31:0] E_MDU_out乘除模块的32位输出
  • 乘除模块功能选择信号

M_MDUop编码编码对应运算指令
5'd0(00000)对MDU没有操作其他不涉及MDU的指令
5'd1(00001)MULT
5'd2(00010)乘(无符号)MULTU
5'd3(00011)DIV
5'd4(00100)除(无符号)DIVU
5'd5(00101)读HIMFHI
5'd6(00110)读LOMFLO
5'd7(00111)写HIMTHI
5'd8(01000)写LOMTLO
5'd9(01001)新操作

2.3.5 mux_E_TR_GRF_RD1

  • GRF_RD1数据转发选择器

模块端口名端口对应信号名对输入信号的描述
input [31:0] in_032'd0
input [31:0] in_1E_GRF_RD1
input [31:0] in_2M_TR_data
input [31:0] in_3W_TR_data
input SelE_TR_GRF_RD1_Sel
output [31:0] YE_TR_GRF_RD1

2.3.6 mux_E_TR_GRF_RD2

  • GRF_RD2数据转发选择器

模块端口名端口对应信号名对输入信号的描述
input [31:0] in_032'd0
input [31:0] in_1E_GRF_RD2
input [31:0] in_2M_TR_data
input [31:0] in_3W_TR_data
input [2:0] SelE_TR_GRF_RD2_Sel
output [31:0] YE_TR_GRF_RD2

2.3.7 mux_E_TR_data

模块端口名端口对应信号名对输入信号的描述
input [31:0] in_0E_PC+8
input [31:0] in_1E_cmp_data
input [2:0] SelE_TR_data_Sel
output [31:0] YE_TR_data

2.4 M级

2.4.1 MREG

模块端口端口对应信号名对信号的描述
input clkclk
input resetreset
input [31:0] E_IM_instrE_IM_instr
input [31:0] E_PCE_PC
input [4:0] E_GRF_A2E_GRF_A2
input [31:0] E_GRF_RD2E_TR_GRF_RD2
input [4:0] E_GRF_A3E_GRF_A3
input [31:0] E_ALU_CE_ALU_C
input [31:0] E_MDU_outE_MDU_out
input E_cmp_signE_cmp_sign
input [31:0] E_cmp_dataE_cmp_data
output [31:0] M_IM_instrM_IM_instr
output [31:0] M_PCM_PC
output [4:0] M_GRF_A2M_GRF_A2
output [31:0] M_GRF_RD2M_GRF_RD2
output [4:0] M_GRF_A3M_GRF_A3
output [31:0] M_ALU_CM_ALU_C
output [31:0] M_MDU_outM_MDU_out
output M_cmp_signM_cmp_sign
output [31:0] M_cmp_dataM_cmp_data

2.4.2 MCTRL

信号名描述
input [5:0] M_op
input [4:0] M_rt
input [5:0] M_func
input [4:0] M_GRF_A2
input [4:0] W_GRF_A3
input [5:0] W_order
output [3:0] m_data_byteen当前M级指令DM写使能
output [2:0] M_DMEXTop
output [2:0] M_DM_A_Sel
output [2:0] M_DM_data_Sel
output [2:0] M_TR_GRF_RD2_Sel
output [2:0] M_TR_data_Sel
output [1:0] M_Tnew
output [5:0] M_order

2.4.3 DMEXT

  • 数据扩展模块

信号名描述
input [31:0] M_DM_A从外置DM中取的数据所在字的地址,DMEXT模块只取最后两位
input [31:0] m_data_rdata从外置DM中取出来的32位待处理数据
input [2:0] M_DMEXTop数据扩展模块功能选择
output [31:0] M_DM_out数据扩展后的32位数数据
  • 数据扩展模块功能选择信号表

M_DMEXTop编码编码对应功能
3'd0(000)无扩展
3'd1(001)无符号字节扩展
3'd2(010)符号字节扩展
3'd3(011)无符号半字扩展
3'd4(100)符号半字扩展
3'd5(101)新扩展

2.4.4 mux_M_TR_GRF_RD2

  • GRF_RD2数据转发选择器

模块端口名端口对应信号名对输入信号的描述
input [31:0] in_032'd0
input [31:0] in_1M_GRF_RD2
input [31:0] in_2W_TR_data
input [2:0] SelM_TR_GRF_RD2_Sel
output [31:0] YM_TR_GRF_RD2

2.4.5 mux_M_TR_data

模块端口名端口对应信号名对输入信号的描述
input [31:0] in_0M_ALU_C
input [31:0] in_1M_PC+8
input [31:0] in_2M_MDU_out
input [31:0] in_3M_cmp_data
input [2:0] SelM_TR_data_Sel
output [31:0] YM_TR_data

2.5 W级

2.5.1 WREG

模块端口端口对应信号吗对输入信号的描述
input clk
input reset
input [31:0] M_IM_instr
input [31:0] M_ALU_C
input [31:0] M_MDU_out
input [31:0] M_DM_out
input [4:0] M_GRF_A3
input M_cmp_sign
input [31:0] M_cmp_data
input [31:0] M_PC
output [31:0] W_IM_instr
output [31:0] W_ALU_C
output [31:0] W_MDU_out
output [31:0] W_DM_out
output [4:0] M_GRF_A3
output W_cmp_sign
output [31:0] W_cmp_data
output [31:0] W_PC

2.5.2 WCTRL

信号名描述
input [5:0] W_op
input [4:0] W_rt
input [5:0] W_func
output reg W_RegWrite
output reg [2:0] W_GRF_WD_Sel
output [1:0] W_Tnew
output [5:0] W_order

2.5.3 mux_W_GRF_WD

模块端口名端口对应信号名对输入信号的描述
input [31:0] in_0W_ALU_C
input [31:0] in_1W_DM_out
input [31:0] in_2W_PC+8
input [31:0] in_3W_MDU_out
input [31:0] in_4W_cmp_data
input [2:0] SelW_GRF_WD_Sel
output [31:0] YW_GRF_WD

2.5.4 mux_W_TR_data

  • 和mux_W_GRF_WD一致

  • assign W_TR_data=W_GRF_WD;

3 暂停控制器设计

Stall_CTRL

信号名描述
input [1:0] D_Tuse_GRF_A1
input [1:0] D_Tuse_GRF_A1
input [1:0] E_Tnew
input [1:0] M_Tnew
input [1:0] W_Tnew
input [5:0] D_order
input [4:0] D_GRF_A1
input [4:0] D_GRF_A2
input [4:0] E_GRF_A3
input [4:0] M_GRF_A3
input [4:0] W_GRF_A3
input E_MDU_busy
output Stall

4 控制信号详解

4.1 功能选择控制信号表

指令名编号D_EXTopD_CMPopD_NPCopE_ALUopE_MDUopM_DMEXTop
LB00-02-2
LBU10-02-1
LH20-02-4
LHU30-02-3
LW40-02-0
SB50-02--
SH60-02--
SW70-02--
ADD8--03--
ADDU9--02--
SUB10--05--
SUBU11--04--
MULT12--0-1-
MULTU13--0-2-
DIV14--0-3-
DIVU15--0-4-
SLL16--07--
SRL17--09 逻辑右移--
SRA18--08 算术右移--
SLLV19--07--
SRLV20--09 逻辑可变右移--
SRAV21--08 算术可变右移--
AND22--00--
OR23--01--
XOR24--010--
NOR25--06--
ADDI260-03--
ADDIU270-02--
ANDI281-00--
ORI291-01--
XORI301-010--
LUI312-011--
SLT32-60---
SLTI33060---
SLTIU34070---
SLTU35-70---
BEQ36-0(D_cmp_sign==1) 1---
BNE37-1(D_cmp_sign==1) 1---
BLEZ38-2(D_cmp_sign==1) 1---
BGTZ39-3(D_cmp_sign==1) 1---
BLTZ40-4(D_cmp_sign==1) 1---
BGEZ41-5(D_cmp_sign==1) 1---
J42--2---
JAL43--2---
JALR44--3---
JR45--3---
MFHI46--0-5-
MFLO47--0-6-
MTHI48--0-7-
MTLO49--0-8-

4.2 数据来源选择控制信号表

指令名编号D_GRF_A1_SelD_GRF_A2_SelD_GRF_A3_SelD_CMP_A_SelD_CMP_B_SelD_NPC_PC_Sel
LB00-0--0
LBU10-0--0
LH20-0--0
LHU30-0--0
LW40-0--0
SB500---0
SH600---0
SW700---0
ADD8001--0
ADDU9001--0
SUB10001--0
SUBU11001--0
MULT1200---0
MULTU1300---0
DIV1400---0
DIVU1500---0
SLL16-01--0
SRL17-01--0
SRA18-01--0
SLLV19-01--0
SRLV20-01--0
SRAV21-01--0
AND22001--0
OR23001--0
XOR24001--0
NOR25001--0
ADDI260-0--0
ADDIU270-0--0
ANDI280-0--0
ORI290-0--0
XORI300-0--0
LUI31--0--0
SLT32001000
SLTI330-0010
SLTIU340-0010
SLTU35001000
BEQ3600-00(D_cmp_sign==1) 1
BNE3700-00(D_cmp_sign==1) 1
BLEZ380--0-(D_cmp_sign==1) 1
BGTZ390--0-(D_cmp_sign==1) 1
BLTZ400--0-(D_cmp_sign==1) 1
BGEZ410--0-(D_cmp_sign==1) 1
J42-----1
JAL43--2--1
JALR440-1--1
JR450----1
MFHI46--1--0
MFLO47--1--0
MTHI480----0
MTLO490----0
指令名编号E_ALU_A_SelE_ALU_B_SelE_ALU_S_SelE_MDU_A_SelE_MDU_B_Sel
LB001---
LBU101---
LH201---
LHU301---
LW401---
SB501---
SH601---
SW701---
ADD800---
ADDU900---
SUB1000---
SUBU1100---
MULT12---00
MULTU13---00
DIV14---00
DIVU15---00
SLL16-00--
SRL17-00--
SRA18-00--
SLLV19-01--
SRLV20-01--
SRAV21-01--
AND2200---
OR2300---
XOR2400---
NOR2500---
ADDI2601---
ADDIU2701---
ANDI2801---
ORI2901---
XORI3001---
LUI31-1---
SLT32-----
SLTI33-----
SLTIU34-----
SLTU35-----
BEQ36-----
BNE37-----
BLEZ38-----
BGTZ39-----
BLTZ40-----
BGEZ41-----
J42-----
JAL43-----
JALR44-----
JR45-----
MFHI46-----
MFLO47-----
MTHI48---0-
MTLO49---0-
指令名编号M_DM_A_SelM_DM_data_SelW_GRF_WD_Sel
LB00-1 W_DM_out
LBU10-1 W_DM_out
LH20-1 W_DM_out
LHU30-1 W_DM_out
LW40-1 W_DM_out
SB500-
SH600-
SW700-
ADD8--0 W_ALU_C
ADDU9--0 W_ALU_C
SUB10--0 W_ALU_C
SUBU11--0 W_ALU_C
MULT12---
MULTU13---
DIV14---
DIVU15---
SLL16--W_ALU_C
SRL17--W_ALU_C
SRA18--W_ALU_C
SLLV19--W_ALU_C
SRLV20--W_ALU_C
SRAV21--W_ALU_C
AND22--W_ALU_C
OR23--W_ALU_C
XOR24--W_ALU_C
NOR25--W_ALU_C
ADDI26--W_ALU_C
ADDIU27--W_ALU_C
ANDI28--W_ALU_C
ORI29--W_ALU_C
XORI30--W_ALU_C
LUI31--W_ALU_C
SLT32--4 W_cmp_data
SLTI33--4 W_cmp_data
SLTIU34--4 W_cmp_data
SLTU35--4 W_cmp_data
BEQ36---
BNE37---
BLEZ38---
BGTZ39---
BLTZ40---
BGEZ41---
J42---
JAL43--W_PC+8
JALR44--W_PC+8
JR45---
MFHI46--W_MDU_out
MFLO47--W_MDU_out
MTHI48---
MTLO49---

4.3 写使能信号

指令名编号m_data_byteenW_RegWrite
LB000001
LBU100001
LH200001
LHU300001
LW400001
SB500010
SH600110
SW711110
ADD800001
ADDU900001
SUB1000001
SUBU1100001
MULT1200000
MULTU1300000
DIV1400000
DIVU1500000
SLL1600001
SRL1700001
SRA1800001
SLLV1900001
SRLV2000001
SRAV2100001
AND2200001
OR2300001
XOR2400001
NOR2500001
ADDI2600001
ADDIU2700001
ANDI2800001
ORI2900001
XORI3000001
LUI3100001
SLT3200001
SLTI3300001
SLTIU3400001
SLTU3500001
BEQ3600000
BNE3700000
BLEZ3800000
BGTZ3900000
BLTZ4000000
BGEZ4100000
J4200000
JAL4300001
JALR4400001
JR4500000
MFHI4600001
MFLO4700001
MTHI4800000
MTLO4900000

5 课上指令分类

5.1 计算类指令

  • 侧重点在E级的MDU和ALU的新运算算法

  • MDU指令需要修改Stall_CTRL,将新指令标签添加到Stall_MDU中。(一般不用考虑Tnew)

5.2 条件跳转类指令

  • 侧重点在D级的CMP的新比较算法

  • 一般为两种指令的结合。比如blezals就是B类跳转指令和jal的结合体。

  • 可能会考到清空延迟槽操作。如果D_cmp_sign==0且Stall==0的时候,产生一个DREG_clr信号,清空DREG。DREG_clr信号的优先级是低于Stall暂停信号的。

5.3 条件存储类指令

  • 因为回写的寄存器地址直到M级才确定,所以一般比较难,需要修改Stall_CTRL模块。

6 如何添加一条新指令

6.1 添加指令基本信息

  • 将新指令编号为6'd50,并将其添加到macro_Decode.v模块中

  • 在Decode_CTRL中根据op,func可能还有rt位将新指令加入到else if语句中

6.2 添加指令的Tuse和Tnew

  • 根据是否需要用到rs和rt来确定D_Tuse_GRF_A1和D_Tuse_GRF_A2,以及什么时候寄存器中保存了回写数据确定E_Tnew,M_Tnew和W_Tnew。填上面的Tuse和Tnew的表格。

  • 将D_Tuse_GRF_A1和D_Tuse_GRF_A2加入到DCTRL中,将E_Tnew加入到ECTRL,M_Tnew加入到MCTRL,W_Tnew加入到WCTRL中。

6.3 填写指令步骤表

 

注意:记得先修改模块!!!添加模块新功能!!!

6.4 按需修改所有转发(同一修改关于转发的数据通路和控制信号)

思考转发有两个很重要的角度:供给者和需求者

6.4.1 供给者

供给者角度问两个很重要的问题:

  • 该指令是否需要回写?

    如果不需要,直接跳过供给者修改部分。

  • 如果需要回写的话,是否产生了新的回写GRF的数据? 就是除了cmp_data,ALU_C,PC+8,DM_out之外的新数据

    • 如果没有产生新数据,判断该指令回写数据属于哪个类别,将它的指令标签添加到两个地方。

      • 根据在最先保存在哪一级REG中修改TR_data_Sel控制信号(供给者)只需添加新指令标签

        • 最早保存在EREG里的回写数据(如cmp_data,PC+8),修改E_TR_data_Sel,M_TR_data_Sel以及W_TR_data_Sel

        • 最先保存在MREG里的回写数据(如ALU_C,MDU_out),修改M_TR_data_Sel,W_TR_data_Sel

        • 最先保存在WREG里的回写数据(如DM_out),修改W_GRF_WD_Sel即可

      • 根据在哪级最先保存回写数据,修改所有前级的TR_GRF_RD1_Sel和TR_GRF_RD2_Sel控制信号,添加新指令的标签啦

    • 如果产生了新数据,可能稍稍有点麻烦了。首先要判断新数据最先出现在哪个流水级寄存器中,然后在mips顶层中的该级及该级之后的所有级mux_TR_data数据选择器中增加新的端口,并添加相应的控制信号。

      • 最先保存回写数据的流水级前面所有的TR_GRF_RD1_Sel和TR_GRF_RD2_Sel都要进行修改(将新指令标签添加到所有保存该指令回写数据的if-else语句中即可)

      • 如果是最先保存在WREG中,D级采用内部转发

      • 要注意该新回写数据的优先级(在写控制信号的时候)

6.4.2 需求者

需求者需要考虑的问题:

  • 该指令是否有新的使用寄存器值的地方?

    如果没有,那就直接跳过。

  • 如果有的话,添加新的转发mux,(mips中加mux以及控制器中添加控制信号)。

6.4.3 需要考虑的控制信号

  • D_TR_GRF_RD1_Sel

  • D_TR_GRF_RD2_Sel

  • E_TR_GRF_RD1_Sel

  • E_TR_GRF_RD2_Sel

  • M_TR_GRF_RD2_Sel

  • E_TR_data_Sel

  • M_TR_data_Sel

  • W_TR_data_Sel

6.5 暂停修改

如果是MDU计算类指令(P6一般都是),要修改Stall_CTRL模块,将新指令标签添加到Stall_MDU中

暂停需要先问一个问题:该指令的回写寄存器编号GRF_A3在D级是否可以确定。如果可以确定,那么就不需要做其他修改了。

如果是存储类指令:

  • 在M级确定GRF_A3,并且在W级保存正确的GRF_A3时,先让D_GRF_A3,E_GRF_A3,M_GRF_A3=5'd0。

有两种不确定可能分别为:GRF_A3二选一模式和GRF_A3完全不确定模式

6.5.1 二选一模式

  • 将D_GRF_A3_Sel=3,选择0号寄存器。

  • 将它的两个可能的寄存器值都进入流水线,设为D_GRF_A3_X1,D_GRF_A3_X2,E_GRF_A3_X1,E_GRF_A3,X2,M_GRF_A3_X1,M_GRF_A3_X2,在M级确定真正的M_GRF_A3_new,将其输入在WREG的M_GRF_A3口

  • 将E_GRF_A3_X1,E_GRF_A3_X2,M_GRF_A3_X1,M_GRF_A3_X2,E_order,M_order传入Stall_CTRL控制器。添加判断。主要是添加E和M的判断,W不用管。

    • 别忘了把新的暂停信号和总的暂停信号|起来

6.5.2 不确定模式

  • 将D_GRF_A3_Sel=3,选择0号寄存器

  • 将E_order和M_order传入Stall_CTRL控制器。添加判断。主要是添加E和M的判断。

  • 在M级直接给M_GRF_A3赋值

7 思考题

7.1 为什么需要有单独的乘除法部件而不是整合进 ALU?为何需要有独立的 HI、LO 寄存器?

  • 因为乘除法的运算速率明显低于其他运算,需要多个时钟周期,为了不干扰其他运算指令的进行,因此将乘除法分离出ALU,自成一个部件。独立的HI、LO寄存器可以保存乘除法运算的值,如果不保存,要等运算完把值存入相应的寄存器,最坏情况会暂停11个周期,这大大降低了流水线CPU的性能,不是我们想要的。

7.2 参照你对延迟槽的理解,试解释 “乘除槽”。

  • 乘除槽就是因乘除法运算的大量时间导致出的结果延后性,即想要这个结果需要等待一定长的时间,这个时间我们自然是不想要浪费的,可以用于运行其他不需要用到乘除器的指令,以保证流水线CPU的性能。

7.3 举例说明并分析何时按字节访问内存相对于按字访问内存性能上更有优势。(Hint: 考虑 C 语言中字符串的情况)

  • 当遇到sb,sh等指令,按字节访存比按字访存更好,如果按字访存,则需要将整个字取出后再进行更改,可能会引起电路震荡,如果按字节访存,则直接对字节进行修改,不用再取出修改了。

7.4 在本实验中你遇到了哪些不同指令类型组合产生的冲突?你又是如何解决的?相应的测试样例是什么样的?

  • 指令冲突跟P5差不多,都是计算型指令,jr,beq,load、store的互相冲突,新增的sw,sb,sh可以概括为store类指令,lb,lbu,lhu,lh概括为load指令,jr,jalr指令为一类,beq,bgez,bne,blez…为一类branch指令,其他除乘除法的计算型指令的Tuse,Tnew几乎一样。而mflo、mfhi、mthi、mtlo与乘除器的冲突都用暂停解决。同样,转发机制与P5就基本一样,因为除乘除法指令外,所有冒险冲突解决机制都搭建好了,只需更改级控制器中的Tuse和Tnew信号。

我要做的测试样例就是测试指令功能的正确性,冒险冲突的解决检验只需要将同类型指令更换。

8 可能会出现的bug

  • 写Tuse的时候要记得同时分别考虑rs(A1)和rt(A2)的使用情况,不要遗漏。

  • 当只有一种情况的时候,直接使用assign语句,千万不要使用always@(*)块

    • 直接assign M_DMop=5'd0;

  • 区分output和output reg

    • output对应assign语句赋值的变量

    • output reg对应always @(*)块赋值的变量

    • 如果将assign改为always@(*)块,记得将output改为output reg

  • 记得所有if_else语句最后要加else begin_end,避免产生锁存器

  • 信号优先级:顶层reset>stall>延迟操清零

    • 清空延迟槽的优先级在Stall后面

  • reg型变量计数器是否清零

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值