在上一个章节中,我们已经了解了一个存储是如何制作出来的,利用这个存储我们就可以做一个最简单的CPU
指令
我们知道CPU负责执行计算机的程序,而程序其实是一个个的操作指令
比如可能是计算指令,cpu会指示ALU进行加减运算
也可能是存储指令,cpu进行内存数据的读写
我们这里给出一个指令表,给cpu支持的所有指令进行一个编号,假设指令都是8bit的数据
前4位为操作码,后4位为地址或者特定寄存器
我们就根据一个程序的执行来组合一个CPU
cpu组合
首先我们需要一个内存,直接使用用上一个章节的RAM
然后我们需要四个寄存器,用来临时存储运算过程中的数据
我们还需要两个寄存器来完成CPU
1. 一个寄存器来追踪程序运行到哪里了,我们叫它“指令地址寄存器(Instruction Address Register)”, 用来存储当前的指令地址
2. 另一个寄存器来存储当前的指令,就叫“指令寄存器(Instrctuion Register)”
当程序开始的时候所有存储的数据都是0000, 这里接给出了所有需要的存储的内容
我们使用上面假设的指令表,在RAM里面放了一个程序,我们跟着这个程序画出CPU的其他部分
CPU运行
取指令阶段(Fetch Phase)
cpu运行的第一个阶段叫取指令阶段, 首先指令地址寄存器链接到RAM, 由于指令地址寄存器数据是0, 就从RAM中读取地址为0的数据进入指令寄存器
解码阶段(Decode Phase)
现在指令拿到了,需要知道是什么指令,才能运行它,这就是阶段阶段
可以看到第一个指令是 0010 1110
前四位 0010 就是LOAD_A 指令
意思就是把 后四位的地址的值放置到寄存器A内, 后四位 1110转成10进制是14,也就是RAM地址14的数据, 我们可以看到RAM地址14的数据是 0000 0011, 也就是把0000 0011 放入寄存器A,这个数据十进制是3,也就是寄存器A此时保存的数据为3
这里就需要一个“控制单元” 来识别这个LOAD_A的指令, 将它转化成对应的操作
我们用一个简单的逻辑门来判断指令是不是 0010(LOAD_A), 如果这个输出为1的话代表执行LOAD_A的操作, 将这个“控制单元”放入整体的cpu中进行特定的链接就是执行的操作
执行阶段(Execute Phase)
经过控制电路后,我们需要读取RAM地址14的数据到寄存器A,所以需要打开RAM的允许读取线以及寄存器A的允许写入线, 并且将寄存器A和RAM的数据线进行连接
这样就完成了一个CPU的指令循环,完成指令后,就关闭所有的线路,将所有的允许写入和读取都关闭,即完成了存储
最后将指令地址寄存器+1,执行阶段就此结束
LOAD_A 只是其中一种指令,控制单元需要识别各种执行,将其转化成各种指令操作,我们可以再进行一层的抽象,将控制单元抽象成一个块,这样就简洁一些
循环
由于指令地址+1, 我们进入了下一个循环, 重新进行读取阶段
将RAM地址1的数据读到指令寄存器中
可以看到 0001 1111, 前4位对应操作为LOAD_B,后四位代表的地址为15
即将RAM地址15的数据 0000 1110 读到寄存器B, 也就是寄存器B此时保存的数据是十进制的14
此时指令地址寄存器再次+1, 完成第二个循环
第三个循环后,将RAM地址2读入地址寄存器,可以看到具体指令为 1000 0100
代表加法指令,后面跟的就是不RAM地址,而是两个寄存器地址,01代表寄存器B,00代表寄存器A, 意思是将寄存器B的数据加到寄存器A, 保存在寄存器A的意思。
为了执行加法操作,需要使用到上一章的ALU进行加法操作
控制单元需要将加法操作给到ALU,并将寄存器A/B的数据输入到ALU,此时计算结果不能直接存储到寄存器A,否则就会不断进行加法操作, 控制单元需要用自己的寄存器保存计算结果,关闭ALU之后,再将数据写到寄存器A
这里进行加法操作3+14 =17, 也就是寄存器A此时保存数据为17,也即是 0001 0001, 最后指令地址寄存器+1, 循环完成
此时开始最后一个循环,RAM地址为3的数据读入0100 1101,根据前4位得到指令
意思是把寄存器A的数据保存到,后四位的RAM地址 1101(十进制15)中
指令地址寄存器再+1,读入RAM地址4的数据为 0000 0000, 程序停止
可以看到我们用4个执行,计算了一个3+14=17,并将结果存储到RAM地址15
可以看到CPU就是在不断循环进行 读取,解码,执行的操作, 那是什么来管理cpu的节奏呢?
答案是时钟
时钟以一个精确的间隔触发电信号,而控制单元根据电信号触发不同的操作,来让cpu不断运行
cpu完成一次 取指令->解码->执行的循环叫做时钟速度
这样一个最简单的CPU就完成了
上一章:
寄存器和内存 - 计算机组成原理(五)