造个计算机--1、设计运算器

话接上文:  造个计算机

废话少说,先聊聊我们要造的这个计算机的硬件结构,本项目(整体计划的实现,对于个人来说算个小project吧,权当上劳动实验课了)的目标是一个模型级的计算机,因此本着只要五脏俱全,不管是麻雀还是老鼠,只要包含主要结构就行。首先百度点基础知识先科普一下。   

冯诺依曼体系结构

冯氏结构是基本上目前市场上所有看到的通用计算机采用的结构,从我们见到的PC到各种平板电脑,到手机,几乎全部都是这个结构(如果有专利费的,估计能够收不少,可惜老冯早逝)简单来说,如图所示:


冯诺依曼计算机体系结构图

关于这个结构的详细的、专业的介绍,请参考百度百科: 冯·诺依曼结构, 冯·诺依曼体系结构

还好本项目的主要目标是把这样一个模型给的玩意给造出来,就跟造车模一样,能跑就行,至于原理术语什么的,知道和不知道对于这个事情来说区别不大,因此如果打开看不懂的话,也丝毫不影响接下来的工作。

简单解释一下:

1、 输入设备: 就是不断往对着电脑输入信息的东西,最原始古老的当然是键盘,但是从广义上来说,所有各种往计算机/手机里面能够用于辅助把信息传入的设备都算,鼠标啊,摄像头,指纹识别,(当然,手指头不算,严格来说,手指头所接触的那一层电容屏幕算),在本项目里面,当然,我们只考虑键盘,最标准最简单的键盘。

2、存储器:广义来说,各种带存的东西都算,内存,硬盘,SD卡,各种东西,反正就是能存东西的,相片、视频、文件、软件等等,当然内存和其它的还是有所区别,不过无所谓了。

3、输出设备:顾名思义,输入的信息在电脑里面加工处理了,就得在输出设备上输出来,最多的就是屏幕,各种屏幕,电脑显示屏、手机、平板的显示屏,打印机也是。 

4、运算器和控制器:这两块内容是CPU里面的,关于CPU,一般人可能听得很多,但做得很少,当然一个能够卖钱的CPU很复杂,但是对于本项目来说,复杂度会降低很多个量级(当然,也还是整个设计里面硬件部分最复杂的内容),运算器做为CPU的核心部分,实现的功能就是运算,CPU的主要功能就是实现在控制器控制下的运算(广义的)。

简单的举个例子说明这几部分是怎么接在一起干活的,就是上面图是提到的数据流、指令流和控制流什么的,其实撇开这些术语,比如在键盘上按一下字母“1+1=”,然后在屏幕的上显示出来“2”,主要的实现过程是这样的:

1、在键盘上依次按下“1”“+”“1”“=”,回车这几个键。

2、按了这几个键以后,实际上传输过去的是一些电流信号(不用care),这个时候,CPU里面的控制器就告诉键盘和存储器,让把这些上面输入的东西依次存在存储器里面,比如说内存,同时还要告诉屏幕,你把内存里面的这些字符串显示出来吧。

3、存了以后,这个时候,运算器就把这个内容读进来,然后算一下,在这里结果是等于2(当然,我们希望他等于别的也行),然后把2这个结果完了以后,再写到内存里面,然后控制器再告诉屏幕,把2显示出来。

OK,整个结果基本就是这样,这是老冯这帮牛人的伟大和牛X之处,总能够提出一些简单易懂但是强大好用的东西。

怎么好用呢?以后再聊。


运算器设计

这里最核心的是运算器的设计,在本项目里面,设计的运算器,基本上就是一个very sample的计算器,支持一些最简单的运算。这个东东有一个比较学术的词(算术逻辑单元,Arithmetic Logic Unit,ALU)以下都叫ALU,或者就叫运算器。在本项目里面要实现的ALU是这么样的一个东西

ALUf

解释一下,整个运算器的主要运算是支持两个16的输入x和y的运算,运算结果的输出也是16位的,支持的计算包括:x+y, x-y, y–x,0, 1, -1,x, y, -x, -y,!x, !y,x+1, y+1, x-1, y-1,x&y, x|y,上面的zx、nx、zy什么的是控制位,主要的作用这样的:

ALU的计算指令表

