S01 —— DRAM:一个电容加一个晶体管,是怎么存一个 bit 的

金句:复杂系统背后,往往只有几个简单的物理原理在支撑。理解 DRAM,先从最底层的 Cell 说起。


1. DRAM Cell 的物理结构

1.1 什么是 DRAM

DRAM(Dynamic Random Access Memory)是目前几乎所有通用计算设备的主内存。从手机到服务器,从 PC 到超算,DDR SDRAM 是主存的代名词。

DRAM 的核心特征:

  • 易失性(Volatile):断电后数据丢失
  • 按地址随机访问:任何地址的访问延迟相同(不像 SSD 按块访问)
  • 每个 bit 靠一个电容的充放电存储:密度极高

1.2 一个 DRAM Cell 的电路结构

Bash
一个 DRAM Cell 只由两个元件组成:

         WL(Word Line,字线)
           │
    ───────┤ NMOS T(晶体管,开关)
           │
           ├───┬────────────── BL(Bit Line,位线)
               │
           ────┴─────
              ████    ← 存储电容(Storage Capacitor)
            ─────────    电荷 → 1,无电荷 → 0
               │
            GND

两个端口:
  - WL(Word Line):控制晶体管开/关,由行解码器驱动
  - BL(Bit Line):读取/写入数据的数据线,连接到列放大器

一个 Cell = 1 个 NMOS + 1 个电容

1.3 电容存储电荷的原理

Bash
电容的基本结构:两个导体之间隔着一个绝缘体

         ┌──────────┐
    ────│  Plate A  │──────── 导体(接电路)
         │   ↓↓↓    │
         │  绝缘层   │
         │   ↑↑↑    │
         └──────────┘
    ────│  Plate B  │──────── 导体(接电路)
         └──────────┘

电容存储的电荷量 Q = C × V
  C:电容值(由面积和绝缘层厚度决定)
  V:电压

在 DRAM 中:
  - "存 1":电容充电到 VDD,电荷 Q1
  - "存 0":电容放电到 0V,电荷 Q0

充电 = 写入"1"
放电 = 写入"0"
检测电压变化 = 读取

2. Bit Line 和 Word Line:Cell 是怎么被访问的

2.1 Bit Line(位线)

每个 DRAM Cell 不直接连到放大器,而是通过共享的 Bit Line(BL)连接。

Bash
一个 Bit Line 连接多个 Cell(通常 256~512 个):

              BL(Bit Line,共享)
                 │
    Cell 0 ──┤  ├── Cell 1 ──┤  ├── Cell 2 ──┤  ...
         │              │              │
       WL0            WL1            WL2

    Word Line 控制哪个 Cell 接入 BL
    同一时刻,每个 BL 上只有一个 Cell 接入

BL 的电压由列放大器(Sense Amplifier)检测。

2.2 Word Line(字线)

Word Line 决定哪个 Cell 被选中接入 Bit Line。

Bash
Word Line 的工作原理:

WL=0(未选中):
  → NMOS 截止
  → Cell 与 BL 断开
  → 该 Cell 的电荷保持不变(静态保存)

WL=1(选中):
  → NMOS 导通
  → Cell 的电容与 BL 连通
  → 可以进行读/写操作

行地址解码器(Row Decoder):
  → 接收行地址(Row Address)
  → 选通对应的 Word Line
  → 一次选通一整行(所有 Cell 同时接入 BL)

3. DRAM Array:Bank / Row / Column 的层次结构

3.1 从 Cell 到 Bank

单个 DRAM Cell 太小,无法独立寻址。DRAM 按层次组织:

Bash
DRAM 的组织层次:

Cell → Word Line Group → Subarray → Array → Bank → Channel

Cell:
  - 1 个 bit 的存储单元
  - 1 个 NMOS + 1 个电容

Word Line(字线):
  - 横向排列,控制一整行 Cell 的选通
  - 一次选通 1024~8192 个 Cell

