上节,我们用逻辑门做了个简单 ALU,它能执行算术(Arithmetic)和逻辑(Logic)运算,ALU 里的 A 和 L 因此得名,当然,算出来之后如果扔掉就没什么意义了。得找个方法存起来,可能还要进行多个连续操作,这就用到计算机内存了。
如果你在主机上打过一场长时间的对局,或玩困难模式的 "扫雷",然后狗跑过来,被电源线绊倒,把插头拔了出来,你知道失去进度的痛苦。真同情你。你损失数据的原因是电脑用的是"随机存取存储器",简称"RAM"。它只能在有电的情况下存储东西,比如游戏状态,另一种存储 (memory) 叫持久存储,电源关闭时数据也不会丢失,它用来存其他东西。我们之后会讨论存储 (memory) 的持久性问题。
今天我们从简单开始,做只能存储 1 位的电路,之后再扩大,做出我们的内存模块。下次和 ALU 结合起来,做出 CPU!
我们至今说过的电路都是单向的,总是向前流动,比如上集的 8 位 "脉动进位加法器",但也可以做回向电路,把输出连回输入,我们拿一个 OR 门试试,把输出连回输入,看看会发生什么。首先,两个输入都设为 0,"0 OR 0" 是 0,所以电路输出0。如果将 A 变成1,"1 OR 0" 为 1,所以输出 1。一转眼的功夫,输出回到 B,OR 门看到两个输入都是 1,"1 OR 1" 仍然为1,所以输出不变,如果将 A 变成 0,OR 门依然输出 1,现在我们有个电路能记录 "1"。
然而有个小问题:这是永久的!无论怎么试,都没法从 1 变回 0,我们换成 AND 门看看会怎样,开始时,A 和 B 都设 1,"1 AND 1" 永远输出 1,如果之后 A 设为 0,由于是 AND 门,输出会变成 0,这个电路能记录 0,和之前那个相反,就像之前,无论 A 设什么值,电路始终输出 0。
现在有了能存 0 和 1 的电路,为了做出有用的存储 (memory) , 我们把两个电路结合起来,这叫 "AND-OR 锁存器",它有两个输入, "设置"输入, 把输出变成 1, "复位"输入,把输出变成 0。如果"设置"和"复位"都是 0,电路会输出最后放入的内容,也就是说,它存住了 1 位的信息!
存储!这叫"锁存", 因为它"锁定"了一个值,放入数据的动作叫 "写入" ,拿出数据的动作叫 "读取",现在我们终于有办法存一个位了!
麻烦的是, 用两条线 "设置"和"复位" 来输入, 有点难理解,为了更容易用,我们希望只有一条输入线,将它设为 0 或 1 来存储值。还需要一根线来"启用"内存,启用时允许写入,没启用时就 "锁定",这条线叫 "允许写入线"。加一些额外逻辑门,可以做出这个电路,这叫"门锁",因为门可以打开和关上。
现在有点复杂了,我们不想关心单独的逻辑门,所以我们提升一层抽象,把 "门锁" 放到盒子里 - 这个盒子能存一个 bit。我们来测一下新组件!一切从 0 开始,数据输入从0换到1, 从1换到0,什么也不会发生 - 输出依然是 0。因为 "允许写入线" 是关闭的,所以内容不会变化,所以要给 "允许写入线" 输入 1, "打开" 门,现在往 "数据线" 放 1,1 就能存起来了,注意输出现在是 1 了,成功!
现在可以关掉 "允许写入线" ,输出会保持 1,现在不管给 "数据线" 什么值,输出都不会变,值存起来了。现在又打开 "允许写入线" , "数据线" 设为0。"允许写入线" 关闭,输出 0。成功了!
当然,只能存 1 bit 没什么大用,肯定玩不了游戏,或做其它事情,但我们没限制只能用一个锁存器。如果我们并排放 8 个锁存器, 可以存 8 位信息,比如一个 8 bit 数字,一组这样的锁存器叫 "寄存器"。