P7流水线CPU设计文档

设计整体概述

  1. 预计实现指令集
    add、sub、and、or、nor、xor、slt、sltu、
    ori、Lui、addi、andi、
    lw、lh、lhu、lb、lbu、sw、sh、sb、
    mult、multu、div、divu、mfhi、mflo、mthi、mtlo、
    beq、bne、nop、j、jr、jal、jalr、
    mfc0、mtc0、eret、syscall
    实际MIPS微系统支持指令与课下要求实现一致。
  • R型指令:add、sub、and、or、nor、xor、slt、sltu、
opcode rs rt rd shamt funct
6 5 5 5 5 6
  • I型指令:lui、ori、andi、addi、lw、lh、lhu、lb、lbu、sw、sh、sb、beq、bne、
    | opcode | rs | rt | offset |
    | :----: | :—: | :—: | :----: |
    | 6 | 5 | 5 | 16 |

  • J型指令:j、jal
    | opcode | instr_index |
    | :----: | :---------: |
    | 6 | 26 |

  • 乘除器操作指令:mult、multu、div、divu、mfhi、mflo、mthi、mtlo

  • CP0指令:mfc0、mtc0

其中,nop指令为空指令,不执行任何操作,add、sub不考虑溢出,故实际执行addu和subu

  1. 实现功能:实现MIPS微系统,内含五级流水线CPU、系统桥以及计时器,能够识别外部中断和内部异常并执行异常处理程序。CPU通过F、D、E、M、W五个阶段实现指令的执行,其中F阶段为取指,D阶段为译码,E阶段为执行,M阶段为访存,W阶段为写回,各阶段均通过流水线寄存器实现流水线操作,通过转发和阻塞机制解决冒险问题。系统桥根据地址范围将数据分发到内存的不同部分,计时器通过状态机实现计时功能。(课程组已给出)

  2. 顶层设计图
    整体架构符合课程组要求
    main

  3. CPU封装为单周期,CP0置于M级,IM与DM实现外置,通过系统桥连接到外部输入输出端口。

  4. 命名格式:模块命名采用所在级_模块名方式,模块内部信号名采取来源_功能方式命名,顶层信号采用所在级_模块名_信号名方式命名。

数据通路模块设计

为实现MIPS微系统功能,需要将CPU封装,满足中断需求,设计较P6有更多改动,以下为顶层端口定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module mips(
input wire clk, // 时钟信号
input wire reset, // 同步复位信号
input wire interrupt, // 外部中断信号
output wire [31:0] macroscopic_pc, // 宏观 PC

output wire [31:0] i_inst_addr, // IM 读取地址(取指 PC)
input wire [31:0] i_inst_rdata, // IM 读取数据

output wire [31:0] m_data_addr, // DM 读写地址
input wire [31:0] m_data_rdata, // DM 读取数据
output wire [31:0] m_data_wdata, // DM 待写入数据
output wire [3 :0] m_data_byteen, // DM 字节使能信号

output wire [31:0] m_int_addr, // 中断发生器待写入地址
output wire [3 :0] m_int_byteen, // 中断发生器字节使能信号

output wire [31:0] m_inst_addr, // M 级 PC

output wire w_grf_we, // GRF 写使能信号
output wire [4 :0] w_grf_addr, // GRF 待写入寄存器编号
output wire [31:0] w_grf_wdata, // GRF 待写入数据

output wire [31:0] w_inst_addr // W 级 PC
);
//

endmodule;

CPU设计

加入了异常中断处理模块CP0,同时添加了宏观PC端口,用于对封装为单周期的CPU进行判断。

  • 定义:将所有CPU内部模块连接起来,实现整个CPU的功能。

  • 端口定义

    信号名 方向 位宽 说明
    clk I 1 时钟信号
    reset I 1 复位信号
    HWInt I 6 硬件中断信号
    i_inst_rdata I 32 指令存储器读取数据
    m_data_rdata I 32 数据存储器读取数据
    i_inst_addr O 32 指令存储器读取地址
    m_data_addr O 32 数据存储器读写地址
    m_data_wdata O 32 数据存储器待写入数据
    m_data_byteen O 4 数据存储器字节使能信号
    m_inst_addr O 32 M级PC
    w_grf_we O 1 GRF写使能信号
    w_grf_addr O 5 GRF待写入寄存器编号
    w_grf_wdata O 32 GRF待写入数据
    w_inst_addr O 32 W级PC
    macroscopic_pc O 32 宏观PC
    Req O 1 异常请求信号
  • 功能实现:实例化所有模块,定义各模块间的连接,在顶层模块中用?:实现多路选择器。

    • Fetch阶段:实例化F_IFU模块,生成PC和指令地址,生成对应异常码。
    • Decode阶段:实例化D_REGMCUD_NPCD_EXTD_CMPGRF模块,进行指令译码和寄存器读写,生成对应异常码。
    • Execute阶段:实例化E_REGMCUE_ALUE_MDU模块,进行算术逻辑运算和乘除运算,生成对应异常码。
    • Memory阶段:实例化M_REGMCUM_BEM_DECP0模块,进行数据存储和异常处理。
    • Write Back阶段:实例化W_REGMCU模块,进行数据写回。
    • Hazards Control:实例化HCU模块,生成转发和停顿信号。

