这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战。
大家好,我是程栩,一个即将入职鹅厂的校招新人。本系列文章将会以一个演进的视角介绍计算机组成原理,并以一个采取Mips指令集的CPU作为范例。
大脑
面对着新的指令,我们有必要告诉我们的机器们,这些指令究竟是干嘛的。就和我们的alu代码一样,根据输入的值来决定做什么样的操作。这就像我们的大脑一样,来决定整个身体的部件的运转。
我们把这个模块称为控制器,也就是Control,由它来根据传入的指令进行信号的输出。如下图所示:
那么在Verilog层面上的表述,就很像我们的alu表示:
module control(opcode, out);
output[4:0] out; //结果
input[3:0] opcode; //命令
always@(opcode) begin
case(opcode)
4'b0000: out = 4'b0001;
…… //此处省略
4'b0110: out = 4'b0011;
endcase
end
endmodule
那么这些输出的信号都去哪里了呢? 我们不妨考虑一下数据存储器,我们会存储(store)数据,也会取出(load)数据,那么存储器并不会知道某个指令执行的时候应该进行读操作还是进行写操作,所以我们可以这样来做:
直接给DM传入我们指令的命令,然后DM根据我们的命令再去决定是读还是写,但是如果每个部件都需要经过传入命令再解析命令的流程的话,就显得浪费时间了。我们可以这样来做:
通过write和read两个一位的信号线来告诉DM该读还是写,但是聪明的你会发现,读写是两个相反的操作,读的时候不会写,写的时候也不会读,所以我们不妨设计成:
通过这一根信号线的高电平(1)还是低电平(0)来决定读还是写,而这个信号则是由控制器发出,如下图所示:
那么我们的指令在被载入以后,我们只需要在控制器这里做一次解析,即可生成全部的控制信号,从而控制所有的硬件的运作。
寄存器
除了我们的DM,我们仍然会有一些小数量的寄存器来存储运行时的一些数据,譬如在汇编中我们经常会用到的eap、exp等寄存器。这些寄存器一方面存储运行时候的运行信息,另一方面可以存储变量数据。使用寄存器可以让我们快速的进行数据的交互,而不需要每次都因为存取数据的延时而拖慢整体的节奏。
从结构上说,寄存器和DM差不多,都是数据存储的场所,如下图:
那么我们为什么不加更多的寄存器呢?
简单来说,寄存器的造价比较贵,而且研究表明,过多的寄存器反而会降低CPU的运算速率。
到现在,我们有了一个计算的算逻单元(alu),一个程序控制器(pc),一个指令存储器(IM),一个数据存储器(DM),还有一系列的寄存器,我们如何把他们组合到一起呢?而与他们相匹配的指令集又该如何设计呢?
到这里我们大概的说了一些组成的概念,接下来我们会以实际的例子进行讲解,包括指令集、CPU结构,并且用指令一步一步的画出运行的过程,希望大家喜欢。
我们明天再见!