这个表里面,上面的这些位都是一个bit的控制位,第一行,当zx位是1话,那么x就是0,然后zy是1,y就是0, 然后f是1,最终结果就是x+y,在这种情况下,x和y不管输入是多少,计算的结果都是0,这一共18条运算指令就构成了这个ALU的指令集,比如倒数第5行,只有在zx、nx zy ny no都为0,f位为1时,才会执行x+y操作,当输入x为0000000000000010(十进制的2), y为0000000000000011(十进制的3),输出的out为0000000000000101(十进制的5)。

zr和ng是两个标志位,当输出out为零的时候,zr为1,否则 为0;当out<0的时候,ng为1,否则为0。在这里对于!x, x&y, x|y需要解释吗?需要吗?不需要吗?

总之,这个东西实际造出来以后,就是一个很强大计算器。看看当年这么强大的计算器,引发了沃兹的个人电脑构想,才有了苹果的诞生。

传说中个人计算机鼻祖--牛郎星8800
牛郎星8800开箱图

这个电脑的输入设备是什么呢?就是看到的那个银色的小旋钮,可以上下扳的那种,代表输入的0或1, 输出设备是什么呢?就是这些漂亮的小红灯。

神奇不,据说当时推出的时候,只要397美元,不是9999,也不是999,是397,你没有听错,就是美元,这样的低价,这么强大的功能, 我勒个去!

逻辑门的概念

关于上述的运算器,怎么开始实现呢?这个需要从最简单的逻辑门开始。

在学习数字电路这门课的时候,老师上来就讲逻辑函数,画卡诺图什么的,主要就是怎么对付考试,实际上真正有趣的东西好像基本上就没讲,还是在某次做实习的才发现这个东东确实非常有趣,可以通过自己接线,来按照你自已的意图进行实现,可惜的是一学期就让上了一次实验课。。现在大学教育确实有点那啥。。尽整高大上,也不怎么接地气。算了,扯远了,还是回来吧。

关于逻辑门的基本概念还是介绍一下,这个东西还是需要理解的。

逻辑运算又称布尔运算,无论是输入还是输出,都只有0和1,用来表示两个对立的逻辑状态。用来执行与、或、非这三种最基本逻辑运算的元件称为与、或、非门。在图中左侧是输入的信号,右侧是输出的信号,对于逻辑门元件来说,必须有输入和输出,可以是一对一,也可以是多对多。

非门:执行的是“非”的操作,一个输入信号和一个输出,对于输入的数据,取该数据的相反数据。

非的逻辑示意图

以下的几张物理实现的示意图是丹尼尔.希利斯在他的书《通灵芯片》里面提到的用弹簧和本杆实现的与 或 非门,假如把木杆往前视为1,往回视回0,从该图可以看到,当输入为前时,输出则为后,输入为后时,则输出为前,实现了非门的逻辑。

非门的一个物理实现示意


或门:执行的是“或”的操作,两个输入信号和一个输出,对于两个输入x和y,当x或y只要其中一个为1时,输出就为1。


或门逻辑示意

同样,在这个物理实现的或门上,可以看到无论哪个输入是往前,那么输出都会往前。

或门的物理实现示意


与门:执行的是“与”的操作,两个输入信号和一个输出,对于两个输入x和y,只有x与y都为1时,输出才为1。和或门的图标相比,左边的输入线是直的。


与门逻辑示意图

这个与门的实现,你自已就得好好看看了。

与门物理实现示意



通过这三种基本的逻辑门,就可以实现所有的逻辑运算,进而在上面构造出一整套的计算。没错,计算机的本质就是上述提到的与门、或门、非门等等各种门,只要实现了类似的功能,把成千上万个这些东西连接在一起,任何东西都能够做成一台计算机。木头,水泵,塑料,卡子,只要能够完成基本逻辑门的功能,任何东西都能够制成计算机。


丹尼尔.希利斯的积木计算机
丹尼尔.希利斯的积木计算机(全景)

我们的征途,从这里开始。

从加法开始

上面说的逻辑门听起来图森破的样子,或许你会怀疑这些简单的逻辑门能够做什么事情,接下来我们看看逻辑门怎么实现基本的计算功能。

与我们平常支持0 到9 的十进制计算不同。因为整个计算机系统只有0 和1两个数,所以这样的计算机系统只能够支持0 和1 的二进制计算,在计算机系统里面,所有的计算都需要转换成二进制。十进制与二进制的对应转换关系如表所示。(话说当初莱布尼兹,没错就是微积分里面那个,发明二进制运算的时候,)