F级:取指Fetch

F_IFU 指令单元

  1. 定义:模块内部包含PC程序计数器、IM指令存储器以在外部实现,因此只负责根据NPC传入的PC值,依照控制信号选择PC值。
  2. 端口定义
信号名 方向 位宽 说明
Next_PC I 32 NPC模块输出的下一条指令地址
EPC I 32 异常返回地址
D_isEret I 1 异常返回指令信号
D_NPCSel I 3 下一条指令PC选择信号
clk I 1 时钟信号
reset I 1 复位信号
Req I 1 异常中断信号
stop I 1 停机信号
F_PC O 32 当前指令地址
F_PC8 O 32 当前指令地址+8
F_BDIn O 1 分支延迟槽信号
IFU_ExcCode O 5 指令异常码
  1. 实现功能
序号 功能 描述
1 同步复位 reset信号为1且处于时钟上升沿时,PC置0x00003000
2 停机 stop信号为1时,PC和指令保持不变
3 取指 stop信号为0时,在clk上升沿得到的下一条指令地址PC,传入顶层模块到i_inst_addr读取指令
4 异常 Req信号为1时,将D_NPC生成的异常处理指令地址0x00004180赋值给PC,同时将异常码传入顶层模块
5 异常返回 D_isEret信号为1时,将EPC赋值给PC
6 输出异常 当PC未字对齐或PC越界时,将异常码传入顶层模块

PC初始化为0x00003000

外接IM具体实现

1
2
assign i_inst_addr = F_PC;
assign F_Instr = i_inst_rdata;

D级:译码decode

D_REG D级流水线寄存器

  1. 定义:用于在时钟上升沿将F级的指令和PC值传递到D级,并根据复位信号重置寄存器值,根据Req信号清空寄存器值,到并在停机信号为1时保持不变
  2. 端口定义
信号名 方向 位宽 说明
clk I 1 时钟信号
reset I 1 复位信号
stall I 1 停机信号
Req I 1 异常请求信号
F_Instr I 32 F级的32位指令
F_PC I 32 F级的PC值
F_PC8 I 32 F级的PC+8值
F_BDIn I 1 F级的分支延迟槽信号
F_ExcCode I 5 F级的异常码
D_Instr O 32 D级的32位指令
D_PC O 32 D级的PC值
D_PC8 O 32 D级的PC+8值
D_BDIn O 1 D级的分支延迟槽信号
D_ExcCode O 5 传入D级的异常码
  1. 实现功能
序号 功能 描述
1 同步复位 reset信号为1且处于时钟上升沿时,D_Instr置0,D_PCPC_ResetD_PC8PC_Reset + 4D_BDIn置0,D_ExcCodeExcCode_Default
2 异常请求 Req信号为1时,D_Instr置0,D_PCExc_AddrD_PC8Exc_Addr + 4D_BDIn置0,D_ExcCodeExcCode_Default
3 停机 stall信号为1时,保持D_InstrD_PCD_PC8D_BDInD_ExcCode的值不变
4 正常传递 stall信号为0时,在时钟上升沿将F_InstrF_PCF_PC8F_BDInF_ExcCode的值传递到D_InstrD_PCD_PC8D_BDInD_ExcCode

D_NPC 指令计算单元

  1. 定义:根据当前PC值、指令类型和条件分支结果,计算下一条指令的PC值。
  2. 端口定义
信号名 方向 位宽 说明
F_PC I 32 当前指令的PC值
Instr_index I 26 跳转指令的目标地址
offset I 16 分支指令的偏移量
rs I 32 寄存器rs的值
NPCSel I 3 下一条指令PC选择信号
CMPOut I 1 比较结果信号
CMPLabJump I 32 LAB跳转地址
EPC I 32 异常返回地址
D_isEret I 1 异常返回信号
Req I 1 异常中断请求信号
Next_PC O 32 计算得到的下一条指令的PC值
  1. 实现功能
序号 功能 描述
1 计算分支地址 根据当前PC值和偏移量计算分支指令的目标地址
2 计算跳转地址 根据当前PC值和指令索引计算跳转指令的目标地址
3 选择下一条指令PC 根据NPCSel信号选择下一条指令的PC值,支持顺序执行、分支、跳转和寄存器跳转
4 异常处理 根据Req信号和D_isEret信号选择异常处理地址或异常返回地址
选择信号 位宽 数值 描述
BranchType 3 3’b011 B型跳转,与CMPOut共同决定跳转
JrType 3 3’b010 JR型跳转
JumpType 3 3’b001 J型跳转
LABType 3 3’b100 LAB跳转

