CPU 设计文档

一、指令类型

  • 解读:将指令按类型分类,并对指令按照功能划分

R类型指令

R类型指令 Op(31~26) Rs(25~21) Rt(20~16) Rd(15~11) Shamt(10~6) Func(5~0)
Add 000000 Rs Rt Rd XXXXX 100000
Sub 000000 Rs Rt Rd XXXXX 100010

I类型指令

I类型指令 Op(31~26) Rs(25~21) Rt(20~16) immediate or address
Ori 001101 Rs Rt imm16
Lui 001111 00000 Rt imm16
Lw 100011 Rs Rt imm16
Sw 101011 Rs Rt imm16
Beq 000100 Rs Rt imm16

J类型指令

J类型指令 Op(31~26) 26 address
j 000010 target

二、主要模块

Conroller(控制器)

控制信号类型及含义

Branch
>

  • Beq 1: 若Zero=1,PC输入选择加法器Nadd
  • Other : 0,PC输入选择加法器Add输出(PC+4)

RegDst
>

  • 0: 选择Rd
  • 1: 选择Rt

RegWirte
>

1: 表示寄存器堆可写入

MemtoReg
>

  • R型指令 0: 选择 ALU 输出
  • Lw 1: 选择数据存储器DM输出

MemtoReg_1
>

  • 0 : MemtoReg
  • Lui 1 : 选择shift输出

ALUSrc
>

  • R型指令 0: 选择寄存器堆的 Read data2 输出
  • Lw 1: 选择Signext的输出
  • Sw 1: 选择Signext的输出
  • Beq 0: 选择Read data2输出

ALUSrc_1
>

  • 0 : ALUSrc
  • Ori 1: 选择zero_ext 输出

ALUOp1 + ALUOp2
>

  • 输入到ALU controller 控制单元

MemRead
>

  • 0:表示DM不可写入
  • 1:表示DM可写入

MemWrite

  • 0:表示DM不可写入
  • 1:表示DM可写入

shiftSrc
>

  • 0: input(shift)选择Rdata2输出,shamt(shift)选择shamt输入
  • 1:input(shift)选择imm16 输出,shamt(shift) 选择0x10输入

指令运算类型选择

指令 Func字段 ALUOp ALU运算类型 ALU Oper
Lw XXXXXX 00 + 000
Sw XXXXXX 00 + 000
Beq XXXXXX 01 >/</= 010
Ori XXXXXX 11 \ \ 011
Add 100000 10 + 000
Sub 100010 10 - 001

指令实现控制信号的转换

  • x表示指令实现与该输入无关
指令 Opcode Branch RegDst RegWrite MemtoReg MemtoReg_1 ALUSrc ALUSrc_1 ALUOp1 ALUOp2 MemRead MemWrite shiftSrc
Add/Sub 000000 0 0 1 0 0 0 0 1 0 0 0 x
Lw 100011 0 1 1 1 0 1 0 0 0 1 0 x
Sw 101011 0 x 0 x x 1 0 0 0 0 1 x
Beq 000100 1 x 0 x x x x 0 1 0 0 x
Ori 001101 0 1 1 0 0 x 1 1 1 0 0 x
Lui 001111 0 1 1 x 1 x x x x 0 0 1
Nop 000000 0 0 1 x 1 x x x x 0 0 0

GRF(寄存器堆)

端口 方向 描述
Clk I 时钟信号
Reset I 复位信号,将寄存器的值全部清零
1: 复位
0:无效
WE I 写使能信号
1: 可写入数据
0: 不可写入数据
Read register1 I 读出地址输入(5位),读出到Read Data1
Read register2 I 读出地址输入(5位),读出到Read Data2
Write register I 写入地址输入(5位)
Write data I 写入数据(32位)
Read Data1 O Read register1地址对应寄存器的输出
Read Data2 O Read register2地址对应寄存器的输出

ALU(算数逻辑单位)

端口 方向 描述
A I 操作数1(32位)
B I 操作数2(32位)
ALU Oper I ALU功能选择(3位)
Zero O 判断操作数1与操作数2是否相等(1位)
Result O 结果输出(32位)

ALU control(ALU控制单元)

端口 方向 描述
ALUOp I 指令类型区分(2位)
Func I 指令[5:0]位
ALU Oper O ALU功能选择(3位)

Add(加法器)

端口 方向 描述
A I 操作数1(32位)
B I 操作数2(32位)
Result O A,B相加结果输出(32位)

