Featured image of post RV32I 单周期数据通路

RV32I 单周期数据通路

逐条说明 RV32I 每条指令在单周期 CPU 中的数据通路,并标注对应数据通路图的位置,供自行绘制。

逐指令数据通路说明(配图版)

本文是单周期 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

R-type 数据通路(红色部分)

数据通路为 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

I-type 数据通路

数据通路与 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

LOAD 数据通路

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

STORE 数据通路

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

BRANCH 数据通路

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

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

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

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

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 选择位的标注依据。

使用 Hugo 构建
主题 Stack 由 Jimmy 设计