Bit Line(位线):
  - 纵向排列,连接一整列 Cell
  - 每列一个 Bit Line

Subarray(子阵列):
  - 256~512 行 × 512~1024 列
  - 有自己的本地 Sense Amplifier

Array(阵列):
  - 多个 Subarray 并排
  - 共享列解码器

Bank:
  - 多个 Array 组成一个 Bank
  - 有独立的行解码器和列解码器
  - 可以独立接受命令

3.2 Bank 的详细结构

Bash
一个 Bank 的内部结构:

                Column Decoder
                     │
    Row Decoder ───┤├──┬──┬──┬──┬──┐
                   │  │  │  │  │  │
              ┌────┴──┴──┴──┴──┴──┴──┐
              │   Array 0             │
              │  ┌───┐ ┌───┐ ┌───┐  │
              │  │   │ │   │ │   │  │
              │  │ SA│ │ SA│ │ SA│  │  ← Sense Amplifier
              │  │   │ │   │ │   │  │
              │  └───┘ └───┘ └───┘  │
              └─────────────────────┘

Bank 的寻址能力:
  - 行地址(Row Address):选通哪一行 Word Line
  - 列地址(Column Address):在选中行中选择哪些列
  - 一次 Row 激活 → 多列数据可以突发读取

3.3 多 Bank 并行

现代 DRAM 芯片有多个 Bank(通常是 4~8 个),每个 Bank 可以独立工作。

Bash
多 Bank 并行的好处:

Bank 0:读取 Row 0      ← 正在操作
Bank 1:预充电/刷新      ← 可以重叠 Bank 0 的操作
Bank 2:读取 Row 5      ← 可以重叠
Bank 3:idle             ← 等待

Bank 之间的切换延迟(tRRD):
  - 激活一个 Bank 后,需要等待几个周期才能激活另一个 Bank
  - DDR4 tRRD = 4 cycles(最小值)

Bank 并行 → 内存控制器可以流水线化多个请求
→ 提高整体带宽利用率

3.4 内存地址到 Cell 的完整映射

Bash
DDR4 系统(8GB 容量,单通道 64-bit)地址映射示例:

CPU 地址 bit 分配(简化版):

  [Bank Group][Bank][Row][Column][Channel]

  - Bank Group(3 bits):选择 Bank Group(2 个 Bank Group)
  - Bank(3 bits):选择 Bank(8 个 Bank)
  - Row(16 bits):选择 Row(64K 行)
  - Column(10 bits):选择列(1K 列)
  - Channel(64-bit 并行)

  行地址 → Row Decoder → 选通对应 Word Line → 一整行 Cell 接入 BL
  列地址 → Column Decoder → 选通对应列 → 数据通过 IO 传输到 CPU

一次读操作的完整流程:
  1. Row Decoder 根据 Row Address 选通某一行(所有列同时接入 BL)
  2. Sense Amplifier 放大 BL 上的微弱电压变化 → 完整电平
  3. Column Decoder 根据 Column Address 选通特定列
  4. 数据通过 DQ 引脚传输到内存控制器
  5. 如果不需要该行,执行 Precharge 关闭行

4. DDR 协议:从 SDR 到 DDR5 的演进

4.1 为什么需要 DDR

DDR = Double Data Rate,核心思想是在一个时钟周期的上升沿和下降沿都传输数据

Bash
SDR(Single Data Rate)vs DDR 对比:

SDR(SDRAM):
  - 只在时钟上升沿传输数据
  - 1 个时钟周期 = 1 次传输
  - 频率 100MHz → 带宽 100MT/s(百万次传输/秒)

DDR1(DDR-266):
  - 上升沿 + 下降沿都传输
  - 频率 133MHz → 带宽 266MT/s
  - 数据率(Peak Transfer Rate)= 2 × 时钟频率

DDR2(DDR2-800):
  - 内部频率翻倍(2n Prefetch)
  - 时钟 400MHz → 带宽 800MT/s
  - 外部总线频率更高,但数据预取宽度更大

