计组实验1

单周期CPU

RV32I指令集

lui:

\(x[rd] = sext(immediate[31:12] << 12)\)

auipc:

\(x[rd] = pc + sext(immediate[31:12] << 12)\)

一些csr相关的,在lab2中用到:

csrrw:

csrrw rd,offset,rs1

\(t = CSRs[csr]; CSRs[csr] = x[rs1]; x[rd] = t\)

csrrs:

csrrs rd,offset,rs1

Any bit that is high in rs1 will cause the corresponding bit to be set in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected (though CSRs might have side effects when written).

\(t = CSRs[csr]; CSRs[csr] = t \or x[rs1]; x[rd] = t\)

csrrc:

csrrc rd,offset,rs1

Any bit that is high in rs1 will cause the corresponding bit to be cleared in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected.

\(t = CSRs[csr]; CSRs[csr] = t \land ∼x[rs1]; x[rd] = t\)

取指

  • 取出PC地址的指令
  • 修改PC的值
    • 若跳转,修改为跳转地址
    • 否则改为PC+4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
when(io.instruction_valid) {
io.instruction := io.instruction_read_data
// lab1(InstructionFetch)
io.instruction_address := pc
when(io.jump_flag_id){
pc := io.jump_address_id
}.otherwise{}
pc := pc + 4.U
}
// la1(InstructionFetch) end


}.otherwise{
pc := pc
io.instruction := 0x00000013.U
}
io.instruction_address := pc

译码

控制信号

  • ALUOp1Src: 控制ALU第一个输入为指令地址或寄存器

  • ALUOp2Src: 控制ALU第二个输入为寄存器或立即数,R指令取0

  • MemoryRE: 内存读使能,Load指令取1

  • MemoryWE: 内存写使能,Store指令取1

  • RegWE: 寄存器写使能,R, I, L, auipc, lui, jal, jalr

  • RegWriteSrc: 寄存器写回数据来源,L选择内存,jal, jalr选择指令地址,其他选择ALU计算结果

执行

  • 进行ALU运算
  • 判断是否跳转
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

alu.io.op1 := Mux(
io.aluop1_source === ALUOp1Source.Register,
io.reg1_data,
io.instruction_address
)
alu.io.op2 := Mux(
io.aluop2_source === ALUOp2Source.Immediate,
io.immediate,
io.reg2_data
)

io.if_jump_flag := opcode === Instructions.jal ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (io.reg1_data === io.reg2_data),
InstructionsTypeB.bne -> (io.reg1_data =/= io.reg2_data),
InstructionsTypeB.blt -> (io.reg1_data.asSInt < io.reg2_data.asSInt),
InstructionsTypeB.bge -> (io.reg1_data.asSInt >= io.reg2_data.asSInt),
InstructionsTypeB.bltu -> (io.reg1_data.asUInt < io.reg2_data.asUInt),
InstructionsTypeB.bgeu -> (io.reg1_data.asUInt >= io.reg2_data.asUInt)
)
)
io.if_jump_address := io.immediate + Mux(opcode === Instructions.jalr, io.reg1_data, io.instruction_address)

访存

  • 读内存,判断是lb, lbu, lh, lhu, lw,根据不同指令取不同位数
  • 写内存,根据不同指令取不同位数

写回

没什么好说的。