算术逻辑单元
复习
- 第十一章:设计完成了全加器,可以串联构成多位加法器
- 第十二、十三章:掌握了原码、反码和补码,理解了补码可以统一加减法
- 第十四~十六章:设计完成了减法器、乘法器、除法器
TL;DR
- 算术逻辑单元(ALU)是计算机的核心运算部件
- 它把加减乘除和与或非等运算都集成在一起
- 用一组“操作码“选择当前要做哪种运算,再用译码器把它翻译成控制信号
正文
引言
到这里,我们手里已经有加法、减法、乘法、除法,还有与、或、非、异或、移位等逻辑操作。它们个个都能独立工作,但要真正用来算题,我们总不能让数据在十几个部件之间手动转来转去吧?
我们需要一个统一的地方,把这些运算装在一起,需要哪个就用哪个。它就叫 ALU(Arithmetic Logic Unit,算术逻辑单元)。
特别说明:乘法器和除法器不太懂也没关系,因为在简单的 ALU 中,压根儿就没有这种东西。乘法就是多次加法,除法就是多次减法。
注意,花十秒钟想一下,上面那些东西是怎么来的。如果不能清楚明白地了解其组成和原理,说明还没有学懂,建议回头再看一次。 这里简单提示一下:
- 晶体管组成逻辑门(与,或,非,异或等);
- 部分逻辑门的计算逻辑与加法一致,所以组成加法器;
- 分出一位作为符号,在逻辑上弥补二进制减法的问题,使用 模 诱骗加法器在形式上做减法,形成减法器;
- 用加法器和减法器,组成乘法器和除法器,如果愿意,其中可以有移位器。
设计简单 ALU
我们试着设计一个 4 位 ALU,它支持 12 种功能:加、减、乘、除、取余、与、或、非、与非、或非、异或、同或。
准备基本部件
先列出需要的部件,同时列出各自的输入和输出。
注意:
- 因为非门只有一个输入,所以此处硬编码为 A 引脚,需要取反的数值应该永远连接到 A 输入上。
- 加法器、减法器等等运算部件,还有一个额外的输出:溢出,所以我们也需要将它连接到输出。但因为连接这些溢出输出会使电路变得复杂,所以我们暂时不考虑连接(溢出标志会在下一章细讲)。
连接运算电路
很快,两个问题冒了出来:
- 这些运算的输出,都接到哪里去?
- 所有部件都在同时运算,我们怎么控制 ALU 只输出我们需要的那一个?
第一个问题:输出接哪儿
最简单的办法:所有运算的输出都接到同一根输出线上,只要保证同一时刻只有一个结果在上面就好。
为此,我们需要一个控制开关:由一根 Enable 信号决定“这个结果要不要送出去“。
它的构造简单到可爱——画个真值表就会发现,它就是一个与门:
| 输入 Data | 控制信号 Enable | 输出 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
对多位数据,就是位宽个与门并排(4 位 4 个,8 位 8 个),每个与门管一位。
加上控制开关,ALU 大概是这样:
第二个问题:怎么选择运算
最直接的办法:每种运算单独连一根线,线的通断决定做哪种运算——加法一根、减法一根……但这样,12 种运算就要 12 根线。功能一多,线的数量就爆炸。
停一下。每根线只有“通/断“两种状态,这……不就是二进制吗?
如果我们把这些线的通断编码成二进制数,线的数量就能大幅压缩。12 种运算,只需要 4 根线就够了:2³(8) < 12 < 2⁴(16)。
添加选择逻辑
用 4 根线表示 12 种运算,我们这样规定:
| 控制信号 | 功能 |
|---|---|
| 0000 | 加法 |
| 0001 | 减法 |
| 0010 | 乘法 |
| 0011 | 除法 |
| 0100 | 取余 |
| 0101 | 与 |
| 0110 | 或 |
| 0111 | 非 |
| 1000 | 与非 |
| 1001 | 或非 |
| 1010 | 异或 |
| 1011 | 同或 |
恭喜你!我们已经在初步接触**“指令”**的概念了——上面这串控制信号,就是告诉 ALU“做什么运算“的指令。
那么,怎么把指令翻译成“选中某一根线“呢?用一个译码器(Decoder)。它的作用,就是把输入的二进制码翻译成特定的信号。看图就懂:
把操作码(op_code)送进译码器,译码器就点亮对应的那一路运算,其余全部关闭。
ALU 就完成了。
验证 ALU
来验证一下:设 A = 4(0100),B = 2(0010),按操作码依次计算结果(加法对应 0000,减法对应 0001……):
| 加法 | 减法 | 乘法 | 除法 | 取余 | 与 | 或 | 非 | 与非 | 或非 | 异或 | 同或 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0110 | 0010 | 1000 | 0010 | 0000 | 0000 | 0110 | 1011 | 1111 | 1001 | 0110 | 1001 |
把这个电路改造一下,让操作码自增,依次观察结果:
结果正确。
思考题
我们用“操作码 + 译码器“来选择运算。如果有一天 ALU 要支持的功能从 12 种增加到 20 种,操作码需要几根线?如果增加到 40 种呢?这说明了什么?
小结
知识点
- ALU 的组成
- 用控制开关(与门)决定结果是否输出
- 用操作码 + 译码器选择运算
- “指令“概念的初步接触
参考资料
- Wikipedia(zh):算术逻辑单元:详细的算术逻辑单元介绍
推荐
思考题答案(仅供参考)
20 种功能需要 5 根线(2⁴=16 < 20 < 32=2⁵),40 种需要 6 根线。功能数量每次翻倍,只需要多加一根线——这就是二进制编码的威力。反过来说,如果不用编码、一种运算一根线,线数会跟着功能数线性、甚至爆炸式增长。用编码换线数,是数字设计里非常典型的一招。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