19__建立数据通路(下):指令+运算=CPU
文章目录
上一讲,我们讲解了时钟信号是怎么实现的,以及怎么利用这个时钟信号,来控制数据的读写,可以使得我们能把需要的数据“存储”下来。那么,这一讲,我们要让计算机“自动”跑起来。
通过一个时钟信号,我们可以实现计数器,这个会成为我们的 PC 寄存器。然后,我们还需要一个能够帮我们在内存里面寻找指定数据地址的译码器,以及解析读取到的机器指令的译码器。这样,我们就能把所有学习到的硬件组件串联起来,变成一个 CPU,实现我们在计算机指令的执行部分的运行步骤。
PC 寄存器所需要的计数器
我们常说的 PC 寄存器,还有个名字叫程序计数器。下面我们就来看看,它为什么叫作程序计数器。
有了时钟信号,我们可以提供定时的输入;有了 D 型触发器,我们可以在时钟信号控制的时间点写入数据。我们把这两个功能组合起来,就可以实现一个自动的计数器了。
加法器的两个输入,一个始终设置成 1,另外一个来自于一个 D 型触发器 A。我们把加法器的输出结果,写到这个 D 型触发器 A 里面。于是,D 型触发器里面的数据就会在固定的时钟信号为 1 的时候更新一次。
这样,我们就有了一个每过一个时钟周期,就能固定自增 1 的自动计数器了。这个自动计数器,可以拿来当我们的 PC 寄存器。事实上,PC 寄存器的这个 PC,英文就是 Program Counter,也就是程序计数器的意思。
每次自增之后,我们可以去对应的 D 型触发器里面取值,这也是我们下一条需要运行指令的地址。前面第 5 讲我们讲过,同一个程序的指令应该要顺序地存放在内存里面。这里就和前面对应上了,顺序地存放指令,就是为了让我们通过程序计数器就能定时地不断执行新指令。
加法计数、内存取值,乃至后面的命令执行,最终其实都是由我们一开始讲的时钟信号,来控制执行时间点和先后顺序的,这也是我们需要时序电路最核心的原因。
在最简单的情况下,我们需要让每一条指令,从程序计数,到获取指令、执行指令,都在一个时钟周期内完成。如果 PC 寄存器自增地太快,程序就会出错。因为前一次的运算结果还没有写回到对应的寄存器里面的时候,后面一条指令已经开始读取里面的数据来做下一次计算了。这个时候,如果我们的指令使用同样的寄存器,前一条指令的计算就会没有效果,计算结果就错了。
在这种设计下,我们需要在一个时钟周期里,确保执行完一条最复杂的 CPU 指令,也就是耗时最长的一条 CPU 指令。这样的 CPU 设计,我们称之为单指令周期处理器(Single Cycle Processor)。
很显然,这样的设计有点儿浪费。因为即便只调用一条非常简单的指令,我们也需要等待整个时钟周期的时间走完,才能执行下一条指令。在后面章节里我们会讲到,通过流水线技术进行性能优化,可以减少需要等待的时间,这里我们暂且说到这里。
读写数据所需要的译码器
现在,我们的数据能够存储在 D 型触发器里了。如果我们把很多个 D 型触发器放在一起,就可以形成一块很大的存储空间,甚至可以当成一块内存来用。像我现在手头这台电脑,有 16G 内存。那我们怎么才能知道,写入和读取的数据,是在这么大的内存的哪几个比特呢?
于是,我们就需要有一个电路,来完成“寻址”的工作。这个“寻址”电路,就是我们接下来要讲的译码器。
在现在实际使用的计算机里面,内存所使用的 DRAM,并不是通过上面的 D 型触发器来实现的,而是使用了一种 CMOS 芯片来实现的。不过,这并不影响我们从基础原理方面来理解译码器。在这里,我们还是可以把内存芯片,当成是很多个连在一起的 D 型触发器来实现的。
如果把“寻址”这件事情退化到最简单的情况,就是在两个地址中,去选择一个地址。这样的电路,我们叫作2-1 选择器。我把它的电路实现画在了这里。
我们通过一个反相器、两个与门和一个或门,就可以实现一个 2-1 选择器。通过控制反相器的输入是 0 还是 1,能够决定对应的输出信号,是和地址 A,还是地址 B 的输入信号一致。
2-1 选择器电路示意图
一个反向器只能有 0 和 1 这样两个状态,所以我们只能从两个地址中选择一个。如果输入的信号有三个不同的开关,我们就能从 2323
文章作者
上次更新 10100-01-10