D_EXT 指令扩展

  1. 定义:根据控制信号,对输入的16位立即数进行零扩展或符号扩展。
  2. 端口定义
信号名 方向 位宽 说明
offset I 16 16位立即数
ExtOp I 1 扩展选择信号,0为零扩展,1为符号扩展
Extend O 32 扩展后的32位立即数
  1. 实现功能
序号 功能 描述
1 符号扩展 ExtOp信号为1时,Extend输出符号扩展后的32位立即数
2 零扩展 ExtOp信号为0时,Extend输出零扩展后的32位立即数

D_CMP 比较器

  1. 定义:根据控制信号,对输入的两个数进行比较,输出比较结果。
  2. 端口定义
信号名 方向 位宽 说明
RD1 I 32 读寄存器1数据
RD2 I 32 读寄存器2数据
CMPOp I 3 比较操作选择信号
CMPOut O 1 比较结果输出
  1. 实现功能
序号 功能 描述
1 相等比较 CMPOp信号为CMP_BEQ时,若RD1等于RD2CMPOut输出1,否则输出0
2 不等比较 CMPOp信号为CMP_BNE时,若RD1不等于RD2CMPOut输出1,否则输出0
3 小于等于零 CMPOp信号为CMP_BLEZ时,若RD1小于等于0,CMPOut输出1,否则输出0
4 大于零 CMPOp信号为CMP_BGTZ时,若RD1大于0,CMPOut输出1,否则输出0

GRF 寄存器堆

  1. 定义:根据读写信号,对寄存器堆进行读写操作。
  2. 端口定义
信号名 方向 位宽 说明
A1 I 5 读寄存器1地址
A2 I 5 读寄存器2地址
RegAddr I 5 写寄存器地址
RegData I 32 写数据
clk I 1 时钟信号
reset I 1 复位信号
RegWrite I 1 写使能信号
PC I 32 当前PC地址,用于输出
RD1 O 32 读寄存器1数据
RD2 O 32 读寄存器2数据

输出寄存器堆中寄存器写入输出到官方mips_tb.v,具体实现如下

1
2
3
4
assign w_grf_we = W_RegWrite;
assign w_grf_addr = W_RegAddr;
assign w_grf_wdata = W_RegData;
assign w_inst_addr = W_PC;
  1. 实现功能
序号 功能 描述
1 复位 当reset为1时,将所有寄存器置为0
2 当RegWrite为0时,将A1、A2对应的寄存器数据输出到RD1、RD2
3 当RegWrite为1时,当RegAddr不为0时,在时钟上升沿将RegAddr对应的寄存器写入RegData

A1、A2分别读取Rs、Rt寄存器,RegAddress根据RegDst选择Rt或R),RegData根据MemRead选择ALU的运算结果或I型指令的立即数

  1. 内部转发
    RegWrite为1时,若D级读取的寄存器和W级写入的寄存器相同且不为0,则将RegAddr对应的寄存器的值输出到RD1RD2
1
2
3
4
assign RD1 = 
(A1 == RegAddr && RegWrite && RegAddr != 0) ? RegData : GRF_reg[A1]; // Read the register1
assign RD2 =
(A2 == RegAddr && RegWrite && RegAddr != 0) ? RegData : GRF_reg[A2]; // Read the register2

E级:执行Execute

E_REG E级流水线寄存器

  1. 定义:存储E级流水线寄存器的数据。
  2. 端口定义
信号名 方向 位宽 说明
clk I 1 时钟信号
reset I 1 复位信号
clr I 1 清除信号
Req I 1 异常请求信号
D_Instr I 32 D级指令
D_PC I 32 D级PC值
D_PC8 I 32 D级PC+8值
D_CMPOut I 1 D级比较结果
D_RD1 I 32 D级寄存器数据1
D_RD2 I 32 D级寄存器数据2
D_Tnew I 2 D级新指令周期
D_Extend I 32 D级扩展数据
D_RegAddr I 5 D级寄存器地址
D_ExcCode_Fixed I 5 D级更新异常码
D_BDIn I 1 D级分支延迟槽信号
E_Instr O 32 E级指令
E_PC O 32 E级PC值
E_PC8 O 32 E级PC+8值
E_A1 O 5 E级寄存器地址1
E_A2 O 5 E级寄存器地址2
E_CMPOut O 1 E级比较结果
E_RD1 O 32 E级寄存器数据1
E_RD2 O 32 E级寄存器数据2
E_Tnew O 2 E级新指令周期
E_Extend O 32 E级扩展数据
E_RegAddr O 5 E级寄存器地址
E_ExcCode O 5 E级异常码
E_BDIn O 1 E级分支延迟槽信号
  1. 实现功能
序号 功能 描述
1 同步复位 reset信号为1或clr信号为1或Req信号为1时,所有输出信号清空,对于暂停操作而言相当于插入nop指令,但clr需保持D_PC的值不变,Req需跳转到异常处理程序
2 正常传递 在时钟上升沿,将D级输入信号传递到E级输出信号

