编码:触发器(二)
1 前言
本文是基于《编码》、《穿越计算机的迷雾》两部著作进行读后整理的记录性博客。对书中较为重要的内容进行归纳整理进行二次创作,略去了繁琐的讲述细节,力求简明扼要。
编码:一种由若干符号和规则组成的系统,用来向计算机表述指令。
2 正文
2.1 D 型触发器
R-S 触发器最突出的特点在于,它可以记住哪个输入端的最终状态为 1。但是有时候我们需要一种记忆能力更加强大的电路,例如能记住在某个特定时间点上的一个信号是 0 还是 1。
我们想在计算机中保存一个比特,但我们会发现我们的触发器有两个输出,保存一个比特不需要这么多,因此我们可以将 Q反废弃不用。
我们的愿望是用触发器保存一个比特,一个比特只需要一根电线就可以传送,对于我们的触发器它有两个输入端 S 和 R。而且,触发器要正常工作,离不开这两个输入端,要想使 Q = 0,S 必须为 0,R 必须为 1;要想使 Q = 1,必须使 S = 1 而 R = 0。
我们可以使用非门使 R 与 S 总是相反,解决触发器保存 1 个比特的问题,如下图所示。很显然,因为要想使触发器保存一个比特,就必须使 S 和 R 以相反的方式出现,所以非门的作用就是创造这样的条件。
可以发现,上述电路虽然可以保存 1 个比特,但它保存的比特会随时因为后面传入的数据而改变,也即上面介绍的方法无法真正保存,被保存的比特不能够独立存在而不受影响。
因此我们可以考虑为上述电路添加一个 “控制器”,不保存数据时输入数据无影响,需要保存数据时打开 “门”,存入数据,关上 “门”,后续输入的数据无法存入除非再次打开 “门”。
在构造具备这种功能的电路之前,让我们先来思考一下它的具体行为。这个电路存在两个输入。其中一个我们称之为数据端(Data),用来传入数据。与所有数字信号一样,数据端取值为 0 或 1;另一个输入被称为保持位(Hold That Bit),保持位的作用就是使当前的状态被 “记住”,通常情况下保持位被设置为 0,在这种情况下数据端对电路不产生影响。当保持位置 1 时,数据端的值就会在电路系统中被 “记住”。随后保持位又置为 0,这时电路已经 “记住” 了数据端的最后一次输入,而之后数据端的输入无论如何变化都不会对电路产生影响。
我们可以把状态转化的过程以真值表的形式表示如下。
在前两种情况下,保持位为 1,输出 Q 与数据端输入相同;后面两种情况下,保持位为 0,输出端 Q 和其前一个状态保持一致。值得注意的是,保持位为 0 意味着输出将不再变化,也就是说不再被数据端所影响,我们可以进一步将真值表简化为如下所示。
X 表示 “其取值情况与结果无关”,只要保持位的值为 0,那么数据位对电路的输出没有影响,电路的输出和其前一个状态相同。也即前面提到的 “关门” 操作,不再存入数据。
如果使用先前学过的 R-S 触发器来实现这种具有保持位的功能系统,那么我们的电路需要在输入端增加两个与门,下图所给出了该系统的实现电路。
只要保持位为 0,则置位端对于输出结果不会有任何影响。保持位为 0,那么无论复位和置位为什么输出都为 0,传输到后续的电路时对应前面介绍的 R = 0,S = 0,Q 和 Q反保持原有状态。而这也保证了触发器不被外面的数据干扰,继续保持原先保存的那个比特。
当保持位信号为 1 时,这套电路系统就和先前讲过的 R-S 触发器功能一致。这时由于上面与门的输出和复位端输入相同,而下面与门的输出和置位端输入相同,所以电路系统的功能和普通的 R-S 触发器是一样的。
但是我们离目标还差一点。我们只想要两个输入,而不是三个,怎么解决这个问题呢?先回忆一下 R-S 触发器的功能表:两个输入端同时为1是非法的,要尽量避免;而两个输入端同时为 0 是无意义的,因为那种情况下输出就会保持不变。我们只要将保持位设置为 0,就完全可以实现相同的功能。
由此可以总结出,真正有意义的输入可以是 S 为 0,R 为 1 或者是 R 为 0,S 为 1 的情形。如果把数据端信号看做置位信号,把它取反后的值看做复位端信号,我们可以画出相应的电路图如下所示。
可以看出只要保持位为 0,电路输出就丝毫不受输入端的影响。当保持位为 1 时,电路反映出数据端输入的值。电路会 “记得” 当保持位最后一次置 1 时数据端输入的值,数据端的变化对此没有影响。例如,数据端再置回 0 对输出将不会产生影响。
这个电路称为电平触发的 D 型触发器,D(Data)表示数据端输入。所谓电平触发是指当保持位输入为某一特定电平(本例中为 “1”)时,触发器才保存数据端的输入值。
D 触发器可以用下列符号来代替:
由于 Q反端舍弃不用,这里表示时也可不必画出输出线
通常情况下,当这种电路出现在书中的时候,输入端是不会被标记为保持位的,而是被标记为时钟(clock)。
通常把数据端简写为 D,时钟端简写为 Clk,其功能表如下所示。
这个电路也就是所谓的电平触发的 D 型锁存器,它表示电路锁存住一位数据并保持它,以便将来使用。这个电路也可以被称为 1 位存储器。后续会介绍如何将多个 1 位存储器连接起来构成多位存储器。
在锁存器中保存多位值通常是很有用的。假如你想用前面介绍的加法器把 3 个 8 位数相加,可以在开关的第 1 行中存入第 1 个加数,以同样的方式把第 2 个加数存入第 2 行,但是必须记下第一次相加的结果。然后你需要把这个结果输入到开关的一行中,再把第 3 个加数输入到开关的另一行中。这里介绍也即我们日常计算多个数相加时的操作,例如 1+2+3,我们先输入 1 和 2 再计算 1+2 的结果算出并记录下来,再将这个计算结果输入并和输入的 3 相加。
实际上不必输入中间结果,我们可以在第一次计算之后直接使用它。可以使用锁存器来解决这个问题。我们在一个小盒子里布置 8 个锁存器,如前所述,每个锁存器包括两个或非门、两个与门以及一个反相器。所有的时钟输入端都互相连在一起。结果如下图所示。
这个锁存器可以一次保存 8 位数。上面的 8 个输入端依次标记为 ,下面的 8 个输出端被标记为 。左边的输入是时钟(Clk),时钟信号通常为 0。当时钟信号为 1 时,D 端输入的 8 位值被送到 Q 端输出。当时钟信号为 0 时,这 8 位值将保持不变,直到时钟信号再次被置 1。
下面是 8 位加法器的图示。
通常,8 个 A 输入端和 8 个 B 输入端连接到开关上,CI(进位输入)接地,而 8 个 S(计算和)输出以及 CO(进位输出)端连接到灯泡上。经过改进,8 位加法器的 8 个 S 输出端既与灯泡相连,又连接到 8 位锁存器的数据(D)输入端。标记为 “保存”(Save)的开关是锁存器的时钟输入,用来存放加法器的运算结果。
标识为 2-1 选择器的方块是让你用一个开关来选择加法器的 B 端输入是取自第 2 排开关还是取自锁存器的 Q 端输出。当开关闭合时,就选择了用 8 位锁存器的输出作为 B 端输入。
[了解] 2-1 选择器使用了 8 个如下所示的电路。
如果选择端(Select)输入是 1,那么或门的输出和 B 端的输入就是一致的。这是因为上面与门的输出和 B 端输入是一样的,而下面与门的输出是 0。类似的,如果选择端的输入是 0,那么或门的输出则和 A 端输入一致。总结起来如下表所示。
改进后的加法器不能很好地处理进位输出(CO)信号。如果两个数的相加使得进位输出信号为 1,那么当下个数被加进来的时候,这个信号将被忽略掉。一个可能的解决方案是将加法器、锁存器、选择器均设置为 16 位宽,或者至少应该比你可能遇到的最大的和的位数多一位。这个问题留到后续部分具体讲述。
对于加法器来说,一个更好的改进方法是去掉一整排 8 个开关。但是首先要对 D 触发器做一些修改,为它加一个或门和一个称为清零(Clear)的输入信号。清零信号通常为 0,但当它为 1 时,Q 输出为 0,如下图所示。
无论其他信号是什么,清零信号总是强制使 Q 输出为 0,以达到使触发器清零的目的。
也许你还不明白为什么要设置这个信号,为什么不能通过把数据输入端置 0 和把时钟输入端置 1 来使触发器清零呢?这也许是因为我们无法精确控制数据端的输入信息的缘故。我们可能有一组 8 个锁存器,它们连着 8 位加法器的输出端,如下图所示。注意,标识为 “相加”(Add)的开关现在控制着锁存器的时钟输入。你可能会发现这个加法器比前面的那个好用,特别是当你需要加上一长串数字时。首先按下清零开关,这个操作会使锁存器的输出为 0,并且熄灭了所有的灯泡,同时使 8 位加法器的第 2 行输入全为 0。然后,通过开关输入第一个加数,并且闭合 “相加” 开关,这个加数的值就反映在灯泡上。再输入第二个加数并再次闭合 “相加” 开关。由开关输入的 8 位操作数加到前面的结果上,所得的和体现到灯泡上。反复如此操作,可以连续进行很多次加运算。
通过锁存器能够实现将多个数的相加。例如我们要计算 1 + 2 + 3,初始在 A 端输入 1,由于锁存器清零,所以 B 端输出 0,经过加法器相加得到 1,存入锁存器。之后 A 端输入 2,B 端接通锁存器则 B 端输出 1,通过加法器得到 3,同样结果 3 存入加法器。后续类似,结果通过灯泡的亮灭表示(亮即为 1)。
3 小结
编码:触发器(二)篇结合前文介绍的 R-S 触发器引出 D 型触发器,对 D 型触发器进行了介绍。为了精简内容删减了部分较为详细的书写,仅作为整理总结。