Skip to content

P4 单周期 CPU 设计文档

一、指令分析

MIPS所有指令大致可分成三类,对它们做一一分析

1.1 R 型指令

R型指令的指令格式为:

[31:26]op(R型指令全0
[25:21]rs(源操作数
[20:16]rt(源操作数
[15:11]rd(目的操作数
[10:6]shamt(位移量
[5:0]func(辅助op决定指令类型)

R 型指令又可具体分成三种:

  1. 第一种类似 add 指令 两个源寄存器 rsrt 进行运算,结果存到第目标寄存器 rd,由 func 段决定具体功能,shamt 段全为 0
  2. 第二种用于移位运算, 例如 sll 指令、sra 指令。此时 shamt 段指示移位量, rs 全为 0
  3. 第三种就是 jr 指令, 只有 oprsfunc 段不为零

1.2 I 型指令

I 型指令格式为:

[31:26]op(决定指令类型)
[25:21]rs(第一个源操作数)
[20:16]rt(目的操作数)
[15:0]immediate(第二个源操作数)

I 型指令具体又分成三种:

  1. 第一种,类似 addi 指令,将 rsimmediate 做运算,结果存到目的寄存器 rt 中。
  2. 第二种,类似于 lw 指令, 将 两个操作数 rsimmediate 直接相加作为数据段内存 RAM 的地址加以操作。
  3. 第三种,例如 beq 指令, 对 rsrt 作比较, 根据结果判断是否利用 immediate 段对pc做操作。

1.3 J 型指令

J 型指令的格式:

[31:26]op(决定指令类型)
[25:0]immediate(立即数)

J 型指令又细分两种:

  1. 第一种如 j,根据 immediate 段直接得到 PC 的值。

  2. 第二种如 jal, 功能类似上一条,但是多了一步,跳转之前会把当前 PC+4 存入 ra 寄存器 中


二、模块设计

2.1 PC

32位寄存器,输入信号包括同步复位信号,时钟信号,下一个 PC 值,输出信号有当前 PC 值

端口方向功能
PCnextinput[31:0]下一条指令的地址
clkinput时钟控制信号
resetinput同步复位信号,高电平有效
PCoutput[31:0]当前执行的指令地址

2.2 NPC

NPC 模块实现对下一条指令的判断,根据对指令的归类,下一条指令可能来自于:当前 PC 值加 4、 J 指令的 26 位立即数段直接置入新的 PC、 I 型跳转指令 16 位立即数与当前 PC 做运算、jr 指令跳转到寄存器存储的指令地址

端口方向功能
imm_26input[25:0]26 位立即数
imm_16input[15:0]16 位立即数
PCinput[31:0]当前PC的值
NPCopinput[1:0]00PC+401PC+4+signed[imm_16]+0010PC[31:28]+imm26+0011regdata
Reg_rainput[31:0]用于 jr 指令
CMPresultinput用于 R 型跳转指令的比较结果
PCnextoutput[31:0]计算所得下一个 PC

2.3 IM

存放指令的存储器。

端口方向功能
instrAddrinput[13:2]指令所在的地址
instroutput[31:0]32 位指令机器码

2.4 ALU

提供各类运算功能。

端口方向功能
operationAinput[31:0]第一个操作数
operationBinput[31:0]第二个操作数
shamtCinput[4:0]用于R指令的移位数
ALUopinput[2:0]控制信号 000:A+B;001:A-B;010: A或B;011:A与B;100:B逻辑右移C;101:B逻辑左移C;110:B算数右移C
CMPopinput[2:0]模块控制信号 000:A=?=B;001:A<?B有符号;010:A>?B有符号;011:A<?B无符号;100:A>?B无符号;101:A!=B?
ALUresultoutput[31:0]32 位输出结果
CMPresultoutput根据 CMPop 输出一位结果,高电平为真

2.5 DM

数据存储器,用于作内存,存储数据。

端口方向功能
Resetinput同步复位信号
clkiinput时钟控制信号,上升沿有效
MemAddrinput[11:0]数据所在地址
MemWriteinput写入信号,高电平时,将数据端口数据写入对应地址当中
MemWDinput[31:0]将要写入 RAM 内存里的数据
MemReadDataoutput[31:0]根据 DataAddr 读出的数据

2.6 EXT

实现有/无符号的扩展。

端口方向功能
EXTininput[15:0]操作数
EXTopinput[1:0]控制信号 00:符号扩展, 01: 无符号扩展; 10: 低位补0
EXToutoutput[31:0]扩展得到的结果

2.7 GRF

32位通用寄存器的读写模块。

端口方向功能
resetinput同步复位信号
GRFWriteinput写控制信号,高电平有效
clkinput时钟信号
regAddr1input[4:0]第一个读寄存器的编号
regAddr2input[4:0]第二个读寄存器的编号
regAddr3input[4:0]用于写的寄存器的编号
regWDinput[31:0]用于写入A3寄存器的32位数据
RD1output[31:0]第一个读出的数据
RD2output[31:0]第二个读出的数据

2.8 Controller

组合逻辑得到控制信号。

端口方向功能
Instr_opinput[5:0]读取指令的 opz 字段
Instr_funcinput[5:0]读取指令的 func 字段
RegWriteoutput寄存器文件 GRF 写控制信号 1:使能;0:不能写入
RegDstouput[1:0]区分 R 型指令与I型指令的多路选择信号 00:选择instr_rd;01:选择instr_rt;10:写入31号寄存器 ra
EXTopoutput[1:0]EXT 模块区分有无符号扩展的控制信号 00:符号扩展;01:无符号扩展;10:低位补零
NPCopoutput[1:0]PCnext = 00PC+401PC+4+signed[imm_16]+0010PC[31:28]+imm26+0011regdata
ALUSrcoutput选择 ALU 的操作数 B 0:RD2;1:扩展后的 32 位立即数
ALUopoutput[2:0]控制信号 000:A+B;001:A-B;010: A或B; 011:A与B; 100:B逻辑右移C; 101: B逻辑左移C; 110: B算数右移C
CMPopoutput[2:0]模块控制信号 000:A=?=B;001;A<?B有符号;010:A>?B有符号;011:A<?B无符号;100: A>?B无符号;101:A!=B?
MemWriteoutput写入信号,高电平时,将数据端口数据写入对应地址当中
DatatoRegoutput[2:0]GRF 输入端 WD 的选择信号,000:ALUresult;001:MemReadData;010:PC+4;011:写入 CMPresult

三、指令实现

该部分则主要是根据要实现的指令特征对 Controller 的输入输出作分析

  • ori 指令:

    功能描述 : GPR[rt] <- GPR[rs] OR unsignedextend(immediate)

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    00110110101001010XXX0000
  • add 指令:

    功能描述:GPR[rd] <- GPR[rs]+GPR[rt]

    opfuncRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    000000100000100XX000000XXX0000
  • sub 指令:

    功能描述 GPR[rd] <- GPR[rs] - GPR[rt]

    opfuncRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    000000100010100XX000001XXX0000
  • sw 指令:

    功能描述:memory[GPR[base]+offset] <- GPR[rt]

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    1010110XX00001000XXX1XXX
  • lw 指令:

    功能描述:GPR[rt] <= memory[GPR[base]+offset]

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    10001110100001000XXX0001
  • lui 指令:

    功能描述:GPR[rt] <- immediate||16'd0

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    00111110110001000XXX0000
  • beq 指令:

    功能描述:if (GPR[rs] == GPR[rt]) PC <- PC + 4 + sign_extend(offset||00) else PC <- PC + 4

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    0001000XXXX01XXXX0000XXX
  • jr 指令:

    功能描述:PC <- GPR[rs]

    opfuncRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    0000000010000XXXX11XXXXXXX0XXX
  • jal 指令:

    功能描述:PC <- (PC[31:28] || instr_immediate || 00); GPR[31] <- PC + 4

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    000011110XX10XXXXXXX0010
  • bne 指令:

    功能描述:if (GPR[rs] ≠ GPR[rt]) PC <- PC + 4 + sign_extend(offset||00) else PC <- PC + 4

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    0001010XXXX01XXXX1010XXX
  • J 指令:

    功能描述:PC <- PC[31:28]||immediate||00

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    0000100XXXX10XXXXXXXX0XXX
  • addi 指令:

    功能描述:GPR[rt] <- GPR[rs]+ signedextend(immediate)

    opRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    00100010100001000XXX0000
  • slt 指令:

    功能描述:GPR[rd] <- (GPR[rs] < GPR[rt])

    opfuncRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    000000101010100XX000XXX0010011
  • sll 指令:

    功能描述:GPR[rd] <- GPR[rt] << s

    功能描述:GPR[rt] <- GPR[rs]+ signedextend(immediate)

    opfuncRegWriteRegDst[1:0]EXTop[1:0]NPCop[1:0]ALUSrcALUop[2:0]COMPop[2:0]MemWriteDatatoReg[2:0]
    000000000000100XX000101XXX0000

四、测试方案

声明:下列所有测试数据均是手捏数据,测试强度不能保证。

ori 指令:

ori $t0, $zero, 200
ori $t1, $t0, 65535
ori $zero, $t1, 100

lui 指令:

lui $a2, 123           
lui $a3, 0xffff         
lui $zero, 123
lui $a1, 0

add 指令:

lui $t1, 0    # t1 > 0
lui $t2, 0xffff # t2 < 0
ori $t1, 100
ori $t2, 100
nop
add $t3, $t2, $t2
add $t4, $t1, $t1
add $t5, $t1, $t2
add $0, $0, $t5

sub 指令:

lui $t1, 0    # t1 > 0
lui $t2, 0xffff # t2 < 0
ori $t1, 100
ori $t2, 100
nop
sub $t3, $t2, $t2
sub $t4, $t1, $t1
sub $t5, $t1, $t2
sub $t5, $t2, $t1
sub $0, $0, $t5

sw 指令:

ori $t0, $0, 16
ori $a0, 100
lui $a1, 0xf000
ori $a1, 0xff00
lui $a2, 0xffff
ori $a2, 0xffff
lui $a3, 0x8fff
ori $a3, 0xffff
sw $a0, 0($t0)
sw $a1, 4($t0)
sw $a2, 8($t0)
sw $a3, -4($t0)

lw 指令:

ori $t0, $0, 16
ori $a0, 100
lui $a1, 0xf000
ori $a1, 0xff00
lui $a2, 0xffff
ori $a2, 0xffff  #a2 = -1
lui $a3, 0x8fff
ori $a3, 0xffff
sw $a0, 0($t0)
sw $a1, 4($t0)
sw $a2, 8($t0)
sw $a3, -4($t0)
nop
lw $0, 0($t0)
lw $s0, -4($t0)
lw $s1, 4($t0)
lw $s2, 17($a2)

beq 指令:

ori $a0, 1
ori $a1, 2
ori $a2, 3
beq $t0, $a0, state1
add $t0, $a0, $a0
beq $t0, $a1, state2
state1:
    add $t0, $t0, $a0
state2:
    beq $t0, $a1, state1
state3:
    beq $t0, $a1, state3
state4:
    beq $t0, $a2, state4
add $t0, $0, $0

jal、jr 指令:

ori $t1, $t1, 50
ori $t2, $t2, 6565
ori $t3, $t3, 0
    while_begin:
        beq $t3, $t1, while_end
        jal fun
        nop
        j while_begin
    while_end:
    la $s3, end
    jr $s3
fun:
    addi $t3, $t3, 2
    jr $ra
end:
    jal end