ALU 算术逻辑单元

  1. 定义:根据控制信号,对输入的两个数进行算术或逻辑运算,并处理溢出异常。
  2. 端口定义
信号名 方向 位宽 说明
A I 32 输入操作数A
B I 32 输入操作数B
ALU_Op I 4 ALU操作码
E_isSt I 1 存储操作标志
E_isLd I 1 加载操作标志
ALU_OvExc I 1 溢出异常标志
ALU_Res O 32 运算结果
ALU_ExcCode O 5 异常码
  1. 实现功能

根据ALU_Op的值,对输入的A和B进行相应的算术或逻辑运算,并将结果输出到ALU_Res,同时处理溢出异常。

序号 功能 描述
1 ADD A + B
2 SUB A - B
3 AND A & B
4 OR A | B
5 XOR A ^ B
6 LUI 加载到高位
7 NOR ~(A | B)
8 SLT $signed (A) < $signed (B) ? 1 : 0
9 SLTU A < B ? 1 : 0
10 LAB 实验指令逻辑
11 输出异常码 根据输入的可能异常类型,结合溢出判断,输出异常码
1
2
3
4
assign ALU_ExcCode = 
(Overflow && E_isLd) ? `ExcCode_AdEL :
(Overflow && E_isSt) ? `ExcCode_AdES :
(Overflow && ALU_OvExc) ? `ExcCode_Ov : 5'b0;

MDU 乘除单元

  1. 定义:根据控制信号,对输入的两个数进行乘法或除法运算。
  2. 端口定义
信号名 方向 位宽 说明
A I 32 输入操作数A
B I 32 输入操作数B
MDUOp I 4 MDU操作码
clk I 1 时钟信号
reset I 1 复位信号
Req I 1 异常中断信号
start I 1 开始状态信号
MDURes O 32 运算结果
Hi O 32 高位结果
Lo O 32 低位结果
busy O 1 忙状态信号
  1. 实现功能

异常中断时,根据MDUOp的值,对输入的A和B进行相应的乘法或除法运算,并将结果输出到Hi和Lo寄存器,同时输出忙信号表示运算状态。

序号 功能 描述
1 MULT 有符号乘法,结果存储在Hi和Lo中
2 MULTU 无符号乘法,结果存储在Hi和Lo中
3 DIV 有符号除法,商存储在Lo中,余数存储在Hi中
4 DIVU 无符号除法,商存储在Lo中,余数存储在Hi中
5 MTHI 将A的值存储到Hi中
6 MTLO 将A的值存储到Lo中
7 MFHI 将Hi的值输出到MDURes
8 MFLO 将Lo的值输出到MDURes

设置临时变量hitemp和loemp,分别存储Hi和Lo的值,根据计数逻辑在完成乘除运算后,将hitemp和loemp的值赋值给Hi和Lo。

M级:存储Memory

M_REG M级流水线寄存器

  1. 定义:存储M级流水线寄存器的数据,并在时钟上升沿将E级输入信号传递到M级输出信号。
  2. 端口定义
信号名 方向 位宽 说明
clk I 1 时钟信号
reset I 1 复位信号
Req I 1 异常请求信号
E_Instr I 32 E级指令
E_PC I 32 E级PC值
E_PC8 I 32 E级PC+8值
E_RegAddr I 5 E级寄存器写地址
E_CMPOut I 1 E级比较结果
E_RD1 I 32 E级寄存器数据1
E_RD2 I 32 E级寄存器数据2
E_ALU_Res I 32 E级ALU运算结果
E_MDURes I 32 E级MDU运算结果
E_Tnew I 2 E级新指令周期
E_ALU_Fwd_MUXOut I 32 E级ALU转发MUX输出
E_BDIn I 1 E级分支延迟槽信号
E_ExcCode_Fixed I 5 E级更新异常码
M_Instr O 32 M级指令
M_PC O 32 M级PC值
M_PC8 O 32 M级PC+8值
M_RegAddr O 5 M级寄存器写地址
M_CMPOut O 1 M级比较结果
M_RD1 O 32 M级寄存器数据1
M_RD2 O 32 M级寄存器数据2
M_ALU_Res O 32 M级ALU运算结果
M_MDURes O 32 M级MDU运算结果
M_Tnew O 2 M级新指令周期
M_ALU_Fwd_MUXOut O 32 M级ALU转发MUX输出
M_BDIn O 1 M级分支延迟槽信号
M_ExcCode O 5 M级异常码
  1. 实现功能
序号 功能 描述
1 同步复位 resetReq信号为1时,所有输出信号清空,对于暂停操作而言相当于插入nop指令,注意对Req需跳转到异常处理程序,且延迟槽BDIn需要保持
2 正常传递 在时钟上升沿,将E级输入信号传递到M级输出信号

M_DM 数据存储器

由于内存外置,故原DM模块实现转移到BE和DE中

M_BE 缓存写回模块

  1. 定义:根据读写信号和地址,对数据进行字节、半字或字的写操作,并处理地址对齐和异常情况。
信号名 方向 位宽 说明
LSOp I 3 读写操作选择信号
BEAddr I 32 缓存写回地址
BE_WD_In I 32 缓存写回输入数据
MemWrite I 1 内存写使能信号
BE_isSt I 1 存储操作标志
byteen O 4 字节使能信号
BE_WD_Out O 32 缓存写回输出数据
BE_ExcCode O 5 缓存写回异常码
  1. 实现功能
序号 功能 描述
1 字写操作 LSOpLs_Word时,byteen4'b1111BE_WD_OutBE_WD_In
2 半字写操作 LSOpLs_Half时,根据BEAddr的值选择高16位或低16位进行写操作
3 字节写操作 LSOpLs_Byte时,根据BEAddr的值选择相应的字节进行写操作
4 默认操作 MemWrite为0或LSOp为其他值时,byteen4'b0000BE_WD_Out32'h00000000
5 异常处理 根据AlignExc, AddrExc, TimerExc, CountExc情况,设置BE_ExcCode的值

M_DE 缓存读模块

  1. 定义:根据读信号和地址,对数据进行字节、半字或字的读操作,并处理地址对齐和异常情况。

  2. 端口定义

信号名 方向 位宽 说明
LSOp I 3 读操作选择信号
DEAddr I 32 缓存读出地址
DE_m_data_rdata I 32 缓存读出输入数据
DE_isLd I 1 读操作标志
DE_RD O 32 缓存读出输出数据
DE_ExcCode O 5 缓存读出异常码
  1. 实现功能
序号 操作 功能
1 字读操作 LSOpLs_Word时,DE_RDDE_m_data_rdata
2 半字读操作 LSOpLs_Half时,根据DEAddr的值选择高16位或低16位进行读操作
3 字节读操作 LSOpLs_Byte时,根据DEAddr的值选择相应的字节进行读操作
4 半字无符号读操作 LSOpLs_Half_Unsigned时,根据DEAddr的值选择高16位或低16位进行无符号读操作
5 字节无符号读操作 LSOpLs_Byte_Unsigned时,根据DEAddr的值选择相应的字节进行无符号读操作
6 默认操作 LSOp为其他值时,DE_RD32'h00000000
7 地址对齐异常检测 LSOpLs_Word且未对齐时,或LSOpLs_Half且未对齐时,AlignExc为1
8 地址范围异常检测 DEAddr不在合法范围内时,AddrExc为1
9 定时器异常检测 LSOpLs_HalfLs_ByteDEAddr在定时器地址范围内时,TimerExc为1
10 异常码输出 DE_isLd为1且存在异常时,DE_ExcCodeExcCode_AdEL,否则为5'b0

CP0 模块

  1. 定义:CP0 模块用于处理异常和中断信号,管理状态寄存器(SR)、异常原因寄存器(CAUSE)和异常程序计数器(EPC)。

  2. 端口定义

信号名 方向 位宽 说明
clk I 1 时钟信号
reset I 1 复位信号
enable I 1 使能信号
CP0Addr I 5 CP0 寄存器地址
CP0_WD_In I 32 CP0 写入数据
VPC I 32 虚拟程序计数器
BDIn I 1 分支延迟槽信号
ExcCodeIn I 5 输入异常码
HWInt I 6 硬件中断信号
EXLClr I 1 EXL 清除信号
CP0Out O 32 CP0 输出数据
Req O 1 异常请求信号
EPCOut O 32 异常程序计数器输出
  1. 实现功能
序号 操作 功能
1 复位操作 reset信号为1时,SRCAUSEEPCCP0Out清零
2 硬件中断处理 Req信号为1时,EXL置1,ExcCode根据HWIntIM设置,EPC根据BDIn设置,BDBDIn
3 EXL 清除操作 EXLClr信号为1时,EXL置0
4 CP0 寄存器写操作 enable信号为1时,根据CP0Addr写入SRCAUSEEPC
5 CP0 寄存器读操作 根据CP0Addr读取SRCAUSEEPCCP0Out
6 异常请求检测 EXL为0且ExcCodeIn不为0或HWIntIM不为0且IE不为0时,Req置1
7 EPC 输出 EPC输出到EPCOut

W级:写回WriteBack

W_REG W级流水线寄存器

  1. 定义:存储W级流水线寄存器的数据。
  2. 端口定义
信号名 方向 位宽 说明
clk I 1 时钟信号
reset I 1 复位信号
Req I 1 异常请求信号
M_Instr I 32 M级指令
M_PC I 32 M级PC值
M_PC8 I 32 M级PC+8值
M_A1 I 5 M级寄存器地址1
M_A2 I 5 M级寄存器地址2
M_RegAddr I 5 M级寄存器写地址
M_RD1 I 32 M级寄存器数据1
M_RD2 I 32 M级寄存器数据2
M_ALU_Res I 32 M级ALU运算结果
M_MDURes I 32 M级ALU运算结果
M_DM_RD I 32 M级数据存储器读数据
RegWrite_M I 1 M级寄存器写使能信号
RegDataSel_M I 3 M级寄存器数据选择信号
M_Tnew I 2 M级新指令周期
W_Instr O 32 W级指令
W_PC O 32 W级PC值
W_PC8 O 32 W级PC+8值
W_A1 O 5 W级寄存器地址1
W_A2 O 5 W级寄存器地址2
W_RegAddr O 5 W级寄存器写地址
W_RD1 O 32 W级寄存器数据1
W_RD2 O 32 W级寄存器数据2
W_ALU_Res O 32 W级ALU运算结果
W_DM_RD O 32 W级数据存储器读数据
RegWrite_W O 1 W级寄存器写使能信号
RegDataSel_W O 3 W级寄存器数据选择信号
W_Tnew O 2 W级新指令周期
  1. 实现功能
序号 功能 描述
1 同步复位 reset或者Req信号为1时,所有输出信号清空,对于暂停操作而言相当于插入nop指令
2 正常传递 在时钟上升沿,将M级输入信号传递到W级输出信号

MCU 控制单元

  1. 定义
    MCU 控制单元用于生成控制信号,控制其他模块的行为。

  2. 端口定义

信号名 方向 位宽 说明
Instr I 32 指令
CMPOut I 1 比较结果信号
RegDstSel O 3 寄存器目标选择信号
ALUBSrcSel O 1 ALU_B源选择信号
RegDataSel O 3 寄存器数据选择信号
RegWrite O 1 寄存器写使能信号
MemWrite O 1 内存写使能信号
NPCSel O 3 下一条指令PC选择信号
ExtOp_D O 1 扩展操作选择信号
CMPOp O 3 比较操作选择信号
ALU_Op O 4 ALU操作码
MDUOp O 4 MDU操作码
MDU_Start O 1 MDU启动信号
LSOp O 3 存储操作码
Tuse_rs O 2 rs使用需要周期数
Tuse_rt O 2 rt使用需要周期数
Tnew_D O 2 产生数据所用周期数
CU_ExcCode O 5 控制单元异常码
isEret O 1 异常返回信号
BE_isSt O 1 存储操作标志
DE_isLd O 1 加载操作标志
ALU_AdExc O 1 地址异常信号
ALU_OvExc O 1 溢出异常信号
Cp0Enable O 1 CP0使能信号
isLAB O 1 LAB信号
  1. 实现功能
序号 功能 描述
1 指令译码 根据操作码和功能码生成对应的控制信号
2 控制信号生成 生成寄存器目标选择信号、ALU B源选择信号、寄存器数据选择信号等
3 冒险时间生成 生成rs和rt的使用时间以及新指令周期
  1. 信号生成说明
    将所有指令译码后根据类型分为cal_rcal_ildstmdmtmfb_typej_type,对于共性控制信号直接按照类型生成

  2. 多路选择器说明

    1. RegDstSel:寄存器目标选择信号,用于选择写入寄存器的目标寄存器。
    类型 方向 位宽 说明
    RaType I 32 写回ra寄存器
    RdType I 32 写回rd寄存器
    RtType I 32 写回rt寄存器
    1. ALUBSel:ALU B源选择信号,用于选择ALU B输入端的源。
    类型 方向 位宽 说明
    E_ALU_Fwd_MUXOut I 32 寄存器值
    EXT I 32 扩展后的立即数
    1. RegDataSel:寄存器数据选择信号,用于选择写入寄存器的数据源。
    类型 方向 位宽 说明
    FromMDU I 32 来自MDU
    FromPC I 32 来自PC8
    FromALU I 32 来自ALU
    FromDM I 32 来自DM

HCU 冒险控制单元

  1. 定义:冒险控制单元用于检测流水线中的数据冒险,并生成相应的转发和停顿信号。
  2. 端口定义
信号名 方向 位宽 说明
Tuse_rs I 2 rs使用需要周期数
Tuse_rt I 2 rt使用需要周期数
Tnew_E I 2 E级产生数据需要周期
Tnew_M I 2 M级产生数据需要周期
Tnew_W I 2 W级产生数据需要周期
D_A1 I 5 D级寄存器地址1
D_A2 I 5 D级寄存器地址2
D_MDUOp I 4 D级MDU操作控制信号
D_isEret I 1 D级异常返回信号
E_A1 I 5 E级寄存器地址1
E_A2 I 5 E级寄存器地址2
E_A3 I 5 E级寄存器写地址
E_rd I 5 E级CP0寄存器地址
E_Busy I 1 E级MDU忙状态
E_Start I 1 E级MDU开始状态
E_Cp0Enable I 1 E级CP0使能信号
M_A2 I 5 M级寄存器地址2
M_A3 I 5 M级寄存器写地址
M_rd I 5 M级CP0寄存器地址
M_Cp0Enable I 1 M级CP0使能信号
W_A3 I 5 W级寄存器写地址
RegWrite_E I 1 E级寄存器写使能信号
RegWrite_M I 1 M级寄存器写使能信号
RegWrite_W I 1 W级寄存器写使能信号
E_isLAB I 1 E级LAB信号
M_isLAB I 1 M级LAB信号
CMP_RD1_Fwd_D O 3 比较器RD1转发信号
CMP_RD2_Fwd_D O 3 比较器RD2转发信号
ALU_A_Fwd_E O 3 ALU A转发信号
ALU_B_Fwd_E O 3 ALU B转发信号
DM_WD_Fwd_M O 3 数据存储器写数据转发信号
stall O 1 停顿信号
  1. 实现功能
序号 功能 描述
1 停顿检测 根据寄存器地址和使用周期数,检测是否需要停顿
2 转发信号生成 生成比较器、ALU和数据存储器的转发信号
3 停顿信号生成 生成流水线停顿信号

暂停Stall

使用A-T法判断,当address相同时,若D级的Tuse_rs或Tuse_rt比E、M、W级的Tnew小,则说明在D级需要使用寄存器中数据时,E、M、W级相应的寄存器数据还未准备好,需要暂停流水线。

1
2
3
4
5
6
7
8
9
E_Stall_Rs = (E_A3 == D_A1) && (D_A1 != 5'b0) && (Tnew_E > Tuse_rs) && RegWrite_E;
E_Stall_Rt = (E_A3 == D_A2) && (D_A2 != 5'b0) && (Tnew_E > Tuse_rt) && RegWrite_E;
M_Stall_Rs = (M_A3 == D_A1) && (D_A1 != 5'b0) && (Tnew_M > Tuse_rs) && RegWrite_M;
M_Stall_Rt = (M_A3 == D_A2) && (D_A2 != 5'b0) && (Tnew_M > Tuse_rt) && RegWrite_M;
E_stall_md = D_MDUOp != `MDU_NONE && (E_Busy || E_Start);
Stall_Eret = D_isEret && (E_Cp0Enable && E_rd == `CP0_EPC || M_Cp0Enable && M_rd == `CP0_EPC);

