计算机系统解密:从理解计算机到编写高效代码
上QQ阅读APP看书,第一时间看更新

3.1 表示时间

无论在历史上还是现如今,我们都使用周期函数来衡量时间,如地球的自转和公转。我们把一个完整的地球自转看作一天,这一天又细分为更小的单位,如时、分、秒。由于一天有86 400秒,因此我们把地球自转的1/86 400定义为一秒。

除了利用像地球自转这样的外部事件外,我们也可以使用某些物理现象(如钟摆摆动所需的时间)来生成周期函数。就是摆动时长代表时间这项技术,让老爷钟里有了“滴答滴答”的声音。当然为了让钟摆更有应用价值,摆锤必须校准到摆过一秒钟所需的标准长度。

计算机与电子学有关,所以需要一个周期性的电子信号。我们可以通过放置一些开关来产生电信号,它们就像钟摆一样生成信号。不过,除非你是一个严肃的蒸汽朋克玩家,否则很可能还是不太想要一台钟摆驱动的计算机。下一节将介绍一些更现代的方法。

3.1.1 振荡器

来看看我们用反相器做的小把戏:把输入和输出连接起来,如图3-1所示。

图3-1 振荡器

把输入和输出连接起来将产生反馈,就像麦克风离扬声器太近时产生的效果一样。反相器的输出在0和1之间来回反弹,或者称之为振荡。振荡的速度是传播延迟的函数(见2.4.3节),而传播延迟会随着温度而变化。频率稳定的振荡器很有应用价值,它可以生成精确的时间参考。

用晶体制作振荡器是一种经济有效的方法,这个想法还挺新潮!晶体,像磁铁一样,与电流有某种关系。如果把电极(电线)连接到晶体上,然后向晶体施加压力,它就会产生电流。如果在与晶体连接的电线上通电流,晶体就会弯曲。这就是所谓的压电效应,是Paul Jacques兄弟(1855—1941)和Pierre Curie(1859—1906)在19世纪末发现的。压电效应有各种各样的应用。晶体可以接收声音振动,因而可以应用到麦克风中。晶体通电后产生的声音振动会使电器发出恼人的蜂鸣声。电路图中的晶体符号如图3-2所示。

图3-2 晶体原理图符号

晶体振荡器利用电子单极双掷开关交替向晶体充电和放电。充电和放电所需的时间是可以预测的,而且非常准确。石英是最好的晶体材料之一,这也是你会看到精确石英钟表的广告的原因。当你在商店里看到高级石英手表的标价时,别忘了一块好的石英售价大约只有25美分。

3.1.2 时钟

振荡器给我们提供了一种测量时间的方法。显而易见,计算机需要保证准时,比如能够以同一速度播放视频。但时间之所以很重要还有另一个原因。在第2章中,我们讨论了传播延迟如何影响电路工作所需的时间。时间为我们提供了一种方法,例如,等待加法器最坏情况下的延迟,然后再查看结果,这样我们就知道它是稳定和正确的。

振荡器为计算机提供了时钟。计算机的时钟就像军乐队中的鼓手,为电路设定节奏。最大的时钟频率或最快的节奏由传播延迟决定。

元件制造涉及大量的统计数据,因为不同的零件之间差异很大。分选过程根据测量到的特性,将元件放入不同的箱或堆。速度最快、价格最高的部件放进一个箱,速度较慢、价格较低的部件放进另一个箱,以此类推。拥有无限多的箱是不切实际的,所以即使箱中部件的差异比所有部件间的差异要小,但还是会有差异。这就是传播延迟被指定为一个范围的原因,生产厂家除了提供一个典型值外,还要提供最小值和最大值。一个常见的逻辑电路设计错误是使用典型值,而不使用最小值和最大值。超频计算机其实是在赌计算机的部件在概率上处于箱的中间,并且时钟可以在不导致部件失效的情况下增加频率。

3.1.3 锁存器

既然有了时间源,我们来试着记住一个单独的信息位。我们可以通过反馈来做到这一点,比如将OR门的输出与输入绑定,如图3-3所示。因为没有反相器,所以输入与输出绑定不会像图3-1那样产生一个振荡器。假设图3-3中的电路输出初始为0。如果输入为1,输出也变为1,而且由于输出连接到了另一个输入端,所以即使输入变回0,输出也会保持不变,换句话说,输出记得它的值。

图3-3 OR门锁存器

当然,完成这个方案还需要一些工作,因为它没有办法再使输出为0。我们需要通过断开反馈来重置输出,如图3-4所示。

图3-4 AND-OR门锁存器

