极客时间已完结课程限时免费阅读

18 | 建立数据通路(中):指令+运算=CPU

18 | 建立数据通路(中):指令+运算=CPU-极客时间

18 | 建立数据通路(中):指令+运算=CPU

讲述:徐文浩

时长10:35大小9.67M

上一讲,我们看到,要能够实现一个完整的 CPU 功能,除了加法器这样的电路之外,我们还需要实现其他功能的电路。其中有一些电路,和我们实现过的加法器一样,只需要给定输入,就能得到固定的输出。这样的电路,我们称之为组合逻辑电路(Combinational Logic Circuit)。
但是,光有组合逻辑电路是不够的。你可以想一下,如果只有组合逻辑电路,我们的 CPU 会是什么样的?电路输入是确定的,对应的输出自然也就确定了。那么,我们要进行不同的计算,就要去手动拨动各种开关,来改变电路的开闭状态。这样的计算机,不像我们现在每天用的功能强大的电子计算机,反倒更像古老的计算尺或者机械计算机,干不了太复杂的工作,只能协助我们完成一些计算工作。
这样,我们就需要引入第二类的电路,也就是时序逻辑电路(Sequential Logic Circuit)。时序逻辑电路可以帮我们解决这样几个问题。
第一个就是自动运行的问题。时序电路接通之后可以不停地开启和关闭开关,进入一个自动运行的状态。这个使得我们上一讲说的,控制器不停地让 PC 寄存器自增读取下一条指令成为可能。
第二个是存储的问题。通过时序电路实现的触发器,能把计算结果存储在特定的电路里面,而不是像组合逻辑电路那样,一旦输入有任何改变,对应的输出也会改变。
第三个本质上解决了各个功能按照时序协调的问题。无论是程序实现的软件指令,还是到硬件层面,各种指令的操作都有先后的顺序要求。时序电路使得不同的事件按照时间顺序发生。

时钟信号的硬件实现

想要实现时序逻辑电路,第一步我们需要的就是一个时钟。我在第 3 讲说过,CPU 的主频是由一个晶体振荡器来实现的,而这个晶体振荡器生成的电路信号,就是我们的时钟信号。
实现这样一个电路,和我们之前讲的,通过电的磁效应产生开关信号的方法是一样的。只不过,这里的磁性开关,打开的不再是后续的线路,而是当前的线路。
在下面这张图里你可以看到,我们在原先一般只放一个开关的信号输入端,放上了两个开关。一个开关 A,一开始是断开的,由我们手工控制;另外一个开关 B,一开始是合上的,磁性线圈对准一开始就合上的开关 B。
于是,一旦我们合上开关 A,磁性线圈就会通电,产生磁性,开关 B 就会从合上变成断开。一旦这个开关断开了,电路就中断了,磁性线圈就失去了磁性。于是,开关 B 又会弹回到合上的状态。这样一来,电路接通,线圈又有了磁性。我们的电路就会来回不断地在开启、关闭这两个状态中切换。
开关 A 闭合(也就是相当于接通电路之后),开关 B 就会不停地在开和关之间切换,生成对应的时钟信号
这个不断切换的过程,对于下游电路来说,就是不断地产生新的 0 和 1 这样的信号。如果你在下游的电路上接上一个灯泡,就会发现这个灯泡在亮和暗之间不停切换。这个按照固定的周期不断在 0 和 1 之间切换的信号,就是我们的时钟信号(Clock Signal)。
一般这样产生的时钟信号,就像你在各种教科书图例中看到的一样,是一个振荡产生的 0、1 信号。
时钟信号示意图
这种电路,其实就相当于把电路的输出信号作为输入信号,再回到当前电路。这样的电路构造方式呢,我们叫作反馈电路(Feedback Circuit)。
接下来,我们还会看到更多的反馈电路。上面这个反馈电路一般可以用下面这个示意图来表示,其实就是一个输出结果接回输入的反相器(Inverter),也就是我们之前讲过的非门
通过一个反相器实现时钟信号

通过 D 触发器实现存储功能