stall = E_Stall_Rs || E_Stall_Rt || M_Stall_Rs || M_Stall_Rt || E_stall_md || Stall_Eret;
//W级不需要判断,因为在GRF中存在内部转发

转发Foward

执行暴力转发,使用A-T法判断,当address相同且D级的Tuse_rs或Tuse_rt大于E、M级相应的Tnew时,说明D级需要使用的数据在E、M级中,需要转发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Forwarding logic for CMP_RD1, W not included because it's forwared in GRF
assign CMP_RD1_Fwd_D =
(M_A3 == D_A1 && RegWrite_M && D_A1) ? `FWD_MEM :
(W_A3 == D_A1 && RegWrite_W && D_A1) ? `FWD_WB : `FWD_GRF;

// Forwarding logic for CMP_RD2, W not included because it's forwared in GRF
assign CMP_RD2_Fwd_D =
(M_A3 == D_A2 && RegWrite_M && D_A2) ? `FWD_MEM :
(W_A3 == D_A2 && RegWrite_W && D_A2) ? `FWD_WB : `FWD_GRF;

// Forwarding logic for ALU_A
assign ALU_A_Fwd_E =
(M_A3 == E_A1 && RegWrite_M && E_A1) ? `FWD_MEM :
(W_A3 == E_A1 && RegWrite_W && E_A1) ? `FWD_WB : `FWD_GRF;

// Forwarding logic for ALU_B
assign ALU_B_Fwd_E =
(M_A3 == E_A2 && RegWrite_M && E_A2) ? `FWD_MEM :
(W_A3 == E_A2 && RegWrite_W && E_A2) ? `FWD_WB : `FWD_GRF;