请注意,我们已经把反相器的输出标为086-03。把横线加在符号之上是硬件语言,意思是“相反的”。这代表着某事物为0时为真,为1时为假。有时这被称为低电平有效,而不是高电平有效,意思是当它是0而非1的时候,它会主动触发。字符上横线的发音是“bar”,所以086-03读作“reset bar”。

当reset为低电平时,086-03为高电平,因此OR门的输出被反馈给输入。当reset为高电平时,086-03为低电平,打破了反馈,所以输出是0。

图3-5表示了一个S-R锁存器,它是建立位存储器的一个稍微聪明一点的方法。S-R代表set-reset。它有低电平有效输入和与输入互补的输出,即输入是低电平有效,输出是高电平有效。也可以使用NOR门来构建一个高电平有效输入的版本,但NOR门通常比NAND门更耗电,除此之外,也更复杂,建造成本更高。

图3-5 S-R锁存器

086-04086-03都活动时(高电平)的情况很奇怪,一般不会使用这种情况下的电路,因为两个输出都是真。另外,如果两个输入同时不活动(由高电平跳变到低电平)(即从0过渡为1),输出的状态将不可预测,因为它取决于传播延迟。

图3-5中的电路有一个图3-4中电路没有的很好的特性,即电路设计是对称的。这意味着set信号和reset信号的传播延迟都是相似的。

3.1.4 锁存器组成的门电路

既然已经有了一些记忆信息的方法,现在一起来看在某个时间点记住某件事情需要什么。图3-6所示的电路在输出端添加了一对门。

图3-6 S-R锁存器门电路

可以看到,当087-03输入不活动(高电平)时,是不受086-04086-03影响的。由于S门和R门的输入都为1,输出不会改变。

因为我们想记住一位的信息,接下来我们可以做的改进是在086-04086-03输入之间加一个反相器,这样只需要一个数据输入(简写为D)即可。图3-7展示了修改后的电路。

图3-7 D锁存器门电路

087-03处于低电平时,如果D为1时,输出Q将被设置为1。同理,当087-03处于低电平时,如果D为0,输出Q会被设定为0。当087-03处于高电平时,D的改变对输出Q没有影响。这意味着D的状态可以被记住。图3-8的时序图展示了这个原理。

图3-8 D锁存器门电路的时序图

这个电路的问题是当087-03处于低电平时,D值的变化就会通过,如图3-8阴影区域所示。这意味着我们得指望D是“行为良好”的,并且在“门”处于“打开”状态时不会改变。如果可以使打开这一操作瞬间完成,就更好了。我们将在下一节介绍如何做到这一点。

3.1.5 触发器

正如上一节中讨论的那样,我们希望最大限度地减少因数据更改导致错误结果的概率。通常的方法是使用逻辑电平之间的过渡来获取数据,而不是在逻辑电平具有特定值时获取数据。这些过渡称为边沿。你可以将边沿视为时间的决策衡量准则。回到图3-8,可以看到逻辑电平之间几乎发生瞬时过渡。边沿触发的锁存器称为触发器。

锁存器是用来制作触发器的构件。我们可以通过巧妙地组合三个S-R锁存器来构造一个称为D触发器的上升沿触发触发器,如图3-9所示。上升沿触发意味着触发器作用于从逻辑0到逻辑1的转换;而对于下降沿触发,触发器将作用于从逻辑1到逻辑0的转换。

图3-9 D触发器的设计

图3-9所示的电路有些令人难以置信。右边的两个门构成了一个S-R锁存器。从图3-5可以知道,除非088-04088-05变成低电平,否则输出不会改变。

图3-10展示了电路在不同的D值和时钟下的表现。细线表示逻辑0,粗线表示逻辑1。

图3-10 D触发器的活动

从左侧开始,可以看到当时钟为0时,088-04088-05都为高电平,所以图3-9右侧的锁存器状态不变,D值无关紧要。再往右看,第2、3两幅图中,如果088-05为低电平,更改D值无效。同样,最右边的两个图显示,如果088-04为低电平,则更改D值无效。因此,无论时钟为高电平还是低电平,D值的更改均不起作用。

我们来看一下时钟从低电平变化到高电平时会发生什么,如图3-11所示。

图3-11 D触发器的上升沿活动

可以在图3-11的左边看到,当时钟为低电平而D值为高电平时,088-04088-05都为高电平,所以锁存器状态没什么变化。但当时钟变为1,088-04变为低电平时,就会改变触发器的状态。在图3-11的右边,可以看到当D值为低电平而时钟变成高电平时也有类似的变化,即会引起088-05变低电平并且改变触发器状态。从图3-11可以看出,其他的改变都无关紧要,不会产生什么影响。

