2.3 SLC/MLC/TLC——越多越不靠谱
一个晶体管能装几个比特
上一节我们讨论了 NOR 和 NAND 两种架构——那是在问:几十亿个晶体管在硅片上怎么连线。现在回到一个更基本的物理问题:单个浮栅晶体管到底能存几个比特?
前面讲浮栅晶体管读写原理时,我们默认了最朴素的方式:浮栅里有电子 = “0”,没电子 = “1”。一个单元只区分两种状态。这叫 SLC(Single-Level Cell,单层单元)。
但工程师们不满足于此。他们问:如果我不只判断“有没有电子“,而是精确控制电子数量——让浮栅里的电子量分成 4 个等级、8 个等级、甚至 16 个等级——不就能在一个晶体管里存更多比特吗?
这就是 MLC(Multi-Level Cell,多层单元,2 bit/cell)、TLC(Triple-Level Cell,三层单元,3 bit/cell)、QLC(Quad-Level Cell,四层单元,4 bit/cell)的逻辑。
但物理不是免费的。每多一个比特,你就在用更小的电压窗口承载同样的逻辑信息。让我们看实际的测量数据。
芯片测试设备会对每一个存储单元做一件事:反复编程、读取、擦除,然后画出一条曲线——阈值电压分布曲线。
横轴是电压(0到3.3V),纵轴是这个电压下读到的单元数量。对于一颗 SLC 芯片,你看到的曲线是这样的:
SLC 阈值电压分布
=======================
单元数量
↑
│
│ ┌──────┐ ┌──────┐
│ │ │ │ │
│ │ 1 │ │ 0 │
│ │(擦除态) │(编程态)
│ │ │ │ │
│ └──────┘ └──────┘
└──────────────────────────────────────────────→ 电压
0V 1.0V 2.0V 3.3V
←────────── 参考电压 ──────────→
~1.5V
你知道这意味着什么吗?
这颗SLC芯片的存储单元只有两个状态。“1”(擦除态)的分布峰值大约在1.0V左右,“0”(编程态)的分布峰值大约在2.5V左右。中间的参考电压定在大约1.5V。读的时候,电压低于1.5V的判为“1“,高于1.5V的判为“0“。
两个分布之间,有一大片开阔地。这片开阔地叫做感测裕度(sensing margin)。在这个SLC的例子里,感测裕度大约是1.0V。这意味着即使擦除态的电子泄漏了一些、阈值电压飘移了0.3V,它仍然稳稳地在“1“的区间里,不会被误判为“0“。
这就是SLC可靠性的根基:足够的容错空间。
现在,测试机切换到一颗MLC芯片。你看到的曲线变了:
MLC 阈值电压分布
=======================
单元数量
↑
│
│ ┌──┐ ┌──┐ ┌──┐ ┌──┐
│ │ │ │ │ │ │ │ │
│ │11│ │10│ │00│ │01│
│ │ │ │ │ │ │ │ │
│ └──┘ └──┘ └──┘ └──┘
└────────────────────────────────────→ 电压
0V 1.0V 1.8V 2.3V 3.3V
←─→ ←─→ ←─→
感测裕度 ~0.3V
四个状态:11、10、00、01。不是简单的二进制顺序——你注意到编码是格雷码(Gray Code),相邻状态之间只变化一位。这是故意的:如果一个单元从“10“误读为“00“,只有一位出错,ECC纠错码可以纠正。
四个状态挤在同样的3.3V电压范围内。每个状态之间的感测裕度从SLC的1.0V骤降到大约0.3V。仅仅多存了一个bit,容错空间被压缩了70%。
你继续按按钮,测试机切到TLC模式:
TLC 阈值电压分布
=======================
单元数量
↑
│
│ ┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐
│ │││││││││││││││││
│ │││││││││││││││││ 8个状态,密密麻麻
│ └┘└┘└┘└┘└┘└┘└┘└┘
└────────────────────────────────────→ 电压
0V 3.3V
←──────── 感测裕度 ~0.15V ────────→
八个状态。感测裕度进一步压缩到大约0.15V。八个分布之间的边界,肉眼几乎分不清了。但测试机的ADC(模数转换器)还必须分清——它需要足够高的精度(至少8位ADC),才能可靠地区分这8个电平。
如果再切到QLC——16个状态——感测裕度大约0.08V,不到SLC的十分之一。
你现在明白你的工作有多难了吗?
0.2V能干什么?
让我们把这个感测裕度的问题具象化。
一颗3.3V供电的NAND Flash芯片,内部有一个电荷泵(Charge Pump)电路,能把3.3V升压到大约20V,用于编程和擦除操作。但读取的时候,它只在3.3V范围内工作。
对于QLC来说,16个状态均匀分布在3.3V的电压窗口里,每个状态分到的“领地“是:
3.3V ÷ 16 = 约0.206V
每个状态只有0.2V的空间。 而且这还不是全部——你还得留出分布之间的间隙(guard band),防止两个相邻状态的尾巴重叠。实际的可用窗口更小。
0.2V是什么概念?
你手机充电器输出的5V,波动范围大约是±0.25V——这已经是相当稳定的电源了。但Flash内部的电荷泵、参考电压电路、读出放大器(Sense Amplifier),它们必须在这个量级的电压上,精确地判断一个浮栅晶体管里几十个电子的去留。
这里有一件事必须讲清楚:Flash存储单元不是数字器件,它是模拟器件。
你写代码的时候,write(fd, "A", 1) 看起来是一个数字操作——你写了一个确定的字节。但在物理层,编程电路在做的事情是:向浮栅注入一串精确控制的电压脉冲,每打完一个脉冲就读取一次阈值电压,和目标阈值比较,不够再加一个脉冲,够了就停。
这个技术叫增量步进脉冲编程(ISPP,Incremental Step Pulse Programming)。它的核心是一串反复迭代:
ISPP 算法伪代码
=======================
target_vth = lookup_table[data_value] // 查表:这个数据对应的目标阈值电压
current_vth = sense(cell) // 读取当前阈值电压
pulse_voltage = V_START // 从起始电压开始
while current_vth < target_vth:
apply_program_pulse(pulse_voltage) // 打一个编程脉冲
current_vth = sense(cell) // 读回当前状态
pulse_voltage += V_STEP // 步进增加脉冲电压
if pulse_count > MAX_PULSES: // 超过最大脉冲数,这个单元可能坏了
mark_bad_block()
break
对于SLC,只有两个目标电压,脉冲可以大步前进——可能5到10个脉冲就完成编程。对于TLC,有8个精细的目标电压,每个脉冲的步长必须极小(可能0.1V的步进),需要几十个甚至上百个脉冲才能精确命中目标。
这也是为什么TLC的写入速度比SLC慢3到5倍。 不是因为物理速度慢了,而是因为编程算法需要更多的精细操作来抵达准确的目标。
电子逃亡记
现在我们来聊更可怕的事:电子不会永远待在浮栅里。
Flash存储单元的结构像一个微型的电容器。浮栅(Floating Gate)被一层大约8-10纳米厚的二氧化硅(SiO₂)隧道氧化层包裹着。编程的时候,你用Fowler-Nordheim隧穿效应(在氧化层两端加一个强电场,电子直接“穿墙“进入浮栅),把电子赶进了这个微型牢笼。
但量子力学告诉我们:没有任何墙是绝对不透的。
电子泄漏模型(简化)
=======================
控制栅 (Control Gate)
════════════════════════
║ ONO介质层 ║
╠══════════════════════╣
║ ██ 浮栅 ██ ║ ← 电子被关在这里
║ ██████████ ║ 但它们在慢慢逃逸
╠══════════════════════╣
║ 隧道氧化层 ~10nm ║ ← 最薄弱的环节
╠══════════════════════╣
║ 沟道 (Channel) ║
════════════════════════
源极 (Source) 漏极 (Drain)
电子逃逸速率 ∝ e^(-tox) ← tox = 氧化层厚度
↑
氧化层越薄,逃逸越快。
10nm不是一个巧合——它是工艺和物理的妥协。
太厚了编程需要太高电压,太薄了电子全跑了。
电子逃逸的数学模型大致遵循阿伦尼乌斯方程(Arrhenius Equation):
逃逸速率 = A × e^(-Ea / kT)
其中:
Ea = 激活能(约1.1eV,与氧化层质量和陷阱密度有关)
k = 玻尔兹曼常数
T = 绝对温度(开尔文)
注意那个T在指数的分母里。温度越高,逃逸越快。
对于SLC来说,这个问题不算致命。假设SLC的“1“状态阈值电压大约1.0V,“0“状态大约2.5V,参考电压1.5V。即使浮栅泄漏了0.4V的电荷量,“1“可能在读出来时变成了1.4V——但仍低于1.5V的参考线,依然判为“1”。没有问题。
对于TLC来说——感测裕度只有0.15V。泄漏0.1V,你已经跨过了边界。
泄漏对不同cell类型的影响
=======================
SLC:
┌──────────────┐ ┌──────────────┐
│ "1" 状态 │ ←─0.4V─→ │ "0" 状态 │
│ (0.5~1.5V) │ 安全余量 │ (1.5~3.0V) │
└──────────────┘ └──────────────┘
↑
参考电压=1.5V
泄漏0.4V后:1.0V→1.4V,仍然判为"1" ✓ 安全
TLC:
┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐┌──────┐
│状态0 ││状态1 ││状态2 ││状态3 ││状态4 ││状态5 ││状态6 ││状态7 │
└──────┘└──────┘└──────┘└──────┘└──────┘└──────┘└──────┘└──────┘
←─0.15V→
泄漏0.1V后:状态3的单元可能被误读为状态4 ✗ 比特错误!
这就是核心矛盾:每个单元存的bit越多,单个状态的电压窗口越小,对电荷泄漏的容忍度就越低。 你要么接受更短的保存时间,要么想办法纠错。
ECC:那个帮你擦屁股的数学
所谓“想办法纠错“,就是纠错码(ECC,Error Correction Code)。
TLC和QLC能做到商用,靠的不是物理上减少电荷泄漏——物理上我们已经撞到量子隧穿的墙了——而是靠数学。在数据写进去之前,先附加上冗余信息;读出来的时候,用这些冗余信息来检测和纠正错误。
SLC产品通常只需要简单的1-bit纠错(汉明码)。MLC需要BCH码(Bose-Chaudhuri-Hocquenghem),可以纠正每个码字中的多个bit错误。TLC和QLC则需要LDPC(低密度奇偶校验码,Low-Density Parity-Check)——一种软判决解码算法,它不只是看“0还是1“,而是读出“这一位有多大可能是0,多大可能是1“,然后通过迭代概率推断来纠错。
Flash 纠错技术演进
=======================
SLC (2 states)
│
├── ECC需求:1-bit 纠错/512B
│ 技术:汉明码 (Hamming Code)
│ 开销:~13 bit/512B (~0.3%)
│
MLC (4 states)
│
├── ECC需求:4~8 bit 纠错/512B
│ 技术:BCH码 (Bose-Chaudhuri-Hocquenghem)
│ 开销:~60 bit/512B (~1.5%)
│
TLC (8 states)
│
├── ECC需求:40+ bit 纠错/1KB
│ 技术:LDPC (Low-Density Parity-Check)
│ 开销:~10% 的存储空间
│
QLC (16 states)
│
├── ECC需求:100+ bit 纠错/2KB
│ 技术:LDPC + 多次重读 + 机器学习校准
│ 开销:~15%~20% 的存储空间
│
PLC (32 states) ← 实验室阶段
│
└── 业界正在尝试,但目前良率极低。
即使做成,写入速度可能慢到令人绝望。
ECC的开销不是免费的。BCH码占用大约1.5%的额外存储空间,LDPC码占用10%甚至更多。这意味着你买的1TB TLC SSD,实际上有大约1.1TB的原始NAND容量,其中100GB被ECC和坏块管理消耗掉了。
而且ECC不是万能的。LDPC软判决解码需要多次读取同一个单元(用不同的参考电压),读出多个样本,然后做概率推断。这个过程叫做read retry(读重试)。在消费级SSD上,你可能感觉不到——因为控制器在后台悄悄做了这一切,只用了微秒级的时间。但如果出错太多,LDPC也救不了,控制器会标记这个块为坏块,把数据迁移走,再也不用了。
这就是你在买“便宜的TLC SSD“时正在购买的东西:不是更好的物理介质,而是更聪明的数学。
85°C的温度实验
2020年,一份来自某头部NAND厂商的可靠性白皮书披露了这样一组数据:
在室温(25°C)下,一块全新的TLC NAND Flash在经历3000次P/E循环后,数据保存时间(data retention)大约为1年。但注意——这是冷断电存储条件下的数据。芯片在未通电状态下,浮栅里的电子只能靠那10纳米氧化层挡着。
现在把温度升高到85°C——这是汽车ECU在引擎舱里的常见工作温度。
同样的芯片,在同样的3000次P/E循环后,数据保存时间从1年骤降到不到1个月。
到125°C——这是某些极端工业应用和汽车级的高温认证温度——保存时间可能降到几天。
温度对数据保持时间的影响(TLC NAND,典型值)
=======================
工作温度 P/E=0 (全新) P/E=3000 (寿命中期) P/E=5000 (寿命末期)
─────────────────────────────────────────────────────────────
25°C 10 年 1 年 3 个月
55°C 3 年 3 个月 2 周
85°C 1 年 1 个月 3 天
125°C 3 个月 1 周 1 天
注:以上为数量级估算,具体数值因厂商和工艺节点而异。
但趋势是确定的:温度每升高10°C,保存时间大约减半(阿伦尼乌斯定律)。
这回答了为什么你车载导航仪的SD卡在夏天暴晒后会莫名其妙地丢数据。也回答了为什么汽车行业几乎全面拒绝TLC/QLC NAND作为ECU的主要存储介质。
温度:物理的加速器
85°C 实验的数据说明了一切:温度每升高 10°C,数据保存时间大约减半(阿伦尼乌斯定律的直接推论)。对于 SLC——感测裕度 1.0V——一块芯片在 125°C 下仍能保持数据数年。对于 TLC——感测裕度只有 0.15V——同样温度下数据可能在几天内就开始出错。
这不是工程偏好的问题。这是物理的必然结论:每多一个比特,温度就把你推向熵增的速度加快一档。 当数据损坏的后果是刹车失灵而不是照片丢失时,你只能选择感测裕度最大的那条路。
这也就是为什么汽车 ECU 几乎全部使用 SLC NOR——不是因为 NOR 的架构更可靠(架构优势是 2.2 的话题),而是因为 SLC 的感测裕度能扛住引擎舱的 125°C。
读干扰:你不写,也会破坏数据
还有一个容易被忽略的问题:读干扰(Read Disturb)。
你可能会想:我只读不写,数据总不会坏吧?
不。
当你读取一个Flash存储单元时,你需要在控制栅上加一个读取电压(通常大约5V),在源极和漏极之间检测电流。这个读取电压虽然远低于编程电压(~20V),但它确实会影响同一个字线(word line)上的其他单元。
在NAND Flash中,一个块(block)内的所有单元共享字线和位线。读一个页的时候,同一字线上的其他页也会感受到这个读取电压。反复读取——比如你的行车记录仪反复回放视频文件——会导致那些“只是被读取“的单元慢慢被软编程(soft program),阈值电压轻微上移。
NAND 读干扰机制
=======================
位线0 位线1 位线2 ... 位线N
│ │ │ │
─────┼────────┼────────┼─────────────┼── 字线0(选中,加读电压~5V)
│ │ │ │
─────┼────────┼────────┼─────────────┼── 字线1(未选中,但也感受到电场)
│ ↑受干扰 ↑受干扰 ↑受干扰 │
─────┼────────┼────────┼─────────────┼── 字线2(同上)
│ │ │ │
反复读字线0上的不同位线
↓
字线1、字线2上所有单元
阈值电压缓慢上移
↓
擦除态("1")的单元
电压升高,跨过参考线
被误读为编程态("0")
↓
读干扰引起的比特错误
NOR Flash在读干扰方面比NAND好得多。原因有三:一是NOR的读取电压更低(~3-5V vs NAND的~5-6V);二是NOR的单元结构不会像NAND串联链那样累积“软编程”效应;三是NOR做XIP时读操作分散在不同地址,而NAND读同一页会反复干扰共享同一字线的邻居单元。这也是汽车偏爱NOR的又一个原因——ECU的大部分操作是读固件代码(XIP,Execute-In-Place),读操作占比极高,对读干扰的抵抗力至关重要。
图书馆
在告别这一节之前,我想给你一个隐喻——一个你永远忘不掉的隐喻。
想象你在编排一面书架:
SLC = 厚木板书架。 每层书架,要么满满地放着书(“1”),要么空着(“0”)。你隔老远就能看清:这格有书,那格没书。不需要尺子,不需要精密仪器,肉眼足够。如果有人偷偷抽走半本书,你根本看不出来——因为书足够厚,抽走半本剩下半本依然是“有书“。这就是SLC:两种状态,极大裕度,肉眼可辨。
MLC = 薄板书架。 每层书架有四种状态:满架、半架、三本、空架。你需要走近一些才能区分。光线暗一点,半架看起来可能像三本。你需要一把尺子。感测裕度不是多余的——它是你在模糊现实中的判断依据。
TLC = 纸板书架。 每层书架有八种可能的书脊厚度。你无法用肉眼区分——你需要一台游标卡尺。你不只是在判断“有没有书“,你是在测量“书脊有多厚“。而且纸板会随着时间流逝慢慢受潮变软(电荷泄漏),你可能今天测得它是3.5mm,三个月后变成3.1mm,而3.0mm是边界。你已经不是在“存书“了,你是在做精密测量。
QLC = 你还想往上叠? 每层书架有十六种书脊厚度。你的卡尺必须是实验室级别。每一次测量都伴随着不可避免的误差。而且书架还在不停地受潮变形,变形的速度取决于温度、湿度、上一次你调整它的时间……你管的不是书架,是一座物理测量实验室。
SLC: [▓▓▓▓▓▓▓▓▓▓] [ ] ← 二值判断,谁都能做
MLC: [▓▓▓▓▓▓▓▓▓▓] [▓▓▓▓▓ ] [▓▓ ] [ ] ← 需要目测
TLC: [▓▓▓▓▓▓▓▓▓▓] [▓▓▓▓▓▓▓ ] [▓▓▓▓▓ ] [▓▓▓▓ ] [▓▓▓ ] [▓▓ ] [▓ ] [ ]
← 需要卡尺 →
QLC: [████████████][███████████][██████████][█████████][████████][███████][██████][█████][████][███][██][█][ ]
← 需要干涉仪 →
你明白了核心命题吗?
每增加一个bit,你就在用一个更易碎的物理现实来承载同样的逻辑信息。 你可以用数学(ECC)来修补物理,但数学也是有限度的。香农定理不是建议,是物理定律。
如果有一天,有人告诉你,“我们做出了八层单元(OLC),每单元存8个bit”——你不需要去读白皮书。你只需要问他一个问题:
“感测裕度是多少?”
如果他支支吾吾,答案就是:“已经低于热噪声水平了。”
PLC和3D NAND:物理极限上的舞蹈
说到这里,你可能会问:既然QLC已经把16个状态塞得满满当当,感测裕度只剩0.08V,为什么业界还在推进PLC(Penta-Level Cell,五层单元,32个状态)?
答案是:他们不在同一个维度上解决问题。
传统的平面NAND(2D NAND)到大约15nm制程节点就走不下去了——光刻精度逼近了量子极限,单元之间的串扰(cell-to-cell interference)大到无法忽略。一个单元的编程状态变化,会通过寄生电容耦合影响到相邻单元,造成“邻居干扰“。这就像一排人挤在窄巷子里,任何一个人动一下,他两边的人都会感受到。
于是业界转向了3D NAND——把存储单元从平面排列变成了垂直堆叠,像盖摩天大楼一样一层一层往上盖。
2D NAND → 3D NAND 的维度跃升
=======================
2D NAND (平面):
┌──┬──┬──┬──┬──┐ ← 所有单元在同一平面
│ │ │ │ │ │ 随着制程缩小,单元间距越来越小
├──┼──┼──┼──┼──┤ 串扰加剧,感测裕度恶化
│ │ │ │ │ │
└──┴──┴──┴──┴──┘
3D NAND (垂直):
↑
┌───┴───┐
│ Layer N│ ← 第N层
├───────┤
│ Layer │ ← ...
│ ... │
├───────┤
│ Layer 3│ ← 第3层
├───────┤
│ Layer 2│ ← 第2层
├───────┤
│ Layer 1│ ← 第1层(衬底上)
└───────┘
↓
好处:每个单元可以做得更大(因为单元在同一层上的间距大了),
感测裕度反而比2D同密度更好。
用大尺寸单元+垂直堆叠,换取密度提升。
3D NAND目前已经堆叠到232层甚至更高(美光2023年量产232层,三星推进到300层以上)。每一层之间的连接通过垂直穿透的“通道孔“(channel hole)——这是一个深宽比超过100:1的恐怖蚀刻工艺工程。
3D NAND的单元不再是平面晶体管,而是一种叫做电荷陷阱闪存(Charge Trap Flash, CTF) 的结构。它不用浮栅多晶硅层存储电子,而是在氮化硅(Si₃N₄)层中捕获电子——像一个陷阱阵列。CTF的好处是:电荷被固定在陷阱中,不会像浮栅那样自由移动,因此相邻单元之间的串扰更小,感测裕度可以做得更宽。
但即使有3D NAND和CTF,物理定律仍然在惩罚多bit存储。TLC 3D NAND的P/E寿命通常比QLC 3D NAND高3到5倍。而且随着层数增加,上层的单元和下层的单元存在工艺偏差,存储特性不一致,会进一步压缩感测裕度。
这个行业陷入了一个有趣的矛盾:NAND厂商疯狂追求每单元多存bit来降低每GB成本,但Flash文件系统工程师则被迫用更强的ECC和更复杂的FTL来掩盖这些bit的不可靠。 一场攻防战,双方都以物理极限为参照系,努力从石头里再挤出一滴水。
而我们的生产系统,反其道而行之——它使用的是SLC NOR,容量小、成本高、但可靠。这种选择背后,不是一个技术判断,而是一个价值判断:当数据损坏的后果是刹车失灵而不是照片丢失时,可靠性的优先级压倒一切。
熵增,是存储永恒的对手
在物理学的视角下,包含信息的任何物理系统,都在走向混乱。这是热力学第二定律的直接推论。
你编程一个SLC单元——你用强电场把几千个电子赶进了浮栅。这是一个低熵状态:电子被精确地限制在一个小小的空间里。信息被编码为“0“。
但你一松手——编程脉冲停止了——熵增就开始了。电子通过氧化层的陷阱慢慢泄漏,浮栅里的电子数量从几千降到几百、几十。阈值电压从明确的“0“状态向模糊的“1“状态漂移。最终,你的“0“变成了“1“——信息被抹掉了。
不是被人抹掉的。是被时间抹掉的。是被熵抹掉的。
你给一个TLC单元编程8个状态之一——你在对抗更大的熵增压力。因为这个状态的电压窗口只有SLC的八分之一,任何轻微的物理扰动都可能把一个状态变成另一个。你就像在沙滩上画了一条细线,海浪一来就没了。
ECC是你对抗熵增的工具——用冗余信息来纠正物理错误。但ECC本身也消耗空间(意味着更多的物理单元),而更多的物理单元也受熵增影响。这是一个递归的悖论:对抗熵增的工具本身也在熵增。
这就是存储最深刻的哲学命题:你永远无法彻底战胜熵。你只能拖延它。Flash文件系统工程的全部智慧,就是在有限的时间和有限的资源里,让信息比它“自然应该“活得更久。
熵,永远是一个不等式,不是一个建议。
下集预告
我们聊了SLC/MLC/TLC/QLC的信息密度之争。但无论你把几个bit塞进一个单元,Flash作为一种存储介质,还有三个与生俱来、无法绕过的“原罪“。这三个原罪——写前擦除、单向编程、有限寿命——决定了Flash文件系统的全部设计哲学。
下一节,我们来给Flash办一场“原罪审判“。
悬念留给:为什么你不能直接修改Flash里的一个字节?为什么每次修改都像搬家一样?为什么你的SSD明明还有空间,写速度却越来越慢?答案都在那三个原罪里。