DDR3(DDR3-1600):
  - 内部频率 4n Prefetch
  - 时钟 800MHz → 带宽 1600MT/s

DDR4(DDR4-3200):
  - 内部频率 8n Prefetch
  - 时钟 1600MHz → 带宽 3200MT/s

DDR5(DDR5-6400):
  - 内部频率 16n Prefetch
  - 时钟 3200MHz → 带宽 6400MT/s

4.2 Prefetch(预取)机制

DDR 速度提升的核心不是靠无限提高外部时钟频率(受物理限制),而是靠Prefetch

Bash
Prefetch 原理:

SDR(1n Prefetch):
  - 每个时钟周期传输 1 个数据字(64 bits)
  - 内存阵列频率 = IO 频率

DDR1(2n Prefetch):
  - 每个时钟周期传输 2 个数据字(128 bits)
  - 内存阵列频率 = 1/2 × IO 频率
  → 内存阵列速度不变,但 IO 速度翻倍

DDR2(4n Prefetch):
  - 每个时钟周期传输 4 个数据字(256 bits)
  - 内存阵列频率 = 1/4 × IO 频率
  → 可以用更低的内部阵列频率实现更高的 IO 频率

DDR4(8n Prefetch):
  - 每个时钟周期传输 8 个数据字(512 bits)
  - 内存阵列频率 = 1/8 × IO 频率
  → DDR4-3200 的阵列频率只需要 200MHz

DDR5(16n Prefetch):
  - 每个时钟周期传输 16 个数据字(1024 bits)
  - 进一步降低内部频率要求

为什么 Prefetch 能提速?
  → 内存阵列(电容 + 放大器)的速度远低于 IO 接口速度
  → 一次从阵列读出更多的数据(Prefetch 宽度)
  → 用较低的阵列频率支撑较高的 IO 频率

4.3 DDR 的关键技术参数

Bash
DDR4-3200(CL22)关键时序参数:

tCK(Clock Period):0.625ns(时钟周期,对应 1600MHz)
tCL(CAS Latency):22 个时钟周期(从读命令到数据输出)
tRCD(RAS to CAS Delay):13.75ns(行激活到列读取)
tRP(Row Precharge):13.75ns(行预充电时间)
tRC(Row Cycle):45ns(连续访问同一行的间隔)
tRFC(Refresh Cycle):350ns(刷新一行的时间)

延迟的绝对时间计算:
  tCL = 22 × 0.625ns = 13.75ns
  tRCD = 13.75ns(已经是绝对值,不是周期数)

突发传输(burst length):
  DDR4 标准 BL = 8(一次读命令传输 8 个数据字 = 64 bytes)
  即一个 Cache Line(64B)一次读完

DDR5 新特性:
  - 双通道 per DIMM(每个 DIMM 有两个独立的 40-bit 通道)
  - 更高的 Bank 数量(32 Bank,4 Bank Group)
  - Same Bank Refresh(SBR)允许其他 Bank 继续访问
  - 内部电压从 1.2V 降到 1.1V
  - 眼图测试更严格,信号完整性要求更高

5. 刷新(Refresh):动态 DRAM 的代价

5.1 为什么要刷新

DRAM 的”Dynamic”(动态)来自电容的漏电特性

Bash
电容漏电的物理原因:

  - 绝缘层不是完美的,总有微量隧穿电流
  - 温度越高,漏电越快
  - 60°C 时漏电速度比 25°C 快约 4 倍

电容电压衰减:
  - 存储"1"(充满电)时,电压约 1.2V(VDD)
  - 漏电后,电压缓慢下降
  - 降到阈值(约 0.6V = 1/2 VDD)以下时,无法被 Sense Amplifier 正确判断为"1"
  - 超过阈值 → 数据损坏

数据保持时间(Data Retention Time):
  - 室温下约 64ms
  - 高温下可能只有 16~32ms

