计组与微机控制
4.5 Cache 和主存容量扩展技术
4.5 Cache 和主存容量扩展技术
分级存储器的设计:Cache 是位于 CPU 和主存之间的高速小容量存储器。

目的:
> 缓解 CPU 速度远高于主存速度的矛盾。
Cache 有效的原因是程序具有局部性:
| 局部性 | 含义 |
| 时间局部性 | 最近访问过的数据/指令很可能再次访问 |
| 空间局部性 | 访问某地址后,很可能访问相邻地址 |
STM32F4 这类 Cortex-M4 通常没有复杂的数据 Cache,但理解 Cache 对学习计算机组成和高性能 MCU 很重要。
也就是说cache把常用访问的数据提前存储方便访问

虚拟存储器(操作系统第四章有说)
虚拟存储器给程序提供比实际物理内存更大、更连续的地址空间。

基本思想:
- 程序使用虚拟地址;
- MMU/地址转换机制把虚拟地址转换为物理地址;
- 不常用的数据可以暂存在外存;
- 常用页面调入主存。
STM32 Cortex-M 一般没有完整 MMU,更多是 MPU 存储保护单元。因此它不像 PC 操作系统那样使用完整虚拟内存。
主存容量扩展技术
主存容量扩展要解决的问题是:单片存储芯片的容量和字长往往不能直接满足 CPU 的要求,所以需要把多片存储芯片组合起来,形成 CPU 所需要的主存容量和数据位宽。
主存容量可以看成:
主存容量 = 存储字数 × 存储字长
所以扩展主存本质上有两个方向:
扩展字长 -> 位扩展
扩展字数 -> 字扩展
既扩展字长又扩展字数 -> 字位同时扩展
主存容量扩展技术
主存容量扩展要解决的问题是:单片存储芯片的容量和字长往往不能直接满足 CPU 的要求,所以需要把多片存储芯片组合起来,形成 CPU 所需要的主存容量和数据位宽。
主存容量可以看成:
主存容量 = 存储字数 × 存储字长
所以扩展主存本质上有两个方向:
扩展字长 -> 位扩展
扩展字数 -> 字扩展
既扩展字长又扩展字数 -> 字位同时扩展
1. 位扩展
位扩展是增加每个存储字的位数,也就是增加“字长”。
例如 CPU 需要:
8K × 8 bit
但现有芯片只有:
8K × 1 bit
那么一片芯片只能提供 1 位数据,CPU 一次需要 8 位数据,所以要用 8 片并联。
连接方法:
所有芯片的地址线并联
所有芯片的片选线并联
所有芯片的读写控制线并联
每片芯片的数据线分别接 CPU 数据总线的一位
也就是说,8 片芯片同时被选中,同时读写同一个地址,只是每片负责一个 bit。
核心公式:
位扩展所需芯片数 = 目标字长 / 单片芯片字长
例子:
目标:8K × 8 bit
芯片:8K × 1 bit
所需芯片数 = 8 / 1 = 8 片

位扩展的特点:
地址空间没有变;
每个地址对应的数据位数变多;
多片芯片同时工作;
主要扩展数据总线宽度。
位扩展:地址不变,数据位数变宽。
2. 字扩展
字扩展是增加存储单元的个数,也就是增加“存储字数”。
例如 CPU 需要:32K × 8 bit
但现有芯片只有:8K × 8 bit
每片芯片的字长已经是 8 bit,正好满足 CPU 一次读写 8 bit 的要求,所以不需要位扩展。但每片只有 8K 个地址,目标需要 32K 个地址,所以需要 4 片芯片组成更大的地址空间。
核心公式:
字扩展所需芯片组数 = 目标存储字数 / 单片存储字数
例子:
目标:32K × 8 bit
芯片:8K × 8 bit
所需芯片数 = 32K / 8K = 4 片
连接方法:
低位地址线接到每片芯片的地址输入端
高位地址线经过译码器产生片选信号
数据线并联到 CPU 数据总线
读写控制线并联
为什么需要译码器?
因为 4 片芯片不能同时工作。CPU 给出一个地址时,只应该选中其中一片芯片。所以要用高位地址线判断当前访问的是哪一片。
例如 32K 地址空间需要 15 根地址线:
32K = 2^15
单片 8K 芯片需要 13 根地址线:
8K = 2^13
所以:
低 13 位地址线 A0-A12 接芯片内部地址
高 2 位地址线 A13-A14 用来选择 4 片芯片
字扩展的特点:
数据位宽不变;
地址范围变大;
同一时刻只选中一片或一组芯片;
主要扩展地址空间。