1918年,英国物理学家William Eccles和Frank Jordan发明了第一个电子版触发器,这个触发器使用真空管制作。图3-12展示了一个稍微不那么古老的D触发器7474的简图。

图3-12 D触发器7474

D触发器具有互补的Q090-04输出以及088-04(设置)和088-05(复位)输入。这有点令人困惑,因为图中显示的是SR,而不是088-04088-05;实际上,正是SR和○的结合使它们成了088-04088-05。所以,除了左边神秘的部分,它就像我们的S-R锁存器。神秘的部分是两个额外的输入,D代表数据,CK代表时钟(用三角形表示)。它是上升沿触发的,所以只要CK上的信号从0变为1,D输入的值就会被存储起来。

除传播延迟外,边沿触发设备还有其他定时考虑因素,比如建立时间,即在时钟边沿之前信号必须稳定的时间量,以及保持时间,即时钟边沿之后信号必须稳定的时间量,如图3-13所示。

图3-13 建立及保持时间

如你所见,除了在时钟边沿周围的建立时间和保持时间期间,其他时间不必关心D输入上发生了什么。而且,与其他逻辑电路一样,输出在传播延迟时间之后是稳定的,而且独立于D输入保持稳定。建立时间和保持时间通常用tsetupthold表示。

触发器的边沿行为与时钟配合得很好。我们将在下一节中给出示例。

3.1.6 计数器

计数是触发器的一个常见应用。例如,我们可以计算振荡器的时间,并用解码器驱动显示器来制作数字时钟。图3-14展示了一个产生3位数字(C2C1C0)的电路,这3位数字表示信号从0变为1的次数。086-03信号可用来把计数器设置为0。

图3-14 3位的纹波计数器

图3-14所示的计数器之所以被称为纹波计数器是因为其结果就像纹波一样从左到右计数,而不是因为它可以用来数瓶装廉价酒的数量。C0改变C1C1改变C2,如果有更多的位的话,以此类推。由于每个触发器的D输入都与090-04输出相连,因此在每次CK信号正跃迁时,都会改变状态。

它也被称为异步计数器,因为每件事都是在它到来的时候才发生。异步系统的问题是很难知道何时查看结果。输出(C2C1C0)在波动期间无效。从图3-15可以看到为何得到每个连续位的结果都需要花费更长的时间,图中灰色区域表示由于传播延迟而未被定义的值。

图3-15 纹波计数器的时序

左边的时序图显示,在传播延迟消除后,我们得到了一个有效的3位数字。但是在右边的时序图,可以看到我们试图用比传播延迟允许的更快的速度进行计数,因此并非任何时间都能产生有效的数字。

这是我们在图2-41中看到的行波进位加法器问题的变体。正如能够用超前进位设计解决这个问题一样,我们也可以通过同步计数器设计来解决纹波问题。

与纹波计数器不同,同步计数器在同一时间(同步)输出所有变化。这意味着所有的触发器都是并行计时的。3位的同步计数器如图3-16所示。

图3-16 3位的同步计数器

可以看到计数器中的所有触发器都同时改变状态,因为它们都是在同一时间开始计时的。尽管传播延迟仍然是判断输出何时有效的一个影响因素,但是级联效应已经被消除。

计数器也是一种功能构件,这意味着它们有自己的原理图符号。在本例中,它是一个矩形框,如图3-17所示。

图3-17 计数器的原理图符号

图3-17中包含了一些我们以前从未见过的输入。计数器可以操作部分或全部的这些输入。大多数计数器都有清理计数器的CLR输入,可以将计数器设置为0。同样常见的是EN输入,它可以启动计数器来计数,除非启用,否则计数器不计数。一些计数器可以在任意方向上计数,使用092-03输入即可选择向上或向下。最后,一些计数器具有数据输入D0–n和负载信号LD(允许将计数器设置为特定值)。

有了计数器,我们就可以用它们来记录时间。但计数并不是我们能用触发器做的唯一事情。下一节将开始介绍如何记住大量信息。

3.1.7 寄存器

D触发器有利于计算机记忆。D触发器的一个很常见的应用是它可以制作寄存器,寄存器是一个包中的一堆共享同一时钟的D触发器。图3-18显示了保存前面讨论的加法器电路加法结果的寄存器示例。

图3-18 保存加法结果的寄存器

一旦加法器的输出被记录到寄存器中,操作数发生改变不会让结果也改变。请注意,寄存器通常具有与计数器类似的使能输入。