结论:
  → 每 64ms(甚至更短)必须把所有行重新读取并写回
  → 这就是"刷新"(Refresh)

5.2 刷新的实现

Bash
刷新操作:

每个 Bank 逐行刷新:
  1. 激活一行(Row)→ 所有 Cell 数据被 Sense Amplifier 读取
  2. 放大后立即写回(Restore)→ 电容重新充电到 VDD
  3. 预充电(Precharge)关闭该行
  4. 移动到下一行

DDR4 刷新规范(JEDEC):
  - 每 64ms 必须刷新所有行(所有 Bank)
  - 以 8192 行为例:64ms / 81927.8μs / 行
  - 刷新频率 ≈ 128KHz(每秒 12.8 万次刷新操作)

刷新时间计算(tRFC):
  - 刷新一行的时间 tRFC ≈ 350ns(DDR4)
  - 刷新 8192 行总时间 = 8192 × 350ns ≈ 2.87ms
  - 占空比 = 2.87ms / 64ms ≈ 4.5%

实际上 DDR4 会用 1x/2x/4x 刷新模式:
  - 1x 刷新:64ms 刷新所有行(标准)
  - 2x 刷新:64ms 刷新所有行两次(高温补偿)
  - 4x 刷新:高温加速刷新,保证数据可靠性

5.3 刷新对性能的影响

Bash
刷新窗口内的带宽损失:

场景:游戏运行时,GPU 持续访问显存
刷新期间:Bank 正在刷新,无法接受新的读写请求

带宽损失示例:
  - DDR4-32008192 行,每行 tRFC = 350ns
  - 刷新占用的时间 = 8192 × 350ns = 2.87ms / 64ms = 4.5%
  - 有效带宽 = 标称带宽 × (1 - 4.5%) ≈ 95.5%

延迟影响:
  - 刷新期间访问请求被挂起
  - tRRD(Bank 到 Bank 延迟)增加
  - 长时间连续刷新导致突发延迟

DDR5 的改进——Same Bank Refresh(SBR):

传统刷新(All Bank Refresh):
  所有 Bank 同时刷新,系统完全暂停

SBR(Same Bank Refresh):
  刷新 Bank N 时,其他 Bank 继续保持访问
  刷新开销降低到 < 0.5%
  游戏/图形渲染时感知延迟大幅减少

5.4 Self-Refresh(自刷新)

当系统空闲时,内存控制器可以让 DRAM 进入自刷新模式

Bash
Self-Refresh 的工作原理:

  - DRAM 内部有自己的刷新计时器
  - 不需要外部控制器发送刷新命令
  - 功耗降到最低(约 1~2mW per Gb)
  - 用于:笔记本待机(S3)、手机待机

功耗对比(DDR4-8Gb,典型值):
  - Active(持续读写):~500mW
  - Idle(开放 Bank):~100mW
  - Precharge Power-Down:~20mW
  - Self-Refresh:~1~2mW

6. 读写操作的时序详解

6.1 完整读操作的时序

Bash
DDR4 读操作的完整时序(行命中 Row Hit):

  阶段 1:Row Activate(行激活)
    tRCD = 13.75ns(行地址到列地址的延迟)
    → WL 拉高,一整行 Cell 接入 BL
    → Sense Amplifier 放大数据

  阶段 2:CAS(列读取)
    tCL = 13.75ns(列地址到数据输出)
    → Column Decoder 选通列
    → 数据从 Sense Amplifier 输出到 IO

  阶段 3:突发传输
    BL = 8(一次传输 8 个数据字)
    每个字 1/2 时钟周期
    持续时间 ≈ 4 × 0.625ns = 2.5ns

  总延迟(行命中)= tRCD + tCL = ~27.5ns

---