有了时钟信号,我们的系统里就有了一个像“自动门”一样的开关。利用这个开关和相同的反馈电路,我们就可以构造出一个有“记忆”功能的电路。这个有记忆功能的电路,可以实现在 CPU 中用来存储计算结果的寄存器,也可以用来实现计算机五大组成部分之一的存储器。
我们先来看下面这个 RS 触发器电路。这个电路由两个或非门电路组成。我在图里面,把它标成了 A 和 B。
或非门的真值表
在这个电路一开始,输入开关都是关闭的,所以或非门(NOR)A 的输入是 0 和 0。对应到我列的这个真值表,输出就是 1。而或非门 B 的输入是 0 和 A 的输出 1,对应输出就是 0。B 的输出 0 反馈到 A,和之前的输入没有变化,A 的输出仍然是 1。而整个电路的输出 Q,也就是 0。
当我们把 A 前面的开关 R 合上的时候,A 的输入变成了 1 和 0,输出就变成了 0,对应 B 的输入变成 0 和 0,输出就变成了 1。B 的输出 1 反馈给到了 A,A 的输入变成了 1 和 1,输出仍然是 0。所以把 A 的开关合上之后,电路仍然是稳定的,不会像晶振那样振荡,但是整个电路的输出 Q 变成了 1。
这个时候,如果我们再把 A 前面的开关 R 打开,A 的输入变成和 1 和 0,输出还是 0,对应的 B 的输入没有变化,输出也还是 1。B 的输出 1 反馈给到了 A,A 的输入变成了 1 和 0,输出仍然是 0。这个时候,电路仍然稳定。开关 R 和 S 的状态和上面的第一步是一样的,但是最终的输出 Q 仍然是 1,和第 1 步里 Q 状态是相反的。我们的输入和刚才第二步的开关状态不一样,但是输出结果仍然保留在了第 2 步时的输出没有发生变化。
这个时候,只有我们再去关闭下面的开关 S,才可以看到,这个时候,B 有一个输入必然是 1,所以 B 的输出必然是 0,也就是电路的最终输出 Q 必然是 0。
这样一个电路,我们称之为触发器(Flip-Flop)。接通开关 R,输出变为 1,即使断开开关,输出还是 1 不变。接通开关 S,输出变为 0,即使断开开关,输出也还是 0。也就是,当两个开关都断开的时候,最终的输出结果,取决于之前动作的输出结果,这个也就是我们说的记忆功能
这里的这个电路是最简单的 RS 触发器,也就是所谓的复位置位触发器(Reset-Set Flip Flop) 。对应的输出结果的真值表,你可以看下面这个表格。可以看到,当两个开关都是 0 的时候,对应的输出不是 1 或者 0,而是和 Q 的上一个状态一致。
再往这个电路里加两个与门和一个小小的时钟信号,我们就可以实现一个利用时钟信号来操作一个电路了。这个电路可以帮我们实现什么时候可以往 Q 里写入数据。
我们看看下面这个电路,这个在我们的上面的 R-S 触发器基础之上,在 R 和 S 开关之后,加入了两个与门,同时给这两个与门加入了一个时钟信号 CLK 作为电路输入。
这样,当时钟信号 CLK 在低电平的时候,与门的输入里有一个 0,两个实际的 R 和 S 后的与门的输出必然是 0。也就是说,无论我们怎么按 R 和 S 的开关,根据 R-S 触发器的真值表,对应的 Q 的输出都不会发生变化。
只有当时钟信号 CLK 在高电平的时候,与门的一个输入是 1,输出结果完全取决于 R 和 S 的开关。我们可以在这个时候,通过开关 R 和 S,来决定对应 Q 的输出。
通过一个时钟信号,我们可以在特定的时间对输出的 Q 进行写入操作
如果这个时候,我们让 R 和 S 的开关,也用一个反相器连起来,也就是通过同一个开关控制 R 和 S。只要 CLK 信号是 1,R 和 S 就可以设置输出 Q。而当 CLK 信号是 0 的时候,无论 R 和 S 怎么设置,输出信号 Q 是不变的。这样,这个电路就成了我们最常用的 D 型触发器。用来控制 R 和 S 这两个开关的信号呢,我们视作一个输入的数据信号 D,也就是 Data,这就是 D 型触发器的由来。
把 R 和 S 两个信号通过一个反相器合并,我们可以通过一个数据信号 D 进行 Q 的写入操作
一个 D 型触发器,只能控制 1 个比特的读写,但是如果我们同时拿出多个 D 型触发器并列在一起,并且把用同一个 CLK 信号控制作为所有 D 型触发器的开关,这就变成了一个 N 位的 D 型触发器,也就可以同时控制 N 位的读写。
CPU 里面的寄存器可以直接通过 D 型触发器来构造。我们可以在 D 型触发器的基础上,加上更多的开关,来实现清 0 或者全部置为 1 这样的快捷操作。

