本文介绍一个简单的4位CPU,ALU(算术逻辑单元)的核心,以及如何自己构建一个。
信不信由你,计算机存在于微控制器和CPU之前。它们曾经使用分立部件构建,包括简单的IC和晶体管。
CPU可以说是现代电子产品的中心,无论是移动设备还是工厂控制电路。由于市场上有这么多类型的CPU(RISC,CISC等),所以很难 - 如果不是不可能的话 - 跟上。但是CPU如何工作?里面发生了什么?
在这个项目中,我们将看一下CPU的数学核心 - ALU。那我们就建一个!
ALU算术逻辑单元
CPU由三个主要部分组成:变量存储器(寄存器),控制电路(微代码)和ALU。ALU(算术逻辑单元)是实际进行计算和条件测试的CPU的一部分。
例如,如果要添加两个二进制数,则ALU负责生成结果。如果你的程序需要执行一些代码,如果两个值相等,则ALU执行值之间的比较,然后在条件满足时设置标志。
ALU的表示。图片由Jim Lamberson通过Wikimedia Commons提供。
现代CPU由数百万个晶体管组成(现在甚至数十亿个!)并且不可能在家中复制。但是一个简单的CPU(例如,Z80)只有8500个晶体管。过去的计算机(例如许多IBM大型计算机)实际上是使用分立的4000和7400系列芯片构建的。
这意味着您可以在家中构建CPU!为什么不呢?
该项目将是一个分立的4位ALU,将由4000系列和7400系列芯片构成。
项目先决条件
由于此项目相当复杂,您将需要以下内容:
对布尔概念的基本理解
对逻辑门的基本理解
二进制加法
两个基本的ALU操作是加法和减法。
理论添加二进制数字(单个位)非常简单,并在下面的列表中显示(所有可能的组合):
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10(这也是0 +进位)
但是,我们如何添加超过一位数的二进制数?这是进位位发挥作用的地方,我们需要使用长时间添加。
如下所示使用进位,其中“0(c)”表示“无进位”,“1(c)”表示“进位”。
0 + 0 +0(c)= 0
0 + 1 +0(c)= 1
1 + 0 +0(c)= 1
1 + 1 +0(c)= 10
0 + 0 +1(c)= 1
0 + 1 +1(c)= 10
1 + 0 +1(c)= 10
1 + 1 +1(c)= 11
如果我们希望以二进制形式添加10和10,我们将首先以长加法的形式将它们写下来。我们使用上面的规则从最右边开始并向左移动,将列添加到列中。当我们从一位加法中得到一个进位时,我们将它向左移动一列,在那里它作为一个位被包含在加法中。
长期添加二进制数
在这个例子中,我们添加了1011和0001(11 + 1 = 12)。从最右边开始,我们加1 + 1,这给我们10(0和一个进位)。然后我们移动到下一列(右起第二列)并添加所有位。请注意进位如何也包含在此加法运算中。这意味着我们添加了三个数字:1(进位),1和0。
那么现在我们可以看到如何在纸上添加两个二进制数字,让我们看看我们是否可以制作一个增加两个二进制位的电路!
电路
该半加器具有两个输入和两个输出如下面的图所示。两个输入表示两个单独的位,Sum输出表示单个位形式的两个位的总和,Carry输出是加法的进位。
半加法器电路,使用AND门和异或(XOR)门
半加法器的真值表
但是这条赛道有什么问题?该电路不能从之前的操作中取出!那么我们如何解决这个问题呢?好吧,这条电路没有被称为半加法器!如果我们使用其中两个加法器和一个或门,我们可以创建一个具有两位输入的全加器,一个进位输入,一个输出输出和一个执行输出。
使用两个半加法器和一个或门制作的全加器
不幸的是,对于4位ALU,使用分立芯片来创建4位加法器是不切实际的。因此我们将欺骗并使用4008 4位加法器IC。你可以在eBay上花几块钱买这些:
4008 4位全加器引脚排列。
二进制减法理论
现在我们可以添加两个4位数字,我们如何减去二进制数?为此,我们将实现一个名为“two's complement”的二进制系统。该系统有一些规则:
要取消数字(例如,将5更改为-5),请翻转所有位并添加1。
如果MSB(最高有效位)为1,则数字为负。例如:
10010是否定的
00010是积极的
请注意,通过遵循规则1,您可以确定负二进制数的值:
0001 = 1:否定此=(1110 + 1 = 1111)= -1
1001 = -7:否定此=(0110 + 1 = 0111)= 7
0110 = 6:否定此=(1001 + 1 = 1010)= -6
二进制补码技术是有益的,因为它允许我们使用相同的加法器电路执行加法和减法。因此,如果我们希望将我们的4位加法器转换为4位加法器/减法器,我们只需要合并一个4070 IC(四倍XOR)。我们将二进制数输入馈入每个XOR门的一个输入,使用另一个XOR输入作为加/减线,然后将该相同的线馈入加法器的进位。
当我们希望从A中减去B时,我们将减法线设为高。这有两件事:
翻转输入B上的所有输入位
将一个添加到加法器
完整的4位加法器/减法器
最终电路还将在输出端使用74HC125四通道缓冲器,以便加法器/减法器单元可以连接到公共数据总线以进行输出。缓冲区还有一条启用线,允许我们从加法器/减法器中选择输出。
完成加/减单元后,就可以查看逻辑函数了。
逻辑函数
当需要位操作时,逻辑函数很有用。想象一下具有8位端口的微控制器,您使用低4位读取4位数据总线。从端口读取时,需要删除高4位,因为这些位会影响程序执行。因此,要删除这些位,可以使用逻辑AND功能将它们屏蔽掉。
此函数将来自一个字(端口)的AND位与另一个数字(将删除高四位的数字)进行比特。如果我们和0x0F(0b00001111)的端口,我们保留低4位(因为x AND 1 = x)并删除高4位(因为x AND 0 = 0)。
AND用于删除位
当你需要翻转所有位时使用NOT(0000将变为1111)
OR用于合并位(0110或0001为0111)
XOR用于翻转所选位(0101 XOR 0100为0001)
ALU中的逻辑单元是连接到缓冲区的AND,OR,XOR和NOT门。启用线为每个逻辑单元馈入每个总线缓冲器,以便可以单独选择每个单元。
4081 - 四和门
4070 - 四路异或门
4071 - 四或门
4049 - 十六进制非门
74HC125 - 输出缓冲器(用于总线隔离)
逻辑门显示ALU的四个逻辑功能
注意:
A和B表示字A中的第0,1,2或3位以及字B中的相应位。
NOT操作只涉及一个单词; 无论另一个单词的状态如何,单词中的每个位都被补充。
比特转换和比较
位移也是一个非常重要的功能。这些功能通常存在于具有串行端口的微控制器中,其中数据逐位流式传输。这意味着,当位到达时,您需要将该位置于开头(或结束)的某个字节中,然后向左或向右移动字节中的所有位(取决于放置传入的位置)位)。
有趣的是,向右移位(例如,0010变为0001)相当于除以2,向左移位(例如,0010变为0100)相当于乘以2。
可以非常轻松地完成位移。唯一需要的芯片是缓冲器,因为物理数据线只是重新排列。
向左旋转
右旋
左转:
位0连接到输出的位1
位1连接到输出上的位2
位2连接到输出上的位3
位3连接到输出上的位0
对于右转:
位0连接到输出上的位3
位1连接到输出的位0
位2连接到输出的位1
位3连接到输出上的位2
在ALU中实现的最后一个操作是比较,这非常有用(并且易于添加)。我们将采用4585幅度比较器; 该芯片的作用是取两个4位数字并告诉我们A> B,A <B是否以及A = B.
这很有用,因为它使得实现“if”指令变得更加容易。许多旧处理器没有幅度比较能力。这意味着尝试确定一个数字是否大于或小于另一个数字是不太重要的 - 可以进行减法,然后检查符号位,但这使得代码不太清楚。在这个ALU中你需要做的只是在数据总线上有两个数字,并且幅度比较器会立即告诉你两个数字是否相等,更少或更多。
4585比较器的缺点是它是一个幅度比较器,不能用于二进制补码。
一个4585幅度的比较器。
BOM - 物料清单
除了这些关键组件,您还需要一种创建电路的方法。就个人而言,我更喜欢使用条形板,因为它会使电路更加永久。但是,您可以使用面包板来加快原型设计甚至设计PCB。
实物图
以下是ALU原理图的链接(PDF格式); 它相当大。但是不要被这个原理图推迟,因为构建ALU实际上非常容易。
不是试图在一块板上构建整个模块,而是将ALU构建成较小的部分,通过总线连接在一起。
我的ALU是在四个独立的条板上构建的,这些条板都适合定制的迷你架子(也是由条板制成)。
前端总线(图像中的左侧面板)是输入A和B.
背面总线(图像中的右侧面板)是数据输出和功能选择
完成的ALU。四个架子和大量的电线!
为了控制ALU用于测试目的,第五个条板用于保持输入按钮,输出LED和4515解码芯片以解码输出。
ALU上的模块具有低电平有效的使能线; 因此,要在数据总线上启用模块,必须将使能线连接到0V而不是5V。5V停止模块发送任何数据。
重要的提示
ALU使用公共数据总线,其中各个功能通过四缓冲器隔离。但是,必须一次只有一个模块正在运行(例如,仅启用ADD而禁用所有其他模块)。一次启用多个模块将导致74HC125芯片损坏。
总结
ALU完成后,我们现在可以在数学上和逻辑上处理两个4位数字。但是这个ALU只是这个难题的一小部分!
对于接下来的步骤,我们可以将一个寄存器附加到ALU的输出并将其反馈到字B.然后我们可以创建一个内存控制器,它可以从芯片中流式传输数字并对这些数字执行操作。在这一点上,我们可以将这些数字存储在内存中,以决定ALU将执行的操作。