// Forwarding logic for DM_WD
assign DM_WD_Fwd_M =
(W_A3 == M_A2 && RegWrite_W && M_A2) ? `FWD_WB : `FWD_GRF;

Bridge 系统桥

  1. 定义:Bridge 模块用于在 CPU 和外设之间进行数据传输和中断管理。它根据地址范围选择目标外设,并处理读写操作和中断信号。

  2. 端口定义

信号名 方向 位宽 说明
interrupt I 1 外部中断信号
TC0_IRQ I 1 定时器0中断请求信号
TC0_Dout I 32 定时器0数据输出
TC1_IRQ I 1 定时器1中断请求信号
TC1_Dout I 32 定时器1数据输出
m_data_rdata I 32 内存数据读取
CPU_m_data_addr I 32 CPU 数据地址
CPU_m_data_wdata I 32 CPU 数据写入
CPU_m_data_byteen I 4 CPU 字节使能信号
CPU_m_inst_addr I 32 CPU 指令地址
HWInt O 6 硬件中断信号
TC0_Addr O 32 定时器0地址
TC0_WE O 1 定时器0写使能
TC0_Din O 32 定时器0数据输入
TC1_Addr O 32 定时器1地址
TC1_WE O 1 定时器1写使能
TC1_Din O 32 定时器1数据输入
CPU_m_data_rdata O 32 CPU 数据读取
m_data_addr O 32 内存数据地址
m_data_wdata O 32 内存数据写入
m_data_byteen O 4 内存字节使能信号
m_inst_addr O 32 内存指令地址
  1. 功能实现