Shift left 2(左移两位)

端口 方向 描述
in I 操作数1(32位)
out O in左移两位输出(32位)

IFU (取指令单元)

端口 方向 描述
Clk I 时钟信号
Reset I 指令存储器(ROM)所有地址的存储值清零
1: 复位
0:无效
Branch I PC值分支跳转判断(1位)
Zero I beq指令判断PC是否跳转条件(1位)
immZeExt I 16位立即数无符号扩展输入(32位)
pc O PC当前值(32位)
instruction O PC地址对应IM(指令存储器)的指令输出(32位)

DM(数据存储器)

端口 方向 描述
Clk I 时钟信号
Reset I 数据存储器(RAM)所有地址的存储值清零
1: 复位
0:无效
MemWrite I 写使能信号,
1: 可写入数据
0: 不可写入数据
MemRead I 读使能信号,
1: 可读出数据
0: 不可读出数据
Address I 读写地址(12位)
Writedata I 写入数据(32位)
ReadData O Address地址对应数据储存器(RAM)的储存值输出

shift(移位器)

端口 方向 描述
input I 操作数
shamt I 偏移量
output I 操作数移位后输出

三、数据通路

  • 加粗表示该列存在分支
指令 A B PC IM Adr Reg1 Reg2 Wreg Wdata A B DM Adr DM Wdata Sign-ext A B shift zero-ext
Adder: ALU: Nadder: /
R型指令与访存 PC 4 Adder PC Rs Rt Rd ALU Rdata1 Rdata2 / / / / / /! /
Lw PC 4 Adder PC Rs / Rt DM Rdata1 Sign_ext ALU / imm16 / / / /
Sw PC 4 Adder PC Rs Rt / / Rdata1 Sign_ext ALU Rdata2 imm16 / / / /
Beq PC 4 Adder/Nadder PC Rs Rt / / Rdata1 Rdata2 / / imm16 Adder Sign-imm16(左移2) / /
Ori PC 4 Adder PC Rs / Rt ALU Rdata1 zero_ext / / / / / / imm16
Lui PC 4 Adder PC / / Rt shift / / / / / / / imm16 / /
Nop PC 4 Adder PC / Rt Rd shift / / / / / / / Rdata2 /

四、测试

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
ori $a1, $a0, 456 #$a0与立即数取或存入$a1
ori $a0, $0, -123 #$0与立即数取或存入$a0
ori $a1, $a0, 2147483646 #$a0与立即数取或存入$a1
ori $a0, $0, 2147483647 #$0与立即数取或存入$a0
nop #空操作指令
lui $a2, 0 # 符号位为 0,将立即数存入$a2高位
lui $a2, 1 # 符号位为 0,将立即数存入$a2高位
lui $a2, 20 # 符号位为 0,将立即数存入$a2高位
lui $a2, 43 # 符号位为 0,将立即数存入$a2高位
lui $a3, 65533 # 符号位为 1,将立即数存入$a3高位
lui $a3, 65534 # 符号位为 1,将立即数存入$a3高位
lui $0, 65535 # 符号位为 1,将立即数存入$0高位
ori $a3, $a3, 0xffff # $a3与立即数取或存入$a3
add $s0, $a0, $a2 # 正正 将$a0与$a2相加存入$s0
add $s1, $a0, $a3 # 正负 将$a0与$a2相加存入$s1
add $s2, $a3, $a3 # 负负 将$a3与$a3相加存入$s2
ori $t0, $0, 0x0000 #$0与立即数取或存入$t0
sw $a0, 0($t0) #将sign_extend(0)+$t0对应地址的值存入$a0
sw $a1, 4($t0) #将sign_extend(4)+$t0对应地址的值存入$a1
sw $a2, 8($t0) #将sign_extend(8)+$t0对应地址的值存入$a2
sw $a3, 12($t0) #将sign_extend(12)+$t0对应地址的值存入$a3
sw $s0, 16($t0) #将sign_extend(16)+$t0对应地址的值存入$s0
sw $s1, 20($t0) #将sign_extend(20)+$t0对应地址的值存入$s1
sw $s2, 24($t0) #将sign_extend(24)+$t0对应地址的值存入$s2
lw $0, 0($t0) #将$0的值存入sign_extend(0)+$t0对应地址
lw $a0, 0($t0) #将$a0的值存入sign_extend(0)+$t0对应地址
lw $a1, 12($t0) #将$a1的值存入sign_extend(12)+$t0对应地址
sw $a0, 28($t0) #将sign_extend(28)+$t0对应地址的值存入$a0
sw $a1, 32($t0) #将sign_extend(32)+$t0对应地址的值存入$a1
nop #空操作指令
ori $a0, $0, 1 #$0与立即数取或存入$t0
ori $a1, $0, 2 #$0与立即数取或存入$a1
ori $a2, $0, 1 #$0与立即数取或存入$a2
beq $a0, $a1, loop1 # 不相等 $a0与$a1值进行比较,相等则跳转,反之不跳转
beq $a0, $a2, loop2 # 相等 $a0与$a2值进行比较,相等则跳转,反之不跳转
loop1:sw $a0, 36($t0) #跳转后执行的指令:#将sign_extend(36)+$t0对应地址的值存入$a0
loop2:sw $a1, 40($t0) #跳转后执行的指令:#将sign_extend(40)+$t0对应地址的值存入$a1
ori $a0, $0, 0 #$0与立即数取或存入$a0
  • Mars导出的机械码:
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
v2.0 raw
34040000
348501c8
3c01ffff
3421ff85
00012025
3c017fff
3421fffe
00812825
3c017fff
3421ffff
00012025
00000000
3c060000
3c060001
3c060014
3c06002b
3c07fffd
3c07fffe
3c00ffff
34e7ffff
00868020
00878820
00e79020
34080000
ad040000
ad050004
ad060008
ad07000c
ad100010
ad110014
ad120018
8d000000
8d040000
8d05000c
ad04001c
ad050020
00000000
34040001
34050002
34060001
10850001
10860001
ad040024
ad050028

