逐指令数据通路说明(配图版)
本文是单周期 RV32I CPU的配套篇:不再用文字画框图,而是逐类说明每条指令的数据通路走向,并标注对应的数据通路图应放在哪里。请将绘制的图片统一放在本目录 Datapath/ 下,文件名按下方标注命名即可直接渲染。
同 opcode 的指令共享同一套数据通路,区别仅在于 ALU 具体运算(由
funct3/funct7决定)与立即数格式(imm_sel)。因此按 9 类 opcode 组织,每类列出覆盖的全部指令。
公共部分(所有指令共用)

在取指阶段 PC 给出地址从 IMEM 读出 32 位指令;指令字经字段提取得到 opcode / funct3 / funct7 / rs1 / rs2 / rd,其中 opcode/funct3/funct7 送 Control 译码,rs1/rs2 送 RegFile 读端口,rd 作为写回地址。同时 ImmGen 按类型生成符号扩展立即数。执行阶段 ALU 的 A 端由 alu_a_sel 选 rdata1 或 PC,B 端由 alu_src 选 rdata2 或 imm;ALU 输出 alu_result(及 zero 标志)。结果经 WBMUX(wb_sel 选择)写回 RegFile,访存类经 DMEM,下一条 PC 由 pc_next 选择逻辑决定。
1. R-type —— 寄存器-寄存器运算(10 条)
覆盖指令:add sub and or xor sll srl sra slt sltu

数据通路为 RegFile.rdata1 → ALU.A、RegFile.rdata2 → ALU.B(因 alu_src=0,B 端取 rs2)。ALU 运算结果直接经 WBMUX(wb_sel=00)写回 RegFile.rd(reg_write=1)。不经过 DMEM,不改变 PC 流向,PC_next = PC + 4。ALU 运算由 {funct7[5], funct3} 选择:0000 ADD / 1000 SUB / 0111 AND / 0110 OR / 0100 XOR / 0001 SLL / 0101 SRL / 1101 SRA / 0010 SLT / 0011 SLTU。
关键控制信号:reg_write=1, alu_src=0, mem_read=0, mem_write=0, branch=0, jump=0, wb_sel=00, alu_a_sel=0, imm_sel=000,alu_op根据命令取值
2. I-type —— 寄存器-立即数运算(9 条)
覆盖指令:addi andi ori xori slti sltiu slli srli srai

数据通路与 R-type 几乎一致,唯一区别是 ALU.B 由 alu_src=1 改为取 ImmGen 输出的立即数(rdata2 不再参与)。ALU 结果经 WBMUX(wb_sel=00)写回 rd。不访存,PC_next = PC + 4。ALU 运算由 funct3 选择;slli/srli/srai 移位量来自立即数低 5 位,其中 srli 与 srai 再靠 funct7[5] 区分逻辑/算术右移。注意没有 subi,减法用 addi 传负数实现。
关键控制信号:reg_write=1, alu_src=1, mem_read=0, mem_write=0, branch=0, jump=0, wb_sel=00, alu_a_sel=0, imm_sel=000
3. LOAD —— 从存储器加载(5 条)
覆盖指令:lw lh lb lhu lbu

ALU 计算地址(A=rdata1,B=imm,alu_src=1,即 rs1 + imm),地址送 DMEM;DMEM 在 mem_read=1 时输出 rdata。rdata 经 WBMUX(wb_sel=01,选 MEM)写回 RegFile.rd(reg_write=1)。不写存储器,PC_next = PC + 4。读写宽度/符号扩展由 funct3 决定:000 LB(符号) / 001 LH(符号) / 010 LW / 100 LBU(零扩展) / 101 LHU(零扩展)。
关键控制信号:reg_write=1, alu_src=1, mem_read=1, mem_write=0, branch=0, jump=0, wb_sel=01, alu_a_sel=0, imm_sel=000
4. STORE —— 写入存储器(3 条)
覆盖指令:sw sh sb

ALU 计算地址(rs1 + imm,alu_src=1),地址送 DMEM。待写入的数据来自 rs2(RegFile.rdata2),在 mem_write=1 时写入 DMEM。STORE 不写回寄存器(reg_write=0),也不经过 WBMUX 写回。PC_next = PC + 4。宽度由 funct3 决定:000 SB / 001 SH / 010 SW。画图时注意区分:地址用 rs1,数据是 rs2。
关键控制信号:reg_write=0, alu_src=1, mem_read=0, mem_write=1, branch=0, jump=0, wb_sel=—, alu_a_sel=0, imm_sel=001
5. BRANCH —— 条件分支(6 条)
覆盖指令:beq bne blt bge bltu bgeu