行未命中(Row Miss)的场景:

  阶段 1:Row Activate(行激活)     tRCD = 13.75ns
  阶段 2:CAS(列读取)               tCL = 13.75ns
  阶段 3:Precharge(预充电当前行)    tRP = 13.75ns(如果需要)
  阶段 4:新行 Activate(新行激活)    tRCD = 13.75ns(新行)
  阶段 5:CAS(新行读取)             tCL = 13.75ns

  总延迟(行未命中)= tRCD + tCL + tRP + tRCD_new + tCL
                   ≈ 68.75ns(约 110 个 CPU 周期)

这就是为什么内存访问延迟高度依赖行地址的局部性。

6.2 写操作的时序

Bash
DDR4 写操作:

写操作没有 CAS Latency 的概念,因为数据直接写入已激活的行。

基本流程:
  1. Activate Row(激活目标行)
  2. 直接写入 Column(写命令包含列地址和数据)
  3. 数据在几个周期后被写入 Cell

Write Latency(WL):
  - DDR4 写延迟约 12~18 个时钟周期
  - WL = CL - 1(大约)

写后操作:
  - 写操作完成后,数据在 Sense Amplifier 中
  - 需要等待一段时间才能 Precharge
  - tWR(Write Recovery)= 15ns

写穿(Write-Through)vs 写回(Write-Back):
  - DRAM 本身不知道 Cache 的策略
  - DRAM 每次写操作都直接写入 Cell
  - Cache 的写回/写穿是 CPU 内存控制器的策略

7. DRAM 芯片的内部结构:完整视图

Bash
一个 DDR4 x8 芯片(8Gb 容量)的内部结构:

                    ┌─────────────────────────────┐
                    │        Row Decoder          │
                    │  (行地址解码,选通 Word Line) │
                    └────────────┬───────────────┘
                                 │
         ┌───────────┬──────────┴───────────┬────────────┐
         │           │                      │            │
    Array 0      Array 1     ...       Array 15      Array 31
   (256 rows   (256 rows              (256 rows    (256 rows
    × 1024)     × 1024)              × 1024)      × 1024)
         │           │                      │            │
         └───────────┴──────────┬───────────┴────────────┘
                                 │
                    ┌────────────┴───────────────┐
                    │      Sense Amplifier Array   │
                    │  (列放大器,放大 BL 电压变化)  │
                    └────────────┬───────────────┘
                                 │
                    ┌────────────┴───────────────┐
                    │     Column Mux / Decoder    │
                    │  (列选择,多路复用)           │
                    └────────────┬───────────────┘
                                 │
                    ┌────────────┴───────────────┐
                    │         IO / DQ Pins        │
                    │   (数据引脚,8-bit 宽)       │
                    └─────────────────────────────┘

重要参数:
  - 32 个 Array × 256 行 × 1024 列 × 1 bit = 8Gb
  - 每个 Array 有独立的 Sense Amplifier
  - 列多路复用(Column Mux)把 1024 列复用到 128 个 IO
  - 16n Prefetch:一次从所有 Array 读 16 个字(16 × 8 = 128 bits)

总结

  • DRAM Cell:1 个 NMOS + 1 个电容,靠电容电荷存储 bit
  • Bit Line / Word Line:BL 是共享数据总线,WL 控制选通哪个 Cell
  • Bank / Row / Column 层次:Row 由 WL 选通(一整行接入 BL),Column 由列解码器选择
  • DDR 协议:通过 Prefetch(2n/4n/8n/16n)在内部低频下实现高频 IO
  • 刷新:电容漏电,每 64ms 必须刷新所有行,约 4% 带宽损失,DDR5 SBR 降至 <0.5%
  • 读写时序:行命中 ~30ns,行未命中 ~70ns,局部性是性能关键

下篇预告(S02):SRAM 为什么不需要刷新?SRAM 的 6 个晶体管是怎么互相”锁死”数据的?SRAM 和 DRAM 的全面对比。


关注公众号「AI不着急」,回复”资料”获取内存学习路线图。

最后修改: 2024年3月20日

作者

评论

发表评论

您的邮箱地址不会被公开。