将上述机械码存入IM(指令储存器),控制时钟信号运行单周期CPU,将Logisim中DM中的内容和MARS中内存中的内容,GRF中的寄存器储存的值与MARS中寄存器储存的值以及Logism的PC值和MARS的PC值进行比对,以此来检测Logisim中的CPU是否运行正确。

五、思考题

Q1

  1. 状态存储:PC寄存器,GRF(通用寄存器组),数据存储器(DM),指令存储器(IM)
  2. 状态转移:ALU(算术逻辑运算单元),Adder(加法器),MUX(多路选择器),Signext(符号扩展器),shift left 2(左移两位)

Q2

  1. 合理。\
    ROM可以完成指令的存入以及程序运行后指令的读出,RAM可以完成程序运行过程中的数据存入和读出。32个register组成一个寄存器堆,可以完成通用寄存器所需的数据临时存储以及读出。
    • 改进意见
    1. ROM和RAM模块的地址访问宽度是24位,若CPU的地址访存范围是超过24位,若使用ROM和RAM,则地址访存空间受到限制。(可以对ROM和RAM进行扩展,扩大地址访存范围)
    2. 使用register作为GRF时,需要将32个寄存器进行合并,扩展成一个通用寄存器组

Q3

  • 设计过Adder模块,ALU模块,GRF模块,EXT模块:
  1. Adder:使用Logisimn内置的Adder
  • 内部设计:
    首先,设计一位半加器(对两个1位二进制数进行相加求和,并向高位进位),再设计一位全加器(对两个1位二进制数进行相加并考虑低位来的进位、求得和并向高位进位),再使用32个1位全加器进行扩展,为降低线路的复杂度,使用组内并行,组间串行的方式32位加法器(8位并行加法器,对上述4个加法器进行串行扩展)
  1. shift(移位器):使用Logisimn内置的Shifter
  • 设置input(输入)和shamt(偏移量)端口,按照shamt对输入进行移位操作,再通过端口output输出。
  1. 移2位:最低两位拼接2位“0”

Q4

  • 因为nop(空操作指令)无需完成任何操作,只需进行PC值的转移(进入下一条指令),而这本身故无需控制信号的控制即可进行,故我们并不需要将nop加人控制信号真值表。

Q5

强度适中,但存在未考虑的情况。

  • 寄存器

    寄存器存入数据时,未考虑数据的边界情况,应分类为0及附近的数,32位数边界附近的数,32位数范围内的一些随机数\
    对于无符号立即数,未考虑无符号立即数的边界情况,应分类为0及附近的数,16位数边界附近的数,16位数范围内的一些随机数\
    未考虑存入寄存器是$0的情况

  • 存取指令

    未考虑地址偏移offset是负数的情况\
    未考虑$base存储值为负数的情况\
    未考虑lw指令的目标寄存器为$0的情况