1. CPU 数据通路
  2. CPU 控制器

Github 项目地址

1. CPU 数据通路

本 CPU 根据《数字设计和计算机体系结构》设计
参考的数据通路如下,同时在这个基础上增加了支持 J 指令的数据通路

2. CPU 控制器

  1. 控制信号
  2. 指令格式
  3. 冒险检测与解决

2.1 控制信号

输出引脚 作用
RegWrite 当前指令需要写入寄存器
MemtoReg 当前指令需要从存储器中获取数据并存入寄存器
MemWrite 当前指令需要写入存储器
ALUCtrl 指定 ALU 运算类型
ALUSrc ALU 中 B 数据来源选择(寄存器/立即数)
RegDst 寄存器写入目的指定,指定需要写入的寄存器(Rt/Rd)
BranchBEQ 当前指令为 BEQ 指令,需要在指令译码阶段判断是否跳转
BranchJ 当前指令为 J 指令,在指令译码阶段完成 J 跳转

2.2 指令格式

根据 MIPS 汇编指令的二进制码转换为对应的 ALU 操作指令
参考网址: CSDN 博客

ALU 操作码 运算 Func 码
000 AND 100100
001 OR 100101
010 ADD 100000
011 SUB 100010
100 SLT 101010
110 NOR 100111
111 XOR 100110

2.3 冒险检测与解决

  1. 已完成的指令

    1. R 型指令
    2. LW 指令
    3. SW 指令
    4. BEQ 指令
    5. J 指令
  2. 未完成指令

    1. ADDI 指令
  3. 已解决的冒险

    1. J 控制冒险
    2. BEQ 控制/数据冒险
    3. RAW 数据冒险(M 阶段和 W 阶段)
  4. 冒险,解决办法和测试指令

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    # 1.RAW数据冲突
    # 即计算得到的结果需要在送回寄存器之前被其他指令用(以R型指令为例,I型指令同理)
    # 1.1 从另一个寄存器转移到另一个寄存器
    # 该冲突使用数据旁路解决
    LW $1,0($0)
    LW $2,1($0)
    ADD $3,$0,$0
    ADD $4,$0,$0
    ADD $5,$0,$0
    ADD $6,$0,$0
    ADD $7,$0,$0
    # ($1,$2寄存器初始化完成,同时流水线中不再使用$1,$2寄存器)
    # 开始测试
    # 正确结果为$8,$9,$10寄存器中的结果为数据存储器0,1地址数之和
    ADD $1,$1,$2
    ADD $8,$1,$0
    ADD $9,$1,$0
    ADD $10,$1,$0
    # 1.2 从数据存储器中取数
    # 该冲突使用插入一个气泡解决
    # 正确结果为$3寄存器中的结果为数据存储器0,1地址数之和
    LW $1,0($0)
    LW $2,1($0)
    ADD $3,$1,$2

    # 2. BEQ指令数据冲突
    # 得到BEQ指令需要用到但是还没送回RF的数据
    # 由于BEQ指令在D阶段就需要用数据,所以不同于R型指令
    # 该冲突同时使用数据旁路和出入气泡解决
    # 2.1 需要用的数据在 W 阶段==>由于寄存器组支持同时读写所以没有冲突
    # 2.2 需要用的数据在 M 阶段==>使用数据旁路解决
    # 2.3 需要用的数据在 E 阶段==>插入一个气泡后使用2.2方法解决
    LW $1,0($0)
    LW $2,1($0)
    ADD $3,$0,$0
    ADD $4,$0,$0
    ADD $5,$0,$0
    ADD $6,$0,$0
    ADD $7,$0,$0
    # ($1,$2寄存器初始化完成,同时流水线中不再使用$1,$2寄存器)
    # 正确结果为完成跳转($4寄存器中的值不变)
    ADD $3,$1,$0
    BEQ $1,$3,4
    ADD $4,$3,$0
    ADD $5,$3,$0
    ADD $6,$3,$0

    # 3. 控制冒险
    # 即指令执行顺序发生改变
    # 3.1 J指令跳转
    # 正确结果为$3,$4寄存器中的值未发生改变
    LW $1,0($0)
    LW $2,1($0)
    J 20
    LW $3,2($0)
    LW $4,3($0)
    LW $5,4($0)
    LW $6,5($0)
    # 3.2 BEQ指令跳转
    # 正确结果为$2,$3寄存器中的值发生改变,$4,$5寄存器中的值未发生改变
    LW $1,0($0)
    BEQ $1,$0,8
    LW $2,1($0)
    LW $3,2($0)
    BEQ $1,$1,8
    LW $4,3($0)
    LW $5,4($0)
    LW $6,5($0)