learn-tech/专栏/深入浅出计算机组成原理/18建立数据通路(中):指令加运算=CPU.md
2024-10-16 09:22:22 +08:00

114 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

因收到Google相关通知网站将会择期关闭。相关通知内容
18 建立数据通路(中):指令加运算=CPU
上一讲,我们看到,要能够实现一个完整的 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。
或非门的真值表
在这个电路一开始输入开关都是关闭的所以或非门NORA 的输入是 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 反馈给到了 AA 的输入变成了 1 和 1输出仍然是 0。所以把 A 的开关合上之后,电路仍然是稳定的,不会像晶振那样振荡,但是整个电路的输出 Q变成了 1。
这个时候,如果我们再把 A 前面的开关 R 打开A 的输入变成和 1 和 0输出还是 0对应的 B 的输入没有变化,输出也还是 1。B 的输出 1 反馈给到了 AA 的输入变成了 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 信号是 1R 和 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 章。
如果对于数字电路和数字逻辑特别感兴趣,想要彻底弄清楚数字电路、时序逻辑电路,也可以看一看计算机学科的一本专业的教科书《数字逻辑应用与设计》。