总结延伸

好了,到了这里,我们可以顺一顺思路了。通过引入了时序电路,我们终于可以把数据“存储”下来了。我们通过反馈电路,创建了时钟信号,然后再利用这个时钟信号和门电路组合,实现了“状态记忆”的功能。
电路的输出信号不单单取决于当前的输入信号,还要取决于输出信号之前的状态。最常见的这个电路就是我们的 D 触发器,它也是我们实际在 CPU 内实现存储功能的寄存器的实现方式。
这也是现代计算机体系结构中的“冯·诺伊曼”机的一个关键,就是程序需要可以“存储”,而不是靠固定的线路连接或者手工拨动开关,来实现计算机的可存储和可编程的功能。
有了时钟信号和触发器之后,我们还差一个“自动”需求没有实现。我们的计算机还不能做到自动地不停地从内存里面读取指令去执行。这一部分,我们留在下一讲。下一讲里,我们看看怎么让程序自动运转起来。

推荐阅读

想要深入了解计算机里面的各种功能组件,是怎么通过电路来实现的,推荐你去阅读《编码:隐匿在计算机软硬件背后的语言》这本书的第 14 章和 16 章。
如果对于数字电路和数字逻辑特别感兴趣,想要彻底弄清楚数字电路、时序逻辑电路,也可以看一看计算机学科的一本专业的教科书《数字逻辑应用与设计》。

课后思考

现在我们的 CPU 主频非常高了,通常在几 GHz 了,但是实际上我们的晶振并不能提供这么高的频率,而是通过“外频 + 倍频“的方式来实现高频率的时钟信号。请你研究一下,倍频和分频的信号是通过什么样的电路实现的?
欢迎留言和我分享你的疑惑和见解,也欢迎你把今天的内容分享给你的朋友,和他一起学习和进步。
分享给需要的人,Ta购买本课程,你将得20
生成海报并分享

赞 39

提建议

上一篇
17 | 建立数据通路(上):指令+运算=CPU
下一篇
19 | 建立数据通路(下):指令+运算=CPU
unpreview
 写留言

