寄存器&内存
能记录“1”的电路
首先,两个输入都设为0,所以电路输出0。
如果将A变成1,输出变为1,且输出回到B,将B变为1。
此时,无论A如何变化,输出都将保持1不变,因为B为1。
能记录“0”的电路
首先,两个输入都设为1,所以电路输出1。
如果之后A设为0,由于是and门,输出会变成0
这个电路能记录0,和之前那个相反。
就像之前,此时无论A设什么值,电路始终输出0;
and-or锁存器
现在有了能存0和1的电路为了做出有用的存储,我们把两个电路结合起来。
设置为1,复位为0时,输出为1;
复位为1时,输出为0;
设置和复位都为0时,电路会输出最后放入的内容,也可以理解为保持上一时段的状态。
也就是说,它存住了1位的信息。
麻烦的是,用两条线“设置”和“复位”来输入,有点难理解,为了更容易用,我们希望只有一条输入线,将它设为0或1来存储值。还需要一条线来“启用”内存。启用时允许写入,没启用时就“锁定”,这条线叫“允许写入线”。
上面这张电路我们称之为“门锁”,因为门(允许写入线)可以打开和关上。
我们不想关心单独的逻辑门,所以我们提升一层抽象。把“门锁”放进盒子里,这个盒子能存一个bit
让我们来测试一下这个盒子。
当允许写入线为0(关闭状态)时,无论数据输入为1还是0,数据输出都为0。因为“允许写入线”是关闭的,所以内容不会变化。
所以要给“允许写入线”输入1,打开“门”。现在往“数据线”放1,1就能存起来了。
此时可以关掉“允许写入线”,输出就会保持1,现在不管给“数据输入”什么值,输出都不会变。
值被存起来了。
寄存器
当然,只能存1个bit好像作用不大,但是我们没限制只能用一个锁存器。
如果我们并排放8个锁存器,可以存8位信息,比如一个8bit数字。一组这样的锁存器叫“寄存器”。
寄存器能存一个数字,这个数字有多少位,叫“位宽”。如8位、16位,到现在常见的32位和64位。
写入寄存器前,要先启用里面所有寄存器,我们可以用一根线连接所有“允许输入线”,把它设为1。然后用8条数据线发数据。
然后将“允许写入线”设回0,现在8位的值就存起来了。
门锁矩阵
现在问题来了,64位需要64根数据线,还有64根连到输出端,还需要1根线启用所有锁存器,但加起来也有129条线了,256位则需要513条线。
我们可以选择矩阵排列。
要启用某个锁存器,就打开相应的行线和列线。
放大看看怎么做的,我们只想打开交叉处的锁存器的“允许写入线”,而所有其他锁存器的该线保持关闭。
我们可以用and门,只有行线和列线均为1时,and门才输出1,所以可以选择单个锁存器。
这种行/列排列法,用一根“允许写入线”连所有锁存器。为了让锁存器变成“允许写入”,行线,列线和“允许写入线”都必须是1,因为每次只有1个锁存器会这样,所以我们可以只用一根“数据线”来连接所有的锁存器来传数据,因为只有那个要存数据的锁存器会启用,其他锁存器因为没有“允许写入”,所以会忽略数据线上的值。我们可以用类似的技巧,做“允许读取线”来读数据,从一个指定的锁存器,读取数据。
所以对于256位的存储,只要35条线,1条“数据线”,1条“允许写入线”,1条“允许读取线”,还有16行16列的线用于选择存储器。
由于最多16行,用4位二进制就可以表示某行或者某列。比如“12行 8列”可以写成“1100 1000”。
多路复用器
为了将地址转成行和列,我们需要“多路复用器”,它类似于上面讲的16行16列的线的矩阵组合,我们仍然不需要具体了解它的内部,所以继续抽象,把它看做一个整体。
它输入一个8位地址,4位代表列,4位代表行;一条允许写入线,一条允许读取线,还有一条数据线,用于读/写数据。
但很不幸,256位的内存也没法做什么事,所以还要扩大规模,把它们并排放置,就像寄存器一样
一行8个,可以存一个8位数字,8位也叫一个字节(byte)
一个8位的二进制数分别被写入到8个内存的同一地址来记录,8个256位内存则可以存储256个8位二进制数,也就是256个字节(byte)
再次,为了简单,我们不管内部,不看作是一堆独立的存储模块和电路,而是看成一个整体的可寻址内存。
8位最多能代表256个内存地址(1111 1111是255,0~255一共256个数字)。如果要给千兆或者十亿字节的内存寻址,则需要32位的地址。
内存的一个重要特性是:可以随时访问任何位置。因此叫“随机存取存储器”,简称RAM,其实也就是内存。
今天,我们用锁存器做了一块SRAM(静态随机存取存储器)