3. SRAM 存储器详解
SRAM,静态随机存取存储器。名字里带个“静态”,很多人就以为它跟 DRAM 一样需要不停刷新。其实不是。我刚开始接触存储器时也搞混过,后来在项目里吃过亏才彻底弄明白。今天咱们就把 SRAM 的里里外外拆开看一遍。
3.1 6T SRAM 单元结构
SRAM 存储一个 bit,需要 6 个晶体管。这就是“6T”的由来。哪 6 个?两个交叉耦合的反相器(4 个管子),再加两个访问管(2 个管子)。
我画个简图帮你理解:
M1 和 M2 组成一个反相器,M3 和 M4 组成另一个。两个反相器首尾相连,形成锁存结构。M5 和 M6 是开关,字线 WL 一拉高,就把存储节点 Q 和 QB 连到位线 BL 和 BLB 上。
关键点:6T 结构一旦写入,只要不断电,数据就能一直保持。不需要像 DRAM 那样定时刷新。这就是“静态”二字的真正含义。
3.2 静态保持 vs 动态刷新
说到这,咱们必须把 SRAM 和 DRAM 放在一起比一比。很多初学者觉得 SRAM 不用刷新就比 DRAM 高级,其实不是这么回事。
| 对比项 | SRAM (6T) | DRAM (1T1C) |
|---|---|---|
| 存储单元 | 6 个晶体管 | 1 个晶体管 + 1 个电容 |
| 数据保持 | 静态锁存,无需刷新 | 电容电荷会泄漏,需周期性刷新 |
| 刷新周期 | 无 | 通常 64ms |
| 读操作 | 非破坏性读出 | 破坏性读出,读后需重写 |
| 单元面积 | 大(约 100-150 F²) | 小(约 6-8 F²) |
| 速度 | 快(1-10 ns) | 较慢(10-50 ns) |
| 功耗 | 静态功耗较高 | 动态功耗为主 |
| 成本 | 高 | 低 |
DRAM 靠电容存电荷,电荷会漏。所以每隔几十毫秒就得把所有行刷新一遍。我做过一个低功耗项目,DRAM 的刷新电流占了系统总功耗的 15%。当时为了省电,我们不得不把刷新周期从 64ms 拉到 128ms,还得在高温下做可靠性测试。
避坑提醒:SRAM 虽然不需要刷新,但它的静态功耗(漏电流)在先进工艺下越来越严重。28nm 以下的 SRAM,漏电功耗可能占总功耗的 40% 以上。选型时千万别只看“静态”两个字就觉得省电。
3.3 读写操作时序
SRAM 的读写时序,说白了就是怎么把数据放进去、怎么把数据拿出来。我习惯把时序拆成三个关键阶段:地址建立、使能窗口、数据稳定。
读操作
- 地址输入:地址信号加到地址线上,需要一段建立时间 tAS。
- 片选使能:CS 拉低,芯片被选中。同时 OE 拉低,输出使能。
- 字线选通:WL 拉高,M5/M6 导通,存储节点 Q/QB 连接到 BL/BLB。
- 位线差分:BL 和 BLB 之间产生微小电压差(约 100-200mV)。
- 灵敏放大器:检测差分信号,放大到满摆幅,输出数据。
读操作最关键的时间参数是 tRC(读周期时间)和 tAA(地址访问时间)。我见过有人把 tAA 和 tRC 搞混,结果时序约束算错了,板子跑起来数据全是乱的。
经验之谈:实际项目中,SRAM 的读时序瓶颈往往不在芯片本身,而在 PCB 走线的信号完整性。地址线和数据线等长没做好,skew 一大,tAA 就白留了。我建议 layout 时把地址线控制在 ±50ps 以内。
写操作
- 地址输入:同读操作,地址先稳定。
- 数据输入:数据加到数据线上,需要满足 tDS(数据建立时间)。
- 写使能:WE 拉低,同时 CS 拉低。此时 OE 必须拉高,避免数据总线冲突。
- 位线驱动:BL/BLB 被强行拉到 VDD 和 GND,覆盖原有存储值。
- 字线关断:WL 拉低,M5/M6 关断,数据锁存在交叉耦合反相器中。
写操作有个容易踩的坑:tWP(写脉冲宽度)必须够宽。我调试一块板子时,发现某些地址写不进去,用示波器一抓,WE 低电平只有 3ns,而芯片要求最少 5ns。时序余量不够,数据根本没写进去。
// 伪代码:SRAM 读写时序示例
// 假设地址线 18 位,数据线 8 位
void sram_write(uint32_t addr, uint8_t data) {
// 1. 设置地址
SET_ADDR(addr);
// 2. 设置数据
SET_DATA(data);
// 3. 片选使能 + 写使能
CS_LOW();
WE_LOW();
// 4. 等待 tWP (至少 5ns)
delay_ns(6);
// 5. 释放写使能
WE_HIGH();
CS_HIGH();
// 6. 数据保持时间 tDH
delay_ns(2);
SET_DATA_HIZ();
}
void sram_read(uint32_t addr, uint8_t *data) {
// 1. 设置地址
SET_ADDR(addr);
// 2. 片选使能 + 输出使能
CS_LOW();
OE_LOW();
// 3. 等待 tAA (地址访问时间)
delay_ns(10);
// 4. 读取数据
*data = GET_DATA();
// 5. 释放
OE_HIGH();
CS_HIGH();
}
3.4 功耗特性:静态功耗 vs 动态功耗
SRAM 的功耗分两块:静态功耗和动态功耗。很多人只关注动态功耗,忽略了静态部分。我做过一个物联网终端,待机时 SRAM 的漏电比 MCU 自身功耗还高,气得我连夜改方案。
静态功耗
静态功耗来自晶体管的漏电流。主要有三种:
- 亚阈值漏电:Vgs 低于阈值时,管子没完全关断,仍有微小电流。工艺越先进,这个越严重。
- 栅极漏电:栅氧化层越来越薄,电子直接隧穿过去。45nm 以下工艺尤其明显。
- 结漏电:源漏与衬底之间的 PN 结反向漏电。温度每升高 10°C,漏电翻一倍。
我测过一个 1MB 的 SRAM,25°C 时静态电流 2mA,到 85°C 飙到 18mA。电池供电的设备根本扛不住。
动态功耗
动态功耗跟操作频率成正比。公式很简单:
Pdynamic = C × V² × f
其中 C 是负载电容,V 是工作电压,f 是切换频率。降低电压是最有效的省电手段。从 3.3V 降到 1.8V,动态功耗直接降到原来的 30%。
| 工作电压 | 频率 10MHz | 频率 50MHz | 频率 100MHz |
|---|---|---|---|
| 3.3V | 10.9 mW | 54.5 mW | 109 mW |
| 2.5V | 6.25 mW | 31.3 mW | 62.5 mW |
| 1.8V | 3.24 mW | 16.2 mW | 32.4 mW |
选型建议:低功耗应用优先选 1.8V 甚至 1.2V 的 SRAM。如果必须用 3.3V,考虑带深度睡眠模式的型号,待机电流能降到 1µA 以下。
3.5 实际项目中的选型考量
说了这么多理论,最后聊聊实战。我总结了几条选型原则:
- 容量匹配:别贪大。SRAM 每 bit 成本比 Flash 高一个数量级。够用就行。
- 速度够用:MCU 主频 100MHz,选 10ns 的 SRAM 就够。没必要上 3ns 的,贵且难 layout。
- 功耗预算:算清楚静态功耗和动态功耗的占比。待机时间长的项目,静态功耗是主要矛盾。
- 温度范围:工业级(-40°C ~ 85°C)和商业级(0°C ~ 70°C)的漏电差很多。户外设备别省这个钱。
- 封装:BGA 封装虽然省面积,但手工焊接困难。小批量生产建议用 SOP 或 TSOP。
我记得有个项目,选了 2MB 的 SRAM,结果实际只用 512KB。多出来的 1.5MB 一直在漏电,白白浪费电池。从那以后,我每次选型都先算清楚最大使用量,再留 20% 余量,绝不多买。
小技巧:如果系统对功耗极其敏感,可以考虑用 FRAM(铁电存储器)替代部分 SRAM。FRAM 的读写速度接近 SRAM,但静态功耗几乎为零。当然,容量和成本是另一回事。