ALU 对 rs1/rs2 做比较(alu_src=0,不访存、不写回)。ALU 输出的 zero 或 result[0] 送「分支判断」逻辑,结合 branch=1 与 funct3 得到 branch_taken。下一条 PC 选择:branch_taken ? PC + imm(B型) : PC + 4。BRANCH 既不写寄存器也不访存。ALU 固定执行减/比较:beq/bne → SUB 看 zero;blt/bge → SLT(有符号);bltu/bgeu → SLTU(无符号),由 funct3[2:1] 与 funct3[0] 区分相等/大小比较及是否取反。
关键控制信号:reg_write=0, alu_src=0, mem_read=0, mem_write=0, branch=1, jump=0, wb_sel=—, alu_a_sel=0, imm_sel=010
6. JAL —— 无条件跳转并链接(1 条)
覆盖指令:jal

跳转目标 = PC + imm(J 型立即数),不经过 ALU 做地址运算,直接送「下一条 PC 选择」逻辑(jump=1 → pc_next = PC + imm)。同时 PC + 4 经 WBMUX(wb_sel=10,选 PC+4)写回 RegFile.rd(reg_write=1)作为返回地址。不访存,ALU 在此类指令中可闲置。
关键控制信号:reg_write=1, alu_src=0, mem_read=0, mem_write=0, branch=0, jump=1, wb_sel=10, alu_a_sel=0, imm_sel=100
7. JALR —— 寄存器间接跳转并链接(1 条)
覆盖指令:jalr

文字描述:跳转地址 = rs1 + imm,由 ALU 计算(alu_src=1,A=rdata1,B=imm),结果清最低位([0]=0)后作为 pc_next(jump=1)。同时 PC + 4 经 WBMUX(wb_sel=10)写回 rd(reg_write=1)作为返回地址。最常用形式 jalr x0, 0(x1) 不保存返回地址(rd=x0)。不访存。
关键控制信号:reg_write=1, alu_src=1, mem_read=0, mem_write=0, branch=0, jump=1, wb_sel=10, alu_a_sel=0, imm_sel=000
8. LUI —— 载入高位立即数(1 条)
覆盖指令:lui

U 型立即数(高 20 位,低 12 位清零)直接经 WBMUX(wb_sel=11,选立即数)写回 RegFile.rd(reg_write=1)。不经过 ALU 运算,也不访存,不访存。PC_next = PC + 4。画图时只需把 ImmGen 输出接到 WBMUX 的 imm 输入端即可。
关键控制信号:reg_write=1, alu_src=—, mem_read=0, mem_write=0, branch=0, jump=0, wb_sel=11, alu_a_sel=0, imm_sel=011
9. AUIPC —— 地址无关高位立即数(1 条)
覆盖指令:auipc

文字描述:ALU 的 A 端由 alu_a_sel=1 改为取 PC,B 端由 alu_src=1 取 U 型立即数,执行 ADD 得到 PC + (imm << 12)。结果经 WBMUX(wb_sel=00)写回 RegFile.rd(reg_write=1)。不访存,PC_next = PC + 4。常用于与 jal 配合构造任意 32 位跳转/PC 相对地址。
关键控制信号:reg_write=1, alu_src=1, mem_read=0, mem_write=0, branch=0, jump=0, wb_sel=00, alu_a_sel=1, imm_sel=011
控制信号速查表(9 类汇总,供画图对照)
| opcode | 类型 | reg_write | alu_src | mem_read | mem_write | branch | jump | wb_sel | alu_a_sel | imm_sel |
|---|---|---|---|---|---|---|---|---|---|---|
0110011 |
R-type | 1 | 0 | 0 | 0 | 0 | 0 | 00 | 0 | — |
0010011 |
I-type | 1 | 1 | 0 | 0 | 0 | 0 | 00 | 0 | 000 |
0000011 |
LOAD | 1 | 1 | 1 | 0 | 0 | 0 | 01 | 0 | 000 |
0100011 |
STORE | 0 | 1 | 0 | 1 | 0 | 0 | — | 0 | 001 |
1100011 |
BRANCH | 0 | 0 | 0 | 0 | 1 | 0 | — | 0 | 010 |
1101111 |
JAL | 1 | 0 | 0 | 0 | 0 | 1 | 10 | 0 | 100 |
1100111 |
JALR | 1 | 1 | 0 | 0 | 0 | 1 | 10 | 0 | 000 |
0110111 |
LUI | 1 | — | 0 | 0 | 0 | 0 | 11 | 0 | 011 |
0010111 |
AUIPC | 1 | 1 | 0 | 0 | 0 | 0 | 00 | 1 | 011 |
该表与单周期 RV32I CPU中 Control 模块的译码表完全一致,可作为画图时每个 MUX 选择位的标注依据。