精选留言(43)

  • 空知
    2019-06-09
    接通R 断开S 结果是 1 RS触发器的真值表 是不是写反了呀
    共 3 条评论
    26
  • linxi
    2021-10-23
    “打开”、“关闭”、“合上”这些词语有时候真的会产生歧义,建议用“闭合”、“断开”这样的词
    共 2 条评论
    15
  • LeeLink
    2020-01-05
    这一部分真一点没看懂,好头疼。

    作者回复: LeeLink同学, 你好,可以先跳过,囫囵吞枣读完之后再回头来看。

    共 4 条评论
    15
  • senekis
    2019-06-10
    老师的课程很精彩,以前都没有好好学,看了受益匪浅,《编码:隐匿在计算机软硬件背后的语言》 和《数字逻辑应用与设计》这两本书都买了,一定要坚持看完啊!!!

    作者回复: 加油 👍,推荐先看完《编码》。

    共 2 条评论
    12
  • 拓山
    2019-10-04
    编码一书看完了 这段内容理解的比较容易
    共 1 条评论
    11
  • 记事本
    2019-10-12
    上大学的时候就学习过触发器,那会儿压根就不知道触发器是做什么用的…谢谢老师!
    共 3 条评论
    7
  • A君
    2020-06-25
    时钟信号用个非门就可以构建,反馈电路还可以用于两两组合做成记忆电路,所谓记忆电路,就是电路会持续输出上次电路改动时的输出结果。
    5
  • LDxy
    2019-06-05
    n分之一分频器可以使用n进制计数器实现,n进制计数器的进位输出端的频率即为输入时钟信号频率的n分之一。 n倍频器可以由锁相环加n分之一分频器实现。锁相环是一个反馈环路,这个环路里面有一个叫鉴相器的部件,外部输入信号f0会进入鉴相器,同时锁相环输出端的信号f1也会反馈到鉴相器的另一个输入端,鉴相器会比较f0与f1的相位差,输出一个变化的电压信号去控制锁相环的其他部件,从而调整输出信号f1的频率。总的来说,锁相环的基本功能就是使得输出端的信号f1与输入端信号f0的相位差维持恒定,所以名为「锁相环」。如上所述,如果f1直接反馈回到鉴相器,为了维持相位差恒定,会有输出信号f1=f0。如果将f1经过n分之一分频器得到信号f2再反馈回到鉴相器,即将f2=f1/n与f0输入鉴相器比较相位。此时,为了维持f2与f0的相位差恒定,鉴相器会输出一个电压信号控制锁相环的其他部件,调整输出信号f1,使得f0=f2。此时,锁相环的输出信号f1=n*f2=n*f0。从而实现n倍频。
    展开
    4
  • Monday
    2020-05-19
    1、或非门的真值表图,表示看不懂,不应该如下吗? 输入1 输入2 结果 0 0 1 0 1 0 1 0 0 1 1 0 2、RS触发器真值表,也有问题吧,正确的我理解如下: S R Q 0 0 Q 0 1 1 1 0 0 1 1 0
    展开
    共 3 条评论
    3
  • Leoorz
    2020-01-21
    今天用一天的时间读了《编码:隐匿在计算机软硬件背后的语言》关于触发器的章节,仔仔细细地每个图都自己分析并画了好几遍,终于把level-triggered/edge-triggered D-type flip-flop搞清楚了 分频书中有讲,采用多个 edge-triggered 触发器级联的方式,~Q作为反馈信号输入至D,并将上一级触发器的~Q作为当前触发器的CLK信号输入,Q输出即为降频的时钟信号 倍频这个暂时不清楚,待继续学习
    展开

    作者回复: 👍

    3
  • 浮夸,
    2020-01-04
    D触发器实战😄
    3
  • w 🍍
    2019-09-26
    “如果这个时候,我们让 R 和 S 的开关,也用一个反相器连起来” 这有什么用,不是很明白

    作者回复: 这个会确保R和S的状态永远是相反的。R是1的时候S就是0,R是0的时候S就是1。

    共 2 条评论
    3
  • Ant
    2019-06-05
    囫囵吞枣的看了,晶体振荡器的实现原理
    3
  • 易儿易
    2019-06-05
    老师,最后一张图,加入反向器之后,不太明白如何用信号D同时控制R-S两个开关……看了之前反向器的介绍,还是没理解……是D输入0之后,R收到1,S收到0,D输入1,R收到0,S收到1吗?
    共 2 条评论
    3
  • 开心
    2019-06-19
    没有时钟信号也可以存储了呀,时钟信号在这里的作用是什么呢~
    共 1 条评论
    2
  • 鱼向北游
    2019-06-05
    分频用计数器就可以吧 从0开始计数模n 归零就来个输入 应该根据此原理用d触发器+计数器有优化的方法 倍频数学的方法叫时域信号傅里叶级数展开到频域 然后滤波器滤专门那个频滤 电路的方法我编不下去了。。。 老师解答吧
    2
  • 🗿顾晓峰🈹🈳�...
    2019-10-23
    买一本CSAPP就可以了,其他上网查一下。
    共 1 条评论
    1
  • -W.LI-
    2019-06-22
    老师好!我虽然是计算机专业的,就是那种计组,操作系统这些课大几学的都不知道那种。现在回头学从哪本开始看好啊。不过你的课能看懂就是有点费力,理解不深脱了课件自己想回忆就费力。
    1
  • Suwian
    2022-12-16 来自福建
    RS触发器的,R跟S应该是搞反了,R:Reset,S:Set,R用来做复位操作,所以R输入高电平,Q应该为0的
  • 云龙
    2022-09-16 来自北京
    时钟信号在这里有什么用处