P4 设计文档

CPU 设计文档 ### 支持指令

add, sub, ori, lui, lw, sw, beq,bne, j, jr, jal, sll, nop

(其中 add,sub 为无符号加减法)

Instuction
add GPR[rd] = GPR[rs] + GPR[rt]
sub GPR[rd] = GPR[rs] - GPR[rt]
ori GPR[rt] = GPR[rs] | ZeroExt(Imm)
lui GPR[rt] = {imm, 16’b0}
lw R[rt] = Mem[GPR[rs]+sign_ext(offset)]
sw Mem[GPR[rs]+sign_ext(offset)] = R[rt]
beq if (GPR[rs] == GPR[rt]) PC = PC + 4 + BranchAddr
j PC = JumpAddr
jal PC = JumpAddr; GPR[31] = PC + 4
jr PC = GPR[rs]
sll GPR[rd] = {GPR[rt] [31-s:0] , s{0}}
bne if (GPR[rs] != GPR[rt]) PC = PC + 4 + BranchAddr

数据通路

image-20230311000307141

使用模块

一、IFU(Instruction Fetch Unit)

  • 包括 PC 和 IM
  • 容量为 16KiB(4096 × 32bit): reg [31:0] IM [0:4095]
  • 注意起始地址为 0x00003000,address 应为 PC-0x00003000,后再取 [13:2] 位,在 IM 堆中对应地址
端口名 输入 / 输出 位宽 功能
clk in 1 时钟信号
reset in 1 同步复位
PCSrc in 1 下一指令地址选择信号
Jump in 1 跳转控制信号
shiftResult in [31:0] 偏移后的指令地址
jumpAdd in [31:0] 直接跳转的指令地址
PC out [31:0] 输出当前地址
D out [31:0] 输出读取指令

二、GRF(General Register File)

  • 存储 $0~$31 这 32 个寄存器数据:reg [31:0] GRF [31:0]
  • 具有 同步复位,读、写功能
  • $0 寄存器输入为常数 0(如果 WA==0,不写)
