> For the complete documentation index, see [llms.txt](https://s2.shizhz.me/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://s2.shizhz.me/s2e4/5.md).

# 4.5. 内存：大容量的存储芯片

上一节的最后我们设计了一个可寻址的存储组件，我们将其称为一个 4x1 内存单元，其中 4 表示该组件的数据容量为 4 Bit, 而 1 表示其数据带宽只有 1 Bit, 也就是说该组件每次只能处理 1 Bit 的数据。我们知道计算机内部的基础数据单位是字节（Byte），一字节包含 8 Bit, 这已经超出了该组件的存储容量；而即使是 Intel 在上世纪70年代发布的第一代 x86 系列芯片 8086, 其寄存器也是16位的，这意味着该芯片的数据带宽为16位，而现在主流的系统都已经上升到了64位。由此可见，单个该组件的实用价值极其有限。

但该组件并不是我们设计的最终产品，而是基础的内存单元，我们在设计该组件时，已经将一个完整的存储芯片所涉及的概念都整合进去了，包括输入、输出、地址、控制信号，因此当我们需要更大容量、更大数据带宽的存储组件时，所面临的问题实质上只是如何组装扩容了。本节我们将讨论如何通过串联扩容数据容量，通过并联扩容数据带宽。

接下来我们来看一下如何通过串联两个组件，构造出一个容量为一字节、即一个 8x1 的内存单元。不考虑内部实现，一个 8x1 内存单元的接口如下图所示：

![8x1 RAM Array](/files/-MdWRspKAwCic5gOiZyN)

容量的增加导致 8x1 内存单元需要 3 根地址总线，这是它在接口上与 4x1 内存单元唯一的变化，如何处理多出来的最高位地址信号 A2 是解决问题的关键。

> &#x20;将 A2 看着是最高位地址信号是指三位地址信号按照 A2A1A0 进行排列。

不难发现，我们可以将 A2 作为如何选择内部两个 4x1 内存单元的指示信号，即当 A2 = 0 时，我们选择图中的RU0进行数据读取操作，而 A2 = 1 时选择RU1。也就是说我们将一字节中的低四位存放在 RU0 中，高四位存放在 RU1 中。通过在输入侧增加一个 1-2 Decoder 来控制写入信号、在输出侧增加一个 2-1 Selector 来选择输出信号, 就可以达成这种效果，最终的电路图如下所示：

![8x1 RAM Array Impl](/files/-MdWS742qlB4sT03vBLq)

这样我们就得到了一个 8x1 的内存单元。通过相同的方式，我们可以将两个 8x1 的内存单元扩容成一个 16x1 的内存单元，以此类推我们可以组装出任何容量为 2^n Bit 的内存单元。

现在我们来看如何通过并联的方式增大数据带宽。

我们先考虑通过 8x1 内存单元构建 8x2 的数据单元，即将数据带宽增大到 2 Bit. 不考虑内部实现，一个 8x2 内存单元的接口如下图所示：

![8x2 RAM Array](/files/-MdWSP0CFJHi7bi3zyr1)

扩容数据带宽的思路很直观，我们在内部并联两个 8x1 内存单元 RU0 与 RU1，这两个内存单元共享地址信号（A2A1A0）与控制信号（R/W, CLK），然后将 DI0 与 DO0 连接到 RU0 的对应引脚，将 DI1 与 DO1 连接到 RU1 的对应引脚即可。示意图如下（图中仅标记出了数据引脚的连接方式，而省略了地址信号及控制信号的连接方式）：

![8x2 RAM Array Impl](/files/-MdWSXd-3ON_PSJPihR-)

这样我们就构建好了一个 8x2 的内存单元，不难发现，使用同样的方法可以构建出任意 8 x N 的内存单元。

本节我们所讨论的内容仅仅是理解内存芯片的一个模型，实际上的芯片结构要复杂得多。例如在计算机内部，内存的最小寻址单位是字节，因此我们可以将内存构造成一个 N x 8 的内存阵列，但 CPU 与内存的数据带宽（即数据总线）要明显高于 8 Bit, 例如当前主流芯片的数据总线是 64 位，因此对于内存而言，其每次需要操作的数据是从地址信号开始的连续 8 字节，在内存芯片内部需要做好这种转换。