3. 字位同时扩展
字位同时扩展就是目标存储器的字数和字长都比单片芯片大。
例如 CPU 需要:32K × 16 bit
现有芯片是:8K × 8 bit
这时要同时扩展两个方向。
第一步,先扩展字长:
目标字长 16 bit
单片字长 8 bit
位扩展需要 16 / 8 = 2 片
也就是说,两片 8K × 8 bit 芯片并联,组成一组:
8K × 16 bit
第二步,再扩展字数:
目标字数 32K 单组字数 8K
字扩展需要 32K / 8K = 4 组
每组 2 片,一共 4 组:
总芯片数 = 2 × 4 = 8 片
总公式:总芯片数 =(目标字长 / 单片字长) × (目标字数 / 单片字数)
例子:目标:32K × 16 bit
芯片:8K × 8 bit
位扩展倍数 = 16 / 8 = 2
字扩展倍数 = 32K / 8K = 4
总芯片数 = 2 × 4 = 8 片
连接方法:
每 2 片组成一组,负责 16 bit 数据宽度
一共 4 组,负责 32K 地址空间
低位地址线接所有芯片
高位地址线经过译码器选择某一组
同一组内的芯片同时工作
不同组之间通过片选信号区分
一句话记忆:
字位同时扩展:先按数据位宽分组,再按地址空间分组。
片选信号

片选信号用于选择当前 CPU 要访问哪一片或哪一组存储芯片。
常见片选方法有三种:
线选法 全译码法 部分译码法
线选法:直接用某根高位地址线作为片选信号。电路简单,但地址空间不连续,地址利用率低。
全译码法:所有相关高位地址线都参与译码。优点是地址唯一,不会出现地址重叠。缺点是硬件电路复杂。
部分译码法:只用部分高位地址线参与译码。电路比全译码简单,但可能出现地址重叠。
5. 地址线如何分配
做题时最重要的是区分:
片内地址线
片选地址线
片内地址线用于选择芯片内部的某个存储单元。
片选地址线用于选择哪一片芯片或哪一组芯片。
例如单片芯片容量是:8K × 8 bit
因为:8K = 2^13
所以每片芯片需要 13 根片内地址线:A0 - A12
如果目标容量是:32K × 8 bit
因为:32K = 2^15
CPU 总共需要 15 根地址线:A0 - A14
那么:A0 - A12:接芯片片内地址
A13 - A14:用于片选,选择 4 片芯片中的一片
做题固定模板
遇到主存容量扩展题,可以按这个流程:
写出目标容量:目标:M × N bit
写出芯片容量:芯片:m × n bit
判断位扩展倍数:位扩展倍数 = N / n
判断字扩展倍数:字扩展倍数 = M / m
算总芯片数:总芯片数 = 位扩展倍数 × 字扩展倍数
判断地址线:
目标字数 = 2^a -> CPU 需要 a 根地址线
芯片字数 = 2^b -> 芯片内部需要 b 根地址线
片选需要 a - b 根地址线
说明连接方式:
低位地址线接芯片地址端
高位地址线接译码器产生片选
数据线按位连接
读写控制线并联
和微机原理、STM32 的联系
主存容量扩展本质上还是地址译码问题。
微机原理里讲:
CPU 发地址 -> 地址译码 -> 片选 -> 读写存储器
STM32 里虽然你需要自己接 SRAM 芯片,但外设地址映射也是类似思想:
CPU 发出地址
总线矩阵/地址译码判断访问的是 Flash、SRAM、GPIO、U SART 还是 TIM
选中对应模块完成读写
比如:GPIOF->MODER
本质是:
GPIOF 基地址 + MODER 偏移
CPU 发出这个地址后,片内总线译码逻辑会选中 GPIOF 模块,而不是 SRAM 或 Flash。
所以主存扩展、I/O 地址译码、STM32 外设寄存器访问,本质都是:
地址 -> 译码 -> 选中目标硬件 -> 读写数据
最后总结
主存容量扩展记住三句话:
位扩展:扩字长,多片芯片同时提供不同数据位。
字扩展:扩字数,高位地址译码选择不同芯片。
字位同时扩展:先按字长分组,再按字数扩组。
做题核心公式:
芯片总数 =
(目标字长 / 芯片字长) × (目标字数 / 芯片字数)
地址线核心判断:
芯片内部地址线 = log2(单片字数)
CPU 总地址线 = log2(目标字数)
片选地址线 = CPU 总地址线 - 芯片内部地址线