端口名 输入 / 输出 位宽 功能
clk in 1 时钟信号
reset in 1 同步复位
WE(RegWrite) in 1 写入使能信号
A1(GRF_A1) in [4:0] 输出数据到 RD1 的寄存器的地址
A2(GRF_A2) in [4:0] 输出数据到 RD2 的寄存器的地址
WA(GRF_WA) in [4:0] 输入到寄存器的地址
WD((GRF_WD) in [31:0] 写入的数据
RD1(GRF_RD1) out [31:0] RD1 输出的数据
RD2(GRF_RD2) out [31:0] RD2 输出的数据

三、ALU(Arithmetic & logical Unit)

  • 提供 32 位加、减、或运算、高 16 位赋 0 以及大小比较功能

  • 加减法按无符号处理

端口名 输入 / 输出 位宽 功能
op in [2:0] ALU 功能控制信号 000:加;001;减;010:或;011:高 16 位赋 0
A(ALU_A) in [31:0] 输入 1
B(ALU_B) in [31:0] 输入 2
Y((ALU_Y) out [31:0] 输出
Greater out 1 A>B
Equal out 1 A=B
Less out 1 A<B

四、DM(Data Memory)

  • 容量为 16KiB(4096 × 32bit): reg [31:0] DM [0:4095]
  • 具有 同步复位,读、写功能,复位地址为 0x00000000
端口名 输入 / 输出 位宽 功能
clk in 1 时钟信号
reset in 1 同步复位
WE(MemWrite) in 1 写控制信号
A(DM_A) in [4:0] 要读 / 写的存储器的地址
WD(DM_WD) in [31:0] 写入的数据
RD(DM_RD) out [31:0] 读出的数据

五、EXT(Bit Extender)

  • 将 16 位偏移量 / 立即数拓展至 32 位
端口名 输入 / 输出 位宽 功能
EXTSelect in 1 选择符号拓展 / 无符号拓展(0/1)
in(EXT_in) in [15:0] 16 位输入
out(EXT_out) out [31:0] 拓展后 32 位输出

六、CU(Control Unit)

  • 生成所有控制信号的组合逻辑
  • 根据每条指令的数据通路列出如下控制信号表格
  • R 指令控制信号为(R==0)
  • 分别根据 Opcode 和 Funct 每一位和与门控制非 R 和 R 型指令的选择
  • 再将指令信号通过或连接,表示某一控制信号被哪些指令选择
Instuction Opcode(in) Funct (in) RegWrite GRF_WASrc GRF_WDSrc ALUSrc ALUSelect MemWrite EXTSelect Branch BranchSelect Jump Jr
add 000000 100000 1 001
sub 000000 100010 1 001 001
ori 001101 1 1 010 1
lui 001111 1 1 011 1
sw 101011 1 1
lw 100011 1 001 1
beq 000100 0 1 000
j 000010 1
jal 000011 1 010 010 1
jr 000000 001000 000 1 1
sll 000000 000000 1 001 011
bne 000101 1 001

logisim 图示

image-20221107194455075

测试

注:自造指令的同时借助 zby 同学的自动化测试工具大范围覆盖,以下仅放出自造指令,以及自动化测试结果截图。

asm 指令

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
ori $1,11
ori $2,22
ori $3,33
lui $4,12
lui $5,23
lui $6,24
lui $7,25
lui $8,34
lui $9,12
addu $10,$9,$9
addu $11,$2,$3
addu $12,$5,$6
subu $13,$3,$5
subu $14,$5,$4
subu $15,$2,$6
nop
lui $16,12
beq $9,$16, next
nop
lui $1,1
lui $2,1
lui $3,1
lui $4,1
a:
lui $5,1
lui $6,1
lui $7,1
lui $8,1
lui $9,1
lui $10,1
next:
beq $1,$2, a
sw $1,0($0)
sw $2,4($0)
sw $3,8($0)
sw $4,12($0)
sw $5,16($0)
sw $6,20($0)
sw $7,24($0)
lw $17,0($0)
lw $18,4($0)
jal out
lw $19, 8($0)
jal end
out:
lw $0,0($0)
jr $31
end:
subu $3,$3,$0
subu $31,$0, $31

机器码

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
34040100
34850123
3c0601c8
3c07ffff
34e7ffff
00868021
00878821
00e7a021
00869023
00879823
ac040000
ac050004
ac060008
ac07000c
ac100010
ac110014
ac120018
ac13002c
ac140030
8c040000
8c05000c
ac04001c
ac050020
34040001
34050002
34060001
10850001
10860001
ad040024
ad050028
0c000c23
0c000c23
ad150040
34a50004
0c000c27
ad050038
ad1f003c
36b50005
03e00008
ad050044
ad1f0048

输出(文本比较)

image-20221104233120667

左侧为 zby 测评机自 mars 导出的输出,右侧为 verilog 中的输出(0 号寄存器写入输出可有可无)

思考题

    • DM 地址来为 GPR[rs]+sign_ext(offset),来自 EXT 对寄存器中地址 rs 寄存器的值符号拓展的输出
    • 为 [11:2] 以对应从 DM 地址 32 位中截取的 [11:2] 位,截去低 2 位,从字节为单位的 PC 对应到以 32bit 为单位的 DM
  1. assembly // 指令对应的控制信号如何取值 always @(*) begin if(add) begin assign RegWrite=1; assign RegDst=1; end else if(sub) begin assign RegWrite=1; assign RegDst=1; assign ALUControl=3'b001; end end // 控制信号每种取值所对应的指令 assign RegWrite=(add||sub||ori||lw||lui||jal); assign RegDst=(add||sub); assign ALUSrc=(ori||lw||sw||lui); assign Branch=(beq); assign MemWrite=(sw); assign MemToReg=(lw); assign EXTSelect=(ori||lui); assign Jump=(j||jal||jr); assign ALUControl=sub?3'b001: ori?3'b010: lui?3'b011: 3'b000; assign Jal=(jal); assign Jr=(jr);

    第一种方法优点在于添加新指令,修改更加集中,不会遗漏控制信号;缺点为当指令种类过多时,篇幅过长。

    第二种方法优点为控制条件更加集中,可读性更强,如 ALU 信号含义更明确,不会错误对应;缺点为增加新指令时需修改多处。

  2. 信号优先级:

    • 同步复位:clk>reset

    • 异步复位:reset>clk

  3. add,addi 具有溢出检测,如果溢出,则不讲加法运算结果写入寄存器。但此结果截断低 32 位后与 addu,addiu 的运算结果相同。此时如果忽略溢出信号,照常写入,则写入值相同,即 add 与 addu,addi 与 addiu 等价