十进制和二进制转换表

举个简单的例子,比如实现2 + 3 = 5 这样的计算,在二进制加法中规则是:1和0相加得1,1和 相加需要往前进一位,得10。二进制和十进制的基本操作过程是一样的,例子是一个2+3=5的二二进制计算示例。

为了实现上述计算功能,需要首先实现半加器,通过半加器实现全加器,再通过三个全加器的连接,就能够形成支持上述计算的一个三位加法器了。

半加器(Half Adder):如图所示,对于给定的输入a 和b(它们都只能取0或者1),通过一个或门、两个与门、一个非门(图中小圆点)的组合,可以对两个位进行加法并形成进位。(sum表示求和结果,carry表示进位)�


半加器实现示例


半加器的输入和输出过程

全加器(Full Adder):如图所示,通过两个半加器和一个或门的组合,形成了一个全加器。与半加器相比,全加器在输入上多了一个接收的进位,可以把从低位进位而来的数据纳入到计算中,将从低位计算产生的进位也加在一起。(其中x、y 表示两数相加,c 表示接收低位的进位)。全加器的输入和输出过程见表3-3。

全加器实现示例

全加器的输入和输出表

三位加法器:通过三个全加器的组合,就形成了一个三位加法器。该加法器可以把从低位相加产生的进位依次传递到高位,可以实现任意三位的二进制数的加法,即可以实现上述例子中的计算。


三位加法器的实现示例图

依次把进位传到下一个全加器。同理,我们可以通过任意位的加法器来实现对于较长二进制数的计算。尽管我们只介绍了加法运算的实现,实际上数学家已经证明,加法是实现所有数学运算的基础。有了加法器,原则上就能通过它们搭建任何其他计算,像乘法、除法、平方、开方、三角函数、对数函数等。

而另外一个大牛图灵在一百年前(好像还不到一百年,当年年轻的图灵躺在剑桥国王学校前草坪上开始在脑子里面构想这些东西的时候,好像是三十年代,那是一个科学和恐怖主义都极度兴盛的时代啊)就已经指明,这些简单运算足以支撑任何信息处理过程。

这个事情看起来似乎太扯了,搞这么一个东西,从逻辑门开始,要拼这么多东西,才能够实现一个8(2的3次方)以内的加法运算。但是这个东西的牛X之处在于,简单的东西是可以连接在一起变成复杂的东西。两个算盘连在一起只是一个更长的算盘,而这些逻辑门连在一起,可以构成复杂的计算世界。而且可以体积很小,大规模的叠加。这也是现在整个时代的秩序运行的基础,如果一旦发生了像刘慈欣在《球状闪电》里面描述的那个宏中子爆炸引起的效果,那无数的低头一族将会全部崩溃(或许我们的世界能够因此更美好?)


整体实现

OK,OK,加法有了,ALU就搞定了吗?很抱歉,还差点,不过差得不多了。

加法器是最核心的部分,但是我们还差一些别的东西,现在再看下我们需要实现的计算指令:

ALU支持的计算指令

在这里面,除了x+y,还有对x和y取反, 还有与(&)和或(|),没有提x-y关于这里面的设计,有一个东西是必不可少的,就是多路选择器,

选择器示意图

这个东东实现的的功能就是根据sel位的控制,判断输出的时候,选择a或者b中的哪一个,这个东西当然也是由基本的与或非门组成的。而且这个东西也可以扩展,比如a和b可以是多位的,在咱们要用的cpu里面,选择的是16位的,而且这个sel可以是两位或者更多,可以选择从四个或者8个输入里面选择指定的一个作为输出。 当然,也有反过来选择器 ,根据sel位判断对于输入的in,从给定的A和B哪个输出口进行输出。

针对上面提到的这些运算指令,可以有无数中实现方法,这个图给出的是实现方法之一:


ALU实现示意图


在这个图里面用了好几个busmux16,就是指的一个16位选择器, 用到了一个16位的加法器,Adder16,然后就是众多的与或非门。

含有计算指令表的计算器有了,接下来干什么呢, 且听下回分晓。

造个计算机-2、设计CPU

推荐阅读更多精彩内容