懂点儿底层原理 – 内存专题 | S05 | Bank、Row、Column——内存地址是怎么一步步映射到具体的 Cell 的
金句:把一个地址翻译成一次物理访问,需要经过多少层抽象。理解 Bank 内部结构,是理解 DDR 性能的关键。
1. DRAM 芯片内部结构:Cell 到 Bank 的完整层次
1.1 从一个 Cell 到一整片 Bank
一个 DRAM 芯片(Die)的组织层次:
最小单元:DRAM Cell(1 个 NMOS + 1 个电容)= 1 bit
↓
若干 Cell 组成一行(Row):每行连接同一根 Word Line
↓
若干行组成一个 Subarray(子阵列):
- 典型 256~512 行 × 1024 列
- 有独立的本地 Sense Amplifier(本地放大器)
↓
若干 Subarray 组成一个 Array(阵列)
↓
若干 Array 组成一个 Bank
- 有自己的行解码器(Row Decoder)和列解码器(Column Decoder)
- 可以独立接受 ACT/READ/WRITE/PRE 命令
一个 DDR4 x8 芯片(8Gb 容量)内部结构:
32 个 Array × 每个 Array 内部 256 行 × 1024 列
→ 总计:32 × 256 × 1024 = 8,388,608 个 Cell(8Mb,实际因为多 bank 更大)
→ 加上 Bank 结构、Bank Group(DDR5)、IO 接口 → 完整芯片1.2 Bank 的详细内部结构
一个 Bank 的内部结构(DDR4,简化图):
Row Decoder(行解码器)
│
Word Line 0 ──────┤
Word Line 1 ──────┤
Word Line 2 ──────┤
...
Word Line N ──────┤
│
┌──────────────────────────────────────────────┐
│ Bit Line(位线)纵向穿过 │
│ │
│ Cell[0,0] Cell[0,1] Cell[0,2] ... Cell[0,1023] ← Row 0
│ │ │ │ │
│ Cell[1,0] Cell[1,1] Cell[1,2] ... Cell[1,1023] ← Row 1
│ │ │ │ │
│ Cell[2,0] Cell[2,1] Cell[2,2] ... Cell[2,1023] ← Row 2
│ │ │ │ │
│ ... ... ... ... ← ...
│ │ │ │ │
│ Cell[N,0] Cell[N,1] Cell[N,2] ... Cell[N,1023] ← Row N
│ │
└──────────────────────────────────────────────┘
│
Sense Amplifier(感知放大器,列方向)
│
Column Mux(列多路复用器)
│
IO
每个交叉点(Cell):一根 Word Line + 一根 Bit Line + NMOS + 电容2. Row Buffer:ACT 之后行数据存在哪里
2.1 什么是 Row Buffer
Row Buffer(行缓冲):ACT 命令激活一个 Row 后,该行所有 Cell 的数据
被 Sense Amplifier 读取并保存在 Sense Amplifier 的锁存器里。
这个锁存器就是"Row Buffer"。
Row Buffer 的物理位置:
- 就在 Bank 内部的 Sense Amplifier Array 里
- 一行对应一组 Sense Amplifier(等于该行的列数)
Row Buffer 的作用:
- Row 被激活后,整行数据都在 Sense Amplifier 里
- Column 访问(READ/WRITE)是对 Row Buffer 中的数据操作
- 不需要每次都从 Cell 电容重新读取(Cell 数据在 Sense Amp 中保持)
Row Buffer 的生命周期:
1. ACT:行数据从 Cell 读到 Sense Amplifier(Row Buffer 建立)
2. READ/WRITE:直接从 Row Buffer 读取/写入
3. PRE:Row Buffer 被清空(Sense Amp 断开,Bit Line 恢复预充电电平)
Row Buffer 和 Cell 数据的关系:
- Row 被激活时,Cell 数据被"复制"到 Row Buffer
- Row Buffer 可以多次读取,不需要重新访问 Cell
- Row Buffer 是易失性的(PRE 后消失),Cell 数据需要写回(如果被修改)
- 如果 Row 有"脏"数据(被写过),PRE 时会自动写回 Cell2.2 Row Buffer 命中 vs Row Buffer 未命中
Row Buffer 的状态决定访问延迟:
Row Buffer Hit(行命中,当前行已激活):
→ ACT 已完成,Row 已在 Row Buffer(Sense Amp)中
→ 直接发送 READ/WRITE → Column 访问
→ 延迟 = CL + tCCD × N
Row Buffer Miss(行未命中,需要激活新行):
→ 当前 Row Buffer 不是目标 Row
→ 必须:PRE(关闭当前行) → tRP → ACT(激活新行) → tRCD → READ/WRITE
→ 延迟 = tRP + tRCD + CL + tCCD × N
Row Buffer Conflict(行冲突,同一行的两个不同实例):
→ 两个 Rank 上同一 Row 都被激活
→ 内存控制器需要序列化访问
→ 延迟加倍
Row Buffer 的有效利用:
- 如果应用有良好的行局部性(连续访问同一行),Row Buffer 持续命中
- 如果应用随机访问跨行,Row Buffer 频繁未命中
- 这就是为什么矩阵乘法等顺序访问场景 DDR 性能好3. Sense Amplifier(感知放大器):Cell 数据是怎么被读出来的
3.1 Sense Amplifier 的工作原理
Sense Amplifier(SA,感知放大器)是 DRAM 里最核心的模拟电路:
结构:差分放大器(Cross-Coupled Inverter Pair)
Bit Line(BL) Bit Line Bar(BLB)
│ │
┌┴────────────────────────┴┐
│ │
└────────┬────────┬───────┘
│ │
↑ ↑
Inverter1 Inverter2
│ │
└────────┘
↑↑(正反馈)
工作原理:
1. 预充电:BL 和 BLB 都充电到 1/2 VDD
2. ACT 激活:Cell 电容连接到 BL
→ 如果 Cell 有电荷(存"1"),BL 电压轻微上升
→ 如果 Cell 无电荷(存"0"),BL 电压轻微下降
→ 电压变化幅度:约 100~200mV(非常微弱)
3. Sense Amp 检测 BL 和 BLB 的电压差,放大到 VDD/GND
→ 差分放大器靠正反馈稳定在"1"或"0"
→ 放大过程约 5~10ns
4. 放大完成后,数据被锁存在 Sense Amp(这就是 Row Buffer)
5. 同时,BL/BLB 电压恢复完整电平("刷新"了 Cell 的电荷)
为什么叫"放大器"而不是"比较器":
→ 它把微弱的模拟信号(100~200mV 差分)放大成数字电平(0~VDD)
→ 本质是一个带正反馈的差分放大器
→ 放大过程需要时间(tRCD 的一部分),这是 DRAM 延迟的物理来源3.2 Sense Amplifier 的时序
Sense Amplifier 的关键时序参数:
1. 放大建立时间(Amplifier Settling):
→ ACT 后,Word Line 拉高,Cell 和 BL 连接
→ BL 电压变化,Sense Amp 开始检测
→ 约 4~8ns 后放大完成(达到稳定逻辑电平)
→ 这就是 tRCD 的一部分
2. 放大器复位(SA Reset):
→ PRE 命令后,Sense Amp 需要复位到初始状态
→ BL/BLB 恢复到 1/2 VDD
→ 约 2~3ns(包含在 tRP 内)
3. 读写共用 Sense Amp:
→ 读:Cell → SA → DQ(数据输出)
→ 写:DQ → SA → Cell(数据直接写入 Sense Amp 或 Cell)
→ 读写共用同一组 Sense Amp,节省硬件
Sense Amp 的功耗:
→ 激活一行 = 激活一整行 Sense Amp(1024~8192 个)
→ 每个 SA 消耗约 10~50µA
→ 一行 SA 总功耗约 10~50mA
→ 这就是为什么 DRAM 激活行时有功耗峰值
→ 行命中率高 → 更多激活行 → 更高功耗4. Bank Read 的完整流程
4.1 Bank 读操作的 6 个阶段
一次完整的 Bank Read 操作(DDR4-3200):
阶段 1:ACT(行激活)
- 内存控制器发送 ACT 命令 + Row 地址 + Bank 地址
- Row Decoder 选通对应的 Word Line
- 整行 Cell(1024~8192 个)通过 NMOS 连接到 Bit Line
- Sense Amp 读取并放大整行数据 → 建立 Row Buffer
- 耗时:tRCD = 13.75ns(22 cycles)
阶段 2:等待 Sense Amp 稳定
- Sense Amp 放大 BL 上的微弱电压变化
- 约 4~8ns 稳定到 VDD/GND
- 这是 tRCD 的物理来源(Cell 充放电 + SA 放大)
阶段 3:发送 READ 命令
- Column 地址通过地址引脚发送
- 列解码器在 Row Buffer 中选择目标列
- 延迟:CL = 13.75ns(22 cycles)
阶段 4:数据从 Row Buffer 输出到 IO
- BL = 8(一次 Burst 传输 8 个数据字 = 64 bytes)
- 每个数据字 1 个时钟周期(DDR = 上升沿+下降沿各一次)
- 8 cycles 传输 8 × 8 = 64 bits
- 耗时:4 cycles(DDR 上升沿+下降沿各一次)
阶段 5:PRE(预充电)
- 如果不再访问该行,发送 PRE 关闭行
- Sense Amp 复位,Bit Line 恢复预充电电平
- Row Buffer 清空
- 耗时:tRP = 13.75ns
阶段 6:恢复时间
- tRRD:同一个 Rank 的下一个 ACT 需要等待
- 不同 Rank 可以并行(tRRD_L = 2 cycles)
总延迟(行命中,单次读):
- tRCD + CL + tCCD + tRP ≈ 13.75 + 13.75 + 3.4 + 13.75 = 44.65ns
连续读同一行(行命中,无 PRE):
- tRCD + CL + N×tCCD ≈ 13.75 + 13.75 + N×3.4ns
- 第一次访问:~27.5ns,后续每次 +3.4ns4.2 写操作的 Bank 流程(对比)
Bank Write 操作(DDR4-3200):
阶段 1:ACT(和读相同)
- 发送 ACT 命令 + Row 地址 + Bank 地址
- 打开目标行,建立 Row Buffer
- 耗时:tRCD = 13.75ns
阶段 2:发送 WRITE 命令 + 数据
- Column 地址 + 写数据同时发送(数据立即进入 DQ 引脚)
- 数据写入 Row Buffer(Sense Amp 锁存)
- 延迟:WL = CWL = 11 cycles(6.875ns)
- 数据 Burst 长度:BL = 8
阶段 3:数据从 Row Buffer 写入 Cell
- 这是透明发生的(不需要额外等待)
- Cell 写操作比读慢,需要完整充电到 VDD
阶段 4:PRE(预充电)
- 如果不再访问,PRE 关闭行
- 注意:如果刚写过,Cell 需要充电稳定时间(tWR = 15ns)
- PRE 之前必须等待 tWR
读 vs 写的主要区别:
- 读:数据从 SA → DQ(SA 放大后输出)
- 写:数据从 DQ → SA → Cell(直接写入)
- 读有 CL 延迟(等待数据返回),写有 CWL 延迟(数据到 DQ 的时间)
- 读破坏性(但 SA 有锁存,Row Buffer 不丢失),写后需要 tWR 才能 PRE5. 多 Bank 操作和 Bank 级并行
5.1 多 Bank 流水线的优势
多 Bank 的设计就是为了让不同 Bank 的操作并行:
Bank 0:ACT[Row=0] ── READ ─────────────────────────────── PRE
Bank 1: ACT[Row=1] ── READ ─────────────────────── PRE
Bank 2: ACT[Row=2] ── READ ────────────── PRE
Bank 3: ACT[Row=3] ── READ ──── PRE
时间线:
Cycle 0: Bank0 ACT
Cycle 22: Bank0 READ(tRCD 后),Bank1 ACT(tRRD 后)
Cycle 44: Bank0 数据输出,Bank1 READ,Bank2 ACT
Cycle 66: Bank1 数据输出,Bank2 READ,Bank3 ACT
...
带宽利用率(4 Bank 交错):
- 单 Bank 有效带宽 = 1 / (tRCD + CL + tRP) ≈ 1 / 44ns ≈ 22.7 MT/s
- 4 Bank 交错带宽 ≈ 22.7 × 4 = 90.8 MT/s(峰值)
- 实际 DDR4-3200 带宽 = 3200 MT/s(因为每个 Cycle 传 2 次 = DDR)
Bank 数量的影响:
DDR4 典型:8 个 Bank(含 2 个 Bank Group 的设计)
DDR5 典型:32 个 Bank(更多 Bank → 更少行冲突)
→ 内存控制器可以把多个请求分散到不同 Bank
→ 提高 Row Buffer 命中率(减少行冲突)5.2 Bank Group(DDR5)的并行能力
DDR5 有 2 个 Bank Group,每个 Group 内部有 4 个 Bank(2BG × 4Bank × 4Bank = 32 Bank):
Bank Group 的独特能力:
→ 两个 Bank Group 可以同时执行不同的命令类型
→ 例如:Group 0 正在读(READ),Group 1 同时可以预充电(PRE)
→ 读和预充电并行,延迟重叠
DDR5 Bank Group 并行示例:
Group 0:ACT[Bank0] ── READ ── PRE
Group 1: ACT[Bank4] ── READ ── PRE
↑
Group 0 和 Group 1 的 ACT 可以重叠
PRE 也可以和另一个 Group 的 ACT/READ 重叠
DDR4(无 Bank Group):
→ 两个 Bank 的 ACT 也不能重叠
→ 必须等 tRRD = 4 cycles 才能发下一个 ACT
DDR5 Bank Group 优势:
→ 行冲突的等待时间被 Bank Group 并行隐藏
→ 有效带宽比 DDR4 提升约 15~20%(在相同频率下)6. 内存地址到 Cell 的完整映射
6.1 地址位分配详解
DDR4 系统地址映射(Intel Skylake 例子,32GB = 2 Channel × 16GB/DIMM):
物理地址 PA = 35 bits(对应最大 64GB,但只有 32GB 可用)
Bit 分配:
[34] → Channel Bit(哪个 Channel,0 或 1)
[33] → Rank Bit(哪个 Rank,双面 DIMM 有 2 个 Rank)
[32:31] → Bank Group(DDR4 实际不需要,但有些实现用它做对齐)
[30:28] → Bank(哪个 Bank,3 bits = 8 个 Bank)
[27:15] → Row(哪一行,13 bits = 8192 行)
[14:6] → Column(哪一列,9 bits = 512 列,但只用部分)
[5:0] → Byte offset in Cache Line(64B = 6 bits)
DDR5 地址映射(DDR5-4800,2×32GB):
[35] → Channel(哪个 Channel)
[34] → Rank
[33:32] → Bank Group(2 bits = 4 个 Group,DDR5 有 2 个 BG)
[31:29] → Bank(哪个 Bank,3 bits = 8 个 Bank per Group)
[28:14] → Row(15 bits = 32K 行)
[13:5] → Column(9 bits)
[4:0] → Byte offset(32B aligned,DDR5 BL16 模式)
实际内存控制器地址映射(优化策略):
- 把行地址放在高位(容易触发行冲突)
- 把列地址放在低位(列内访问无切换开销)
- 把 Bank 地址放在行地址之上(减少同一行内的 Bank 冲突)
- 把 Channel/Rank 放在最高位(最大粒度分离)6.2 行列冲突的实际例子
假设访问模式:
场景 1:顺序访问数组(行命中)
for(i=0; i<1024; i++)
a[i]++
地址连续递增:PA → Row 不变,Column 递增
→ 只需一次 ACT,后续全是 Column 访问
→ Row Buffer 持续命中
→ 带宽利用率高
场景 2:随机访问(行冲突)
for(i=0; i<1024; i++)
j = rand() % 1024
a[j]++
地址随机:Row 频繁切换
→ 每次访问:PRE → tRP → ACT → tRCD → READ
→ 延迟 = tRP + tRCD + CL + tCCD ≈ 13.75 + 13.75 + 13.75 + 3.4 ≈ 44.65ns
→ 带宽利用率低
场景 3:结构体数组(Structure of Array,SoA vs AoS)
struct Point { x, y, z } points[1024];
SoA(Structure of Array,x/y/z 分开存):
x[0], x[1], ... x[1023](行命中)
y[0], y[1], ... y[1023](行命中)
z[0], z[1], ... z[1023](行命中)
→ 3 次行激活,每次 1024 次访问,高效
AoS(Array of Structure,x/y/z 交错存):
points[0].x, points[0].y, points[0].z, points[1].x, ...(每次跨行)
→ 每次访问都触发行切换
→ 延迟增加约 3 倍7. 总结
- Bank 内部结构:Cell → Row → Subarray → Array → Bank,Row Decoder + Sense Amplifier + Column Mux + IO
- Row Buffer:ACT 后整行数据保存在 Sense Amplifier 锁存器里,READ/WRITE 直接操作 Row Buffer,不需要每次都访问 Cell
- Sense Amplifier:差分放大器,把 Cell 过来的微弱电压变化(100~200mV)放大到 VDD/GND,是 DRAM 延迟的物理来源(tRCD 的一部分)
- Bank Read 流程:ACT(tRCD)→ READ(CL)→ 数据输出(tCCD)→ PRE(tRP)→ 关闭行
- 多 Bank 并行:8~32 个 Bank 可以流水线化,减少行冲突概率
- DDR5 Bank Group:2 个 Bank Group 可以并行执行读/预充电,隐藏行切换延迟
- 地址映射:PA → Channel → Rank → Bank → Row → Column → Byte offset,具体映射因 CPU 而异
下篇预告(S06):DDR5 相比 DDR4,内存带宽翻倍的秘密是什么?Bank Group、BL16、CAM Downlink、决策反馈均衡(DFE)——DDR5 的架构改革。
关注公众号「AI不着急」,回复”资料”获取内存学习路线图。
评论