储存器组织
储存器与锁存器
人们总是将需要的记住的内容事先记起来,在需要时拿出来阅读;习惯于将可能用到的事物先存起来,在需要时将它们取出来。从技术角度来说,这个过程称为先存储后访问。存储器的职责和作用就在于此,它负责保障这两个过程之间信息完好无损。我们每次存储信息都要利用不同种类的存储器。比如,保存文本信息的不二之选就是纸张,而磁带则更适于储存音乐和电影。
电报继电器(Telegraph Relays)——以一定形式组织起来构成逻辑门,然后再形成触发器——同样具备保存信息的能力。在前面章节中我们讨论过,一个触发器可以对1位信息进行存储。这样的存储能力要存储一大堆的信息还远远不够,但它却为我们达到目标迈出了坚实的一步。其实知道了如何存储1位信息,很容易就可以想象出如何存储1位,3位或更多信息。
在第14章的学习过程中,我们一起讨论过由一个反向器,两个与门和两个或非门构成的D型电平触发器,如下图所示。
当时钟输入为1,Q端输出与数据端输入保持一致。但当时钟输入跳变为0时,Q端输出将保持数据端最后一次的输入。除非时钟输入再次还原为1,之后的数据端输入不会影响输出。此触发器的真值表如下。
在第14章的讨论中,这种触发器可以由两种不同特性的电路来实现,而在本章我们仅选择其中一种——目的就是为了保存1位信息。为了更清楚地表述,我们给输入和输出端重新命名,使其名称与功能相符,如下图所示。
从结构上来讲,这套电路与先前所学到的是同一种触发器,只是命名方式不尽相同,现在Q输出端被称为数据输出端(Data Out),时钟输入端(在第14章叫做保持位)命名为写操作端(Write)。就像信息可以被记录在纸上一样,写操作端的信号同样使得数据输入(Data In)信号被写入(Written Into),也可以称之为被存储(stored)到电路中。一般情况下,如果写操作端为0,则数据输入信号状态对输出无影响。而当我们想把数据输入信号存储在触发器中时,可以把写入信号应先置1后置为0.在第14章讲到过,这种类型的电路也被称为锁存器,因为存储进去的数据就好像被锁住一样。下面给出了1位锁存器简化框图,框图未画出其内部结构中的部件。
我们很容易想到如何把多个1位锁存器组织成为多位锁存器,所要做的就是把写操作端的信号连接到系统中,就像下面这样。
图中显示的8位锁存器其输入和输出端各有8个。另外还包括一个写操作端,在非工作状态下一般为0.如果把一个8位二进制数存储在锁存器中,首先要把写操作端置1,然后置0.我们同样可以把这个锁存器以框图的形式表现出来,就像下面这样。
为了和先前提到的1位锁存器保持一致,我们将它可以画成下面这种形式。
储存器
还有另一种方法集成8个1位锁存器,但其结构并不像上面的这样直观。假设我们只想用一个数据输入和输出信号端,而且希望锁存器能将输入信号数据分8次独立存储。最后一项要求就是我们还希望能够通过观察数据输出信号端确定实际的8位输出。
换句话说,在这种锁存器中我们只想存储8个单独的比特,而不是存储1个8位二进制数。
8-1数据选择器
我们知道现在所需要的是8个1位锁存器。先不考虑数据如何存储在这些锁存器中,把重点放在如何用一个灯泡来确定锁存器的数据输出信号。最简单的方法就是把这个灯泡一次连接到锁存器上,分若干次来测试各个锁存器的输出,但是我们要追求更加自动化的方法。用关开选择想要检查的锁存器是一个好的办法。
究竟需要多少个开关能解决问题呢?我们可以把这个过程进一步抽象,问题变成了怎么样从8个物体选出一个我们想要的,我们需要3个开关。这是因为通过3个开关连通与闭合的排列组合,总共表示出8个不同的值:000,001,010,011,100,101,110,111.
现在我们手头上已有8个1位锁存器、3个开关、1个灯泡,此外在开关和灯泡之间还有另外一种装置,如下图所示。
这个“额外装置”就是图中的神秘盒子,顶部带有8个输入端,左侧也带有3个输入端。通过三个开关的闭合和断开,对顶部的输入进行8选1操作,输出结果被传递到其底部连接的灯泡,使其发光。
上图的这个装置我们称为8-1数据选择器(8-Line-to-1-Line Data Selector)。
8-1选择器有8个输入端(在其顶部),以及3个选择输入端(在其左侧)。选择输入端的功能就是选择一个输入端数据,然后使其在输出端输出。如果选择输入端为000,则将D0锁存器的值输出;若选择端为111,则D7锁存器的值将被输出;若选择端为101,则相应地输出D5的值。系统的真值表如下所示。
8-1选择器主要组成部件为:三个反向器,八个4端口输入与门,一个8端口输入或门,系统的组织结构如下图所示。
这个电路看上去线路密布,要理解它是如何工作的,最好方式就是一起来看一个例子。假设S2初始化为1,S1初始化为0,S0初始化为1.从顶部开始的第6个与门的输入由S0,1-S1,S2组成,初始状态下它们全为1.其余与门的这三项输入数据都与第6个与门不尽相同,这使得其余与门输出全部为0.若D5变为0意味着第6个与门输出为0;反之第6个与门输出则为1.对最右边的或门也可以按照同样的方式理解。我们可以总结出下面这个结论:若选择端为101,则数据输出端与D5的输出保持一致。
让我们重新整理一下思路,想想自己究竟要干什么。我们的目的是通过某种方式连接8个1位锁存器,使自己能够从一个输入信号端写入数据,还能从一个输出信号端鉴别出数据。现在我们已经成功地使用了一个8-1选择器对8个锁存器进行了选择操作,并将相应锁存器的数据输出,下面是电路的结构图。
3-8译码器
到这里我们已经成功了一半。既然输出端已经满足了要求,现在把注意力集中到输入端。
输入端包括了数据输入信号及写操作信号。我们可以把所有数据输入信号在锁存器的输入端连接在一起。但8个写入信号是不可以连在一起的,因为我们很可能要向每个锁存器依次写入数据。除此之外还需要一个独立的写入信号,它能被路由到任意(且唯一)的锁存器上,系统的结构可用下图表示。
为了圆满完成任务,我们需要另外一款电路元件,而且这款元件与8-1选择器功能类似,但它的作用正好相反。我们所说的正是3-8译码器(3-to-8 Decoder)。前面的章节中我们曾学习过一个简易的数据译码器(Data Decoder)——在第11章中为了选择喜欢的猫咪的毛色,我们把开关以一定方式进行连接使其具有选择功能。
3-8译码器的输出端口共有8个。在任何时刻,译码器只会有一个锁存器的输出为1,其余均为0.每一个输出端的结果都是由S0,S1,S2这三个信号的排列组合决定的。而数据的输出和输入一致,如下图所示。
我再次强调一遍:注意从上往下数的第6个与门,它的输入包括S0,1-S1,S2.没有任何一个与门具有和它相同的三个输入。在这种情况下,如果选择输入端为101,则除了O5要根据情况进行判定外,其余与门输出都为0.这个时候,若数据端输入为0,则O5随之输出为0;相应的,若数据端输入为1,则O5输出为1.译码器的逻辑表可以如下表所示。
3-8译码器和8-1选择器简直一模一样,唯一的区别是3-8译码器的8个连接输出端的与门各多了一个数据输入端。
随机访问存储器
将8个锁存器加入到电路就形成了完整的系统。
值得注意的是,译码器和选择器具有相同的选择信号,在上图中这三个信号一起被称为地址端口(Address)。地址的作用就像我们平时使用的邮箱号,长度为三位的地址决定了8个锁存器中的哪一个将被引用。在3-8译码器的输入端,地址起到了决定哪些锁存器可以被写操作端的信号触发来保存数据的作用。在输入端(图的下半部分),8-1选择器通过地址来选择8个锁存器的一个,最后将其输出。
这种配置下的锁存器在有的资料中也被称为读/写存储器(read/write memory), 但更普通的叫法是随机访问存储器(Random Access Memory),或RAM。可以认为我们讨论的这种存储器是可以存储8个独特比特的RAM,它的简化结构图如下所示。
上图所示的电路之所以能够称为存储器是因为它可以保存信息。而能够被称为读/写存储器是因为它不仅可以在每个锁存器中存储新的数据(可以把这种功能称为写数据),而且我们还可以检查每个锁存器都保存了什么数据(可以把这种功能称为读数据)。之所以可以被称为随机访问存储器,是因为读写操作很自由,我们只需要改变地址及相关的输入,就可以从8个锁存器中读出或写入需要的数据。相比其他的顺序型的存储器——这种存储器在使用时有一定的限制,如果想要读取地址为101的数据,必须先把地址为100的数据读取出来。
RAM阵列
将RAM进行特殊的配置可形成RAM阵列(Array),我们说讨论的这种RAM阵列以8x1(读作8乘1)的方式组织起来。阵列以1bit作为存储单元,共存储8个单位的数据。所以这个RAM阵列中能存储的位数等于8与1的乘积。
RAM阵列的组合形式多种多样。比如我们可以通过共享地址的方式可以把两个8x1的RAM阵列连接起来,如下图所示。
我们把这个8x1的RAM阵列的地址和输出都分别看成一个整体,这样就得到了一个8x2的RAM阵列,如下图所示。
这个RAM阵列可存储的二进制数依然是8个,但每个数的位宽为2位。
我们还可以把两个8x1的RAM阵列看作是两个锁存器,使用一个2-1选择器和一个1-2译码器就可以把它们按照单个锁存器连接方式进行集成,下面给出了这种方案的电路图。
“选择”端之所以连接到译码器和选择器,主要作用是在两个8x1RAM阵列中选择一个,本质上它扮演了第4根地址线的角色。因此这种结构实质上是一种16x1的RAM阵列,如下图所示。
上图所示的RAM阵列存储容量为16个单元,每个单元占一位。
RAM阵列的存储容量与其地址输入端的数量有直接的联系。在没有地址输入端的情况下(只有1位锁存器和8位锁存器的情况),只能存储1个单元的数据;当存在1个地址输入端时,可以存储2个单元的数据;有两个地址输入端时,可以存储4个单元的数据;有3个地址输入端时,可以存储8个单元的数据;有4个地址输入端时,可以存储16个单元的数据。我们可以把它们之间的关系归纳成如下等式。
前面已经向大家演示了怎么搭建小型RAM阵列,你可能回问:为什么不搭建一个大规模的RAM阵列呢?就像下面这样。
上图所示的RAM阵列可存储8192个bit的信息,每8个bit为一组,总分为1024组。因为2的10次方恰好是1024,所以地址端共有10个输入端口。电路还包括8位的数据输入端和8位的数据输出端。
从专业角度来讲,这个RAM阵列的存储容量为1024个字节。就好比一个邮局放置了1024个邮箱,而每个邮箱里面都可以存放1字节大小的邮件。
在计算机中,我们常用1K代替1024字节,但是这里所说的1千字节却代表着1024字节——并非1000个字节。
存储容量为1KB的存储系统由8个数据输入端、8个数据输出端和10个地址输入端所组成。由于这些字节是由10个地址输入端来标识和访问的,所以这种RAM阵列存储容量为2的10次方字节。如果我们再加上一条地址线,它的存储容量将变成原来的两倍。
我们把1024个字节简化成为1KB,相同的逻辑,我们把1024KB统称为1兆字节,兆字节通常缩写为MB。
1024MB也就顺其自然地被称为1吉字节,缩写为GB。
同理1太字节表示2的40次方个字节,约为10的12次方,太字节的缩写为TB。
还有1批字节(petabyte),1安字节(exabyte)。
64Kx8RAM
既然我们已经学会如何构造任意大小的RAM阵列,接下来继续对这个问题探究下去。假设现在已经构造好了一个容量为65536字节的存储器组织,如下图所示。
为什么要选择大小为64KB的RAM阵列?而给32JB或128KB?因为65536是一个约整数,转换为幂的形式就是2的16次方,这个RAM阵列需要配备16位的寻址端。换句话说,该地址恰好可以用2个字节表示。将地址范围转换为十六进制就是0000h~FFFFh。
如果用一种控制面板来辅助我们管理对这块64KB存储器的操作——包括写数据和读数据,一切就会直观明了。在这款控制面板上,有16个开关用于控制地址位,还有8个开关用于控制要输入的8bit数据。写操作端也用一个开关来表示,8个灯泡用来显示8位数据,这个控制面板如下图所示。
初始状态下所有的开关均置0.其右下角有一个标识为控制端(takeover)的开关,这个开关的作用是确定由控制面板还是由外部所连接的其他电路来控制存储器。如果其他电路连接到与控制面板相连的存储器,这时控制端置0(如图所示),此时存储器由其他电路系统接管,控制面板上的其他开关将不起任何作用;当控制端置1时,控制面板将重新获得对存储器的控制能力。
这种功能可以用一些2-1选择器来实现。仔细数一下会发现,我们需要25个2-1选择器——其中包括16个地址输入端,8个数据输入端,以及1个写操作端。电路如下图所示。
当控制端开关断开时,RAM阵列的地址端,数据输入和写操作端的数据全部来源于外部信号,也就是在2-1选择器的左上角的输入信号;当控制端开关闭合,RAM阵列的地址端,数据输入端和写操作端的数据来源于控制面板开关发出的信号。但最终RAM阵列的输出信号都会传输到8个灯泡上或其他可能的地方。
下面这幅是控制面板与64Kx8 RAM阵列的逻辑结构框图。
当控制端开关闭合时,通过操作16个地址开关,我们可以选择65536个地址中的任何一个,灯泡的状态将表示地址中所保存的8位数据。我们可以使用8个数据开关表示一个新数,然后把写操作端置1,从而将数据写入存储器。
64Kx8的RAM阵列和控制面板这一组合的确很使用,它可以帮助我们存储65536个8位数据并且读取其中的任意一个。与此同时,我们也给其他部件提供了接入系统的机会——需要接入系统的通常是一些电路部件——这些部件可以轻易地读取并利用存储器中存放的数据,还可以把数据写入存储器。
一个辛辛苦苦装满了65536字节珍贵数据的64Kx8RAM阵列,如果断掉电源,所有的电磁铁都将因为没有电流而失去磁性,金属片将弹回原位,所有继电器将还原到未触发状态。
正因此如此,随机访问存储器也被称为易失性(volatile)存储器。为了保证存储的数据不丢失,易失性存储器需要恒定的电流。