序号 功能 描述
1 地址选择 根据 CPU 数据地址选择目标外设(定时器0、定时器1或内存)
2 数据传输 根据选择的目标外设进行数据读写操作
3 中断管理 处理外部中断信号和定时器中断请求信号,并生成硬件中断信号
4 写使能控制 根据字节使能信号和目标外设生成定时器写使能信号

TC 计时器模块

课程组官方提供

  • 空闲(IDLE):如果ctrl寄存器的第0位为1,则进入加载状态。
  • 加载(LOAD):将预置值加载到计数器中,然后进入计数状态。
  • 计数(CNT):如果ctrl寄存器的第0位为1,则计数器减1,直到计数器为0,然后进入中断状态。
  • 中断(INT):设置中断信号_IRQ为1,然后根据ctrl寄存器的第2、3位决定是否重置计数器或清除中断信号,最后回到空闲状态。
当前状态 条件 下一个状态 动作
IDLE ctrl[0]为1 LOAD _IRQ置0
LOAD - CNT countpreset
CNT ctrl[0]为1且count>1 CNT count减1
CNT ctrl[0]为1且count<=1 INT count置0,_IRQ置1
CNT ctrl[0]为0 IDLE -
INT ctrl[2:1]为2’b00 IDLE ctrl[0]置0
INT 其他 IDLE _IRQ置0

测试方案

沿用P6的随机测试程序,用于检测指令执行与转发阻塞的正确性,对于异常处理,则手动构造所有可能的异常情况,依次并验证其正确性。对于中断处理,使用官方tb,检测在对应的target_PC是否执行中断。

P7思考题

  1. 请查阅相关资料,说明鼠标和键盘的输入信号是如何被 CPU 知晓的?

键盘和鼠标本质上都是输入设备,通过设备自身程序释放中断信号,指引处理器处理相应的输入信息。

  1. 请思考为什么我们的 CPU 处理中断异常必须是已经指定好的地址?如果你的 CPU 支持用户自定义入口地址,即处理中断异常的程序由用户提供,其还能提供我们所希望的功能吗?如果可以,请说明这样可能会出现什么问题?否则举例说明。(假设用户提供的中断处理程序合法)

是可以的,我们可以通过改变出现异常中断时的跳转地址,但是这样可能会出现用户自定义程序与系统程序冲突的问题,对于不同的用户需要重新修改处理器,这样会使得处理器变得复杂,并且无法通用。

  1. 为何与外设通信需要 Bridge?

由于外设的种类是多样的,而CPU在处理指令时只需要处理数据,因此需要通过Bridge来进行数据的中转,从而在增加外设时无需修改CPU的设计,使得CPU可以通用。

  1. 请阅读官方提供的定时器源代码,阐述两种中断模式的异同,并分别针对每一种模式绘制状态移图。

模式0:
[*] --> IDLE
IDLE --> IDLE:reset
IDLE --> LOAD:ctrl[0] = 1
LOAD --> CNT
CNT --> CNT:ctrl[0] && count > 1
CNT --> INT:ctrl[0] && count <= 1
INT --> IDLE:ctrl[0] = 0 && Int = 1
CNT --> IDLE:!ctrl[0]

模式1:
[*] --> IDLE
IDLE --> IDLE:reset
IDLE --> LOAD:ctrl[0] = 1
LOAD --> CNT
CNT --> CNT:ctrl[0] && count > 1
CNT --> INT:ctrl[0] && count <= 1
INT --> IDLE:Int = 0
CNT --> IDLE:ctrl[0] == 0

  1. 倘若中断信号流入的时候,在检测宏观 PC 的一级如果是一条空泡(你的 CPU 该级所有信息均为空)指令,此时会发生什么问题?在此例基础上请思考:在 P7 中,清空流水线产生的空泡指令应该保留原指令的哪些信息?

如果此时PC为空,那么在流水线中会一直空泡,导致宏观PC也将表现为0,因此需要保留原指令的PC信息。

  1. 为什么 jalr 指令为什么不能写成 jalr $31, $31?

因为jalr指令的跳转地址是PC+4+立即数,而$31是PC,因此如果将jalr指令写成jalr $31, $31,那么如果jalr的延迟槽内出现异常中断,那么中断异常结束后,会再次执行 jalr 指令,由于无法撤销已经执行的jalr指令,导致寄存器值已经修改,这就会跳转到不正确的 PC 地址。