EEJournal

专题文章
现在就订阅

古代的奥秘:二进制编码十进制(BCD)

我喜欢学习过去的逻辑设计师如何用创新的解决方案解决棘手的问题。我越深入研究这类事情,我就越对自己说:“哇!我从来没有想到过这一点!”一个很好的例子是二进制编码的十进制(BCD),因为这个主题比人们最初想象的要多得多。

事实上,我可以大胆地说,即使你是一个数字逻辑专家,拥有一个16码的大脑,如果你没有在这个专栏中学到一些新的东西,那么我的名字就不是伟大的马克斯!

说到逻辑,在我们兴致盎然地(当然是沉着地)投入到BCD争论之前,让我们花点时间来提醒自己一个我最喜欢的逻辑难题。

我们从一个黑盒开始,它有三个输入a、B和C,以及三个输出NotA、NotB和NotC。这三个输出是它们对应输入的逻辑倒数(当A为0时,NotA为1;当A为1时,NotA为0;当B为0时,NotB为1,等等)。

我们的任务是确定黑匣子的内容。如果我们被允许使用任何我们想要的逻辑门,那么我们只需要三个NOT门就可以完成这项工作。遗憾的是,我们被告知我们有问题只有两个非门听候我们的差遣。此外,在你问之前,我们不允许使用任何NAND, NOR, XOR或XNOR门。从好的方面来看,我们可以随心所欲地使用许多AND和OR门。

如果你以前没有接触过这个小流氓,那么你很值得花时间思考这个装腔作势的人。虽然一开始看起来不可能,但确实有一个简单的逻辑解决方案,在本专栏的末尾将为您提供乐趣和乐趣。

设定场景

正如我在先前的文章中所提到的(ag亚博网站 ),我目前正在撰写一系列的Arduino训练营实用的电子产品体育),是英国首屈一指的电子及电脑爱好者杂志。

不幸的是,那部光荣巨著的编辑邪恶的杰出的马特·普尔泽,想让我专注于实际操作。马特激烈地阻止我在杂草中徘徊,这是我的习惯,因为我不能覆盖所有的东西体育我正在写这样的辅助文章,以捕捉和分享许多超级有趣的上下文材料(看看我的无焊面包板博客,例如)。

我的早期专栏Arduino训练营系列描述了使用7段显示器的无数方法,包括BCD的多种表现形式。作为其中的一部分,我正在创建一些我认为非常漂亮的图,下面显示了一个示例。

尽情享受我的精彩图表吧(来源:Max Maxfield)

讨论了面包板顶部和底部的电源轨和接地轨中间有跳线的原因提到的博客

那是什么?我是否听到你喃喃自语:“我敢打赌这些图像是用弗里茨软件“小声说?”如果是这样,你会损失你的钱,因为我所有的图表都是用微软Visio创建的。和许多工程师一样,我身上也有一丝强迫症的味道。因此,多年来,我花了无数个快乐的时间手工制作这类手工图表。

有几根手指?

正如我们在ag亚博网站 列中,当今绝大多数数字计算机的底层基础是二进制(以2为基数)的数字系统,只支持两个值:0和1。

使用二进制的原因是,我们可以相对容易地创建简单逻辑函数的电子实现,如AND, NAND, OR, NOR, XOR和XNOR,它们可以检测输入上两个不同电压之间的差异,并在输出上生成这些电压。

我们不讨论具体的电压值,而是将它们抽象为0和1。除了将这些0和1值视为二进制数外,我们还可以使用它们来表示布尔概念而且真正的

一个二进制数字叫做A.我们可以将一组位集合在一起来表示我们想要的几乎任何东西,包括整数或浮点数形式的数值、字母数字字符和标点符号,等等。两种非常常用的分组是4位分组nybbles(或轻咬)和8位字节

不幸的是,人类很难用二进制数来思考问题。由于我们有十个手指(包括拇指),我们最熟悉的数字系统是小数一个省,十进制的(以10为基数),使用10位数字:0、1、2、3、4、5、6、7、8和9。由于各种各样的原因,包括广泛的使用,我们倾向于认为十进制使用直观,易于理解。举个例子,如果你发现自己在一个废弃的大厦在一个月黑风高的夜晚,和你听到可怕的声音来自一个房间与二进制数001010011010门上涂上(什么是人们只能希望)滴红色油漆,你可能没有相同的本能反应,如果相同的值给出了十进制666(我担心我看过的恐怖片比有利于我)。

题外话,这个术语四足动物的指的是有四肢、臀部、肩膀、手指和脚趾的动物。超类四足动物总纲包括人类和河马,两栖动物和食蚁兽,青蛙和鳄鱼,蜥脚类动物和下孔类动物,还有……再一次,名单还在继续。迄今为止发现的最原始的四足动物是棘螈(Acanthostega),出现在大约3.65亿年前的泥盆纪晚期(法门尼纪)。我在这里提到这个的原因是棘螈每只手上有八个发育完全的手指。

第一种四足动物棘螈,每只手上都有八个发育完全的手指
(资料来源:Max Maxfield和Alvin Brown)

如果进化没有绕道而行,我们可能最终会使用16进制的编号系统,当我们最终发明数字计算机时,这将是非常方便的(没有双关语的意思),但我们离题了……

把脚趾伸进BCD的水里

总结一下我们目前所处的位置:(a)人类更喜欢使用十进制表示,(b)数字计算机在使用二进制时最开心。我们需要的是在两者之间进行映射(转换)的方法。事实上,有无数的映射可能性,我们统称为二进制编码的十进制数的这类二进制编码(BCD)。

因为4位可以表示24= 2 × 2 × 2 × 2 = 16种不同的0和1的组合,它只需要4位来编码我们的10个十进制值。

BCD最直观和明显的形式是基于使用自然二进制数格式(“自然”是因为它遵循十进制和其他位值编号系统中使用的一般计数方法)。在这种情况下,大多数人通常认为是BCD的缩影,但更恰当的说法是自然BCD (NBCD)或简单BCD (SBCD),每个数字都有一个与之相关的权重。正如我们在ag亚博网站 列,这些权重是23., 22, 21,和20,等于8、4、2和1,所以这种方法也被称为“8421编码”或“BCD 8421”。

BCD 8421(来源:Max Maxfield)

观察一下,在用于存储BCD数字的4位nybble中有6个未使用的二进制组合。对于BCD 8421,这些未使用的组合是1010、1011、1100、1101、1110和1111。

尽管我自己在现实世界中从未遇到过这种情况,但持有BCD值的nybble可以被称为tetrade(来自“一组或一组四个”),在这种情况下,代表BCD数字的十个状态可以被称为四分体四联球菌

打包和拆包

大多数计算机以8位字节的形式处理数据。即使在具有16位、32位和64位数据路径的机器中,我们也倾向于认为这些路径分别为2、4和8字节宽。

记住这一点,可以用以下两种方式之一来编码BCD 8421值:打开包装.在未打包BCD的情况下,每个BCD数字被编码为8位字节的四个最低有效位(lsb)(位0到3),而字节的四个最高有效位(msb)(位4到7)没有任何意义(它们通常被装入0)。在本例中,十进制值95的编码如下所示。

将十进制值95存储为未打包的BCD 8421(来源:Max Maxfield)

相比之下,在打包BCD的情况下,两个BCD数字被编码成一个字节,其中一个数字在最低有效nybble (LSN)(位0到3)中,另一个数字在最高有效nybble (MSN)(位4到7)中大端法格式,十进制值95将被编码如下所示。

将十进制值95存储为打包的BCD 8421(来源:Max Maxfield)

移位和屏蔽操作可用于打包或解包BCD数字(另请参阅我的专栏)屏蔽和C/ c++位操作符).

输入与输出

“这些都很有趣,但BCD现在还在使用吗?”我听见你在哭。你可以用你的小棉袜子打赌!稍后我们将详细讨论这个问题,但是,作为一个诱人的品尝者,一个常见的应用程序是允许人们使用BCD拇指轮开关轻松指定十进制值,例如302109000ck(现在是Littelfuse的一部分)。

302109000 BCD拇指轮开关(来源:C&K)

在这种情况下,操作员旋转前面的拇指轮,相应的BCD代码显示在后面的四个终端上。通常用于工业控制应用,这些开关组可以安装在一起,从而允许用户指定更大的数值。

另一个常见的应用是在7段显示器上显示十进制值。如果是个位数共阴极7段显示例如,我们可以使用德州仪器的CD4511 bcd -to-7段解码器。CD4511真值表的简化表示如下所示。

CD4511 bcd -to-7段解码器真值表(来源:Max Maxfield)

我们之所以说这是真值表的简化版本,是因为CD4511还具有灯测试(LT)、冲裁(BL)和锁存使能(LE)输入,可分别用于测试显示、关闭或调节其强度以及锁存/存储BCD代码。

无符号、符号幅度和有符号二进制数

稍后,我们将研究表示由BCD数字组成的大数的不同方法。然而,在我们这样做之前,快速刷新一下我们如何在二进制中做事可能是一个好主意。

为了简单起见,让我们使用4位二进制值。我们知道,4位可以表示24= 2 × 2 × 2 × 2 = 16种0和1的不同组合。如果我们决定使用这些组合来表示正数(我们称之为无符号二进制),那么我们就可以表示0到15的十进制值。这如下图(a)所示。

无符号、符号幅度和有符号的4位二进制数的比较(来源:Max Maxfield)

如果我们希望同时表示正数和负数,那么有两种常用的方法。第一个是调用,它的使用相对较少sign-magnitude二进制.如上图(b)所示。在本例中,是最高有效位(MSB),称为符号位,用于表示正、负值(0 =正,1 =负)。其余的位与之前的列权值相同,用于表示数字的大小。使用这个方案,我们可以表示从-7到+7的值。尽管这种方法直观且平衡(它提供了相同数量的正负值),但使用起来有点“笨拙”,尤其是我们最终得到了两种类型的零(+0和-0)。

表示正负值的更常用方法是使用签署了二进制格式(或称。二进制补码格式,我们将在本文后面讨论)。如上图(c)所示。在本例中,MSB表示一个基于列权值的负数。对于一个4位有符号二进制数,MSB中的0表示0,MSB中的1表示-8,其余位继续表示正值。因此,我们现在可以使用4位字段来表示从-8到+7的数字。带符号的二进制格式对我们的大脑来说不太直观,但是——正如我们将看到的——它在实践中使我们的生活变得非常非常简单。

手动添加二进制数

我的目的不是在这里教授二进制算术——在互联网上有无数的资源可以用于这类事情——但我通常从稍微不同的方向来研究事情,我有一些想法在我的脑海中回荡,我想分享。

例如,如果我们想把两个十进制数字加在一起,有100种不同的可能性:0 + 0 = 0,0 + 1 = 1,0 + 2 = 2…1 + 0 = 1,1 + 1 = 2,1 + 2 = 3…2 + 0 = 2,2 + 1 = 3,2 + 2 = 4…等等。如果操作的结果小于或等于9,则不执行到下一阶段。或者,如果结果在10到18之间,则执行1到下一阶段。

通过比较,如果我们希望将两个二进制数字相加,只有四种不同的可能性:0 + 0 = 0,0 + 1 = 1,1 + 0 = 1和1 + 1 = 10(或十进制的2)。我们通常认为后一种情况是:“1 + 1 = 0加上1到下一阶段的执行。”

当然,如果我们有一个从上一阶段带入的数据,这就给了我们一个额外的可能性,即1 + 1 + 1 = 11(或十进制形式的3)。我们通常认为后一种情况是:“1 + 1 + 1 = 1加上1到下一阶段的执行。”

在任何数制中,最坏的情况是每一阶段都有一个执行。假设我们使用的是4位数的值,考虑下面的例子:

十进制和二进制加法中的进位示例(来源:Max Maxfield)

在带有进位的例子中,因为我们已经声明我们处理的是4位数的值,所以我们假设没有办法存储任何额外的数字,所以我们简单地丢弃任何进位到第五列的数字。

也许有必要暂停一下,对比一下(b)和(d)的9998和1110结果,因为这暗示了“引子下面”发生了什么。

现在,事情开始变得有趣了。假设我们正在处理无符号二进制数,我们决定将0011 + 1001(或十进制形式的3 + 9)相加。结果是1100(或十进制12),如下图(a)所示。

手动添加无符号和有符号二进制数(来源:Max Maxfield)

或者,假设我们正在处理有符号的二进制数,我们决定将0011 + 1001(或十进制中的3 +(-7))相加。在本例中,结果是1100(或十进制的-4),如上图(b)所示。

等等!怎么啦?这两种情况的值是相同的!这就是我们开始欣赏有符号二进制格式的狡猾之处。我们是否认为这些值是有符号的或无符号的并不重要,因为我们用完全相同的方式添加正负值。正如我们将很快看到的,这极大地简化了使用逻辑门执行加法的任务。

唯一的“规则”是,无论我们认为我们的值是哪种格式(无符号或有符号),为了使结果有效,它必须能够适合我们使用的任何大小的字段。对于我们的4位值,这意味着如果我们认为值是无符号的,结果必须在0到15的范围内,或者如果我们认为值是有符号的,结果必须在-8到+7的范围内。

用逻辑门添加二进制数

由于我们在本专栏中涉及了如此多的主题,可能值得注意的是,要与另一个数字相加的数字称为被加数源自拉丁语augendum,意思是“要增加的东西”。相比较而言,一个数字加到另一个数字上称为数字加数源自拉丁语addere,意思是“相加”。两个或两个以上数字相加的结果被称为“加法”总和源自拉丁语总结,源自of的阴性词summus,意思是“最高的”。

我们首先定义一个1位全二进制加法器。符号和真值表如下所示,其中A是我们的1位加数,B是我们的1位加数,Cin(进位)是来自前一阶段的1位进位,S是1位和,Cout(进位)是前往下一阶段的1位进位(您将看到我所说的“前一阶段”和“下一阶段”)。还有一种1位二进制半加法器,它只有a和B输入(没有Cin),但我们不会在这里使用这个小流氓。

定义一个1位全二进制加法器(来源:Max Maxfield)

说句题外话,关于真值表,有些人更喜欢把Cin放在左边的输入列中,把A和B放在右边的两列中。。影片完全没有异议虽然这可能会让您停下来思考一下,但实际上您所要做的只是交换列顶部的a、B和Cin标签,并保持其他所有内容“原样”。

我们很容易想出一组逻辑门来实现这个真值表。如下所示,一种常见的实现包括一个2输入OR门、两个2输入AND门和两个异或门(通常是2输入)。(如果您有兴趣深入研究这个主题,只需执行谷歌搜索“1位全加法器”。)

1位全二进制加法器的一种可能的门级实现
(来源:Max Maxfield)

为了匹配我们一直手动执行的计算,下一步是连接1位加法器的四个实例化,以创建一个4位版本,如下所示。

构建一个4位二进制加法器(来源:Max Maxfield)

在符号的情况下,与数字4相关联的有角度的线表示这些是4位(四线)总线。

观察我们强制Cin输入输入最低有效位(LSB)为0,因为没有早期阶段驱动这个位(我们可以在这一阶段使用半加法器,但我们稍后将需要Cin输入)。来自LSB的Cout驱动Cin到下一个位,以此类推。出于这里讨论的目的,我们可以假设丢弃(不注意)来自最高有效位(MSB)的Cout。在现实世界中,我们会使用这个“进位”信号(以及另一个叫做“溢出”的信号)来告诉我们加法结果的大小是否超出了我们在处理位中表示它的能力,但这是另一个故事。

由于显而易见的原因,这个实现被称为纹波进位加法器因为传接球会波及到整条线。这是最慢的一种加法器,但它需要最少的逻辑门,而且最容易理解,这使得它非常适合我们在这里谈论的内容。

用逻辑门减二进制数(不要这样做!)

要减去另一个数的那个数叫做被减数源自拉丁语minuendum,意思是“要被削弱的东西”。通过比较,要从另一个数字中减去的数字称为减数源自拉丁语subtrahendum,意思是“减去”。用一个数减去另一个数得到的结果叫做剩余部分或者是区别

根据我们到目前为止讨论的所有内容,如果您无意中穿越了一个时间点,发现自己在20世纪40年代早期,那么您已经具备了使用原始逻辑门实现二进制减法所需的知识。

重要的是要明白,我要告诉你的不是我们在现实世界中执行二进制减法的方式。然而,如果我们不知道我将在本专栏稍后向您展示的内容,那么有必要稍微转移一下注意力,看看我们可能会被诱惑做事情的方式。

我们的第一步是定义一个1位全二进制减法器。符号和真值表如下所示,其中A是我们的1位被减数,B是我们的1位减数,Bin(“借进”)是来自上一阶段的1位借,D是1位差,而Bout(“借出”)是进入下一阶段的1位借。

定义1位全二进制减法器(来源:Max Maxfield)

你现在知道该怎么做了。如果我们真的要采用这种方法(实际上我们并没有),我们将提出一组逻辑门来实现这个真值表,然后我们将使用1位减法器的四个实例化来创建一个4位版本。你只需要相信我,就像我们的4位加法器一样,这个减法器可以愉快地处理无符号和有符号的二进制值。

我们不想在这上面花费太多时间,所以让我们跳过,考虑如何同时实现4位加法器和4位减法器,也许是作为中央处理器(CPU)的一部分。

实现4位二进制加减法(来源:Max Maxfield)

这里的思想是,我们将4位A[3:0]和B[3:0]信号输入加法器和减法器,我们使用4位2:1多路复用器来选择我们当前感兴趣的操作的输出,并将这些输出作为我们的4位结果R[3:0]。

同样,为了讨论的目的,我们假设丢弃了加法器MSB中的Cout信号和减法器MSB中的Bout信号。

假设我们的加法器消耗A逻辑门(为了这些讨论的目的,我们不关心实际的数字)。再假设减法器消耗的门数与加法器相同。我们也可以说我们的多路复用器消耗M个逻辑门。这意味着我们实现的总门数是2A + m。此外,如果我们故意含糊,我们可以说这个实现涉及从主要输入到主要输出的两个延迟阶段。让我们把这些事实记下来,以便将来讨论。

这个解决方案的问题是,我们现在有两个相对复杂的函数——我们的加法器和减法器——消耗资源(硅芯片上的逻辑门和空间),并且不断消耗能量,即使我们在任何特定时间只使用其中一个函数。要是有更好的办法……

基数和减数基数补数

在我们继续讨论之前,现在是时候注意一下与每种数字系统相关的补语有两种形式补码减基数补-这里的术语基数指的是数字系统的基数。

在十进制(以10为基数)系统中,基数补数也被称为十的补减根补被称为九的补.在二进制(以2为底)系统中,基数补数也称为二进制补码减根补被称为一个人的补充

在这个领域有很多困惑。例如,应该写tens, ten ' s,还是tens的补位?问题是你可能会碰到所有这些变体。许多风格手册建议完全去掉撇号。然而,许多从业者更喜欢用“10的补语”、“9的补语”、“2的补语”和“1的补语”的形式来写这些词,我们在本文中将使用这种方法。

如果我们用RC和DRC分别表示基数补和减基数补,那么RC = DRC + 1(反之,DRC = RC - 1)。你很快就会理解这个方面的事情。

说句题外话,在我们继续之前,你有没有想过' = '字符的起源?在这个汉字发明之前,平等通常用一个词来表示aequalesaequantur,源自拉丁语aequlis,意思是“偶数”或“水平”(例如,数学家写“6 + 2等于8”)。现代等号符号的第一次使用出现在公元1557年的一本名为智慧的磨刀石这本书的作者是英国数学家罗伯特·雷考德(Robert Recorde, 1510-1558)。在这本大部头中,雷考德写道:“我将像我在工作中经常使用的那样,将一对平行线或一行的格莫韦线拉长,这样' = ' bicause noe 2, thynges就可以更相等。”

二进位数手工减法

当我们用一个数减去另一个数时,很难让我们的大脑理解借位的概念。即使我们使用十进制,这也是正确的,尤其是因为执行借位操作有不同的方式(请参阅我的博客)既不借债也不放债).

学习如何在二进制中执行借位运算可能同样令人难以置信。我不能说,因为我从来没有被迫这么做过。相反,我使用1和2的补语来执行这些操作。

假设我们希望以十进制形式执行5 - 2 = 3的计算。这很简单,不是吗?那么二进制呢?假设我们仍然使用4位值,这将是0101 - 0010 = 0011。和大多数事情一样,如果你语速快、手势激烈,这看起来很容易,但我是怎么做到的呢?老实说,我只是简单地看了一下十进制的原始计算,然后——因为我已经熟记于心了——我用十进制值代替了它们的二进制等价值,从而掩盖了我们实际如何执行计算。说到这个,看看下面的例子。

谁知道如何在二进制中执行借位?(来源:Max Maxfield)

我们从LSB开始,它涉及到操作1 - 0 = 1。下一位要求我们执行操作0 - 1,这将涉及到借位。我相信这很容易学习和做,但是——就像我刚才说的——我从来没有被强迫这样做,因为有其他方法可以达到预期的结果。

让我们回到原来的5 - 2 = 3的十进制计算。另一种方法是5 +(-2)= 3。你可能会觉得这并没有实质性地改善我们的处境,但让我进一步解释。我们知道二进制的+2是0010。我们要做的是创建与-2等价的二进制数,如果我们看一下有符号的二进制表,我们知道它是1110。我们在二进制中获得-2的方法是在二进制中生成2的+2补。有三种方法可以做到这一点。

第一种方法,我们可以称之为“减法和加法”,如下(a)所示。这包括我们用1111(所有的1)减去0010(+2)来生成1的补数1101(-3)。注意,在执行此操作时,我们不必执行借位操作。接下来,我们将0001(+1)相加以生成这两个数的补数1110(-2)。

生成1’s和2’s的补语(来源:Max Maxfield)

第二种方法是上文(b)所示的“翻转和添加”。在本例中,从0010(+2)开始,我们简单地翻转(反转)所有的位,0到1,1到0,以生成1的补码1101(-3)。和前面一样,接下来加0001(+1)以生成这两个数的补数1110(-2)。

第三种方法是一个有用的捷径,如上文(c)所示。同样,我们从0010(+2)值开始。从LSB开始,我们复制到(和包括)第一个1,然后我们翻转(逆)其余的位,留下我们的两个补1110(-2)。

反之亦然。如果我们从1110(-2)开始,生成它的两个补数,我们将得到0010(+2)。关键是,我们可以在不执行借位操作的情况下实现这一切。此外,如果我们坚持使用(b)和(c)技术,我们甚至不需要执行减法。如果你还没有意识到这一点,我们在这里谈论的是一个真正的“Tra-la”时刻,因为这为各种可能性打开了大门。

例如,让我们回到原来的问题5 - 2(二进制0101 - 0010),我们现在可以重新表述为5 +(- 2)(二进制0101 + 1110),如下图所示。

用两个补数做减法(来源:Max Maxfield)

执行最后一步只需要做加法。记住,我们处理的是4位的值,我们丢弃任何进位到第五列的值,只留下预期的结果0011(+3)。

用逻辑门建立一和二的互补性

在前一节中,我们讨论了如何使用1的补数和2的补数的概念手动执行二进制减法。下一步是使用逻辑门实现这些功能。由于为了简单起见,我们限制自己使用4位值,因此我们从创建4位值的补数开始。这是简单的柠檬挤压,因为它只需要四个非(逆变器)门如下(a)所示。

在逻辑门中构建1和2的互补子(来源:Max Maxfield)

从我们之前的讨论中,我们知道二进制数的二补是它的一补加1,我们可以使用4位二进制加法器来实现这一点,如上面(b)所示(观察,我们将这个加法器的Cin输入连接到0,我们根本不使用它的Cout输出)。

二进位数的互补性减法(不要这样做!)

再一次,基于我们到目前为止讨论的所有内容,你可能会想,能够加减两个4位二进制数的一个很好的解决方案将是如下所示的实现:

使用2的补数实现4位二进制加减法(来源:Max Maxfield)

正如我们所看到的,输入A[3:0]总是被输入到我们原来的4位加法器中。原始加法器的其他输入来自一个4位2:1多路复用器,如果我们希望执行加法(Sel = 0),它用于在B[3:0]输入之间进行选择;如果我们希望执行减法(Sel = 1),则用于在B[3:0]输入的两个补(我们称为tcB[3:0])之间进行选择。

回想一下我们考虑使用4位加法器和4位减法器的时候。您可能还记得,我们假设加法器需要A个门,减法器需要同样的门,4位2:1多路复用器需要M个门,总共是2A + M。我们还注意到,该解决方案涉及从主要输入到主要输出的两个阶段的延迟。

现在考虑我们最新的解决方案。记住,我们的二补子是由一个一补子(四个非门)和一个4位二进制加法器组成的。这意味着我们的新解决方案消耗2A + M + 4*NOT门,这意味着它包含更多的盖茨比原来(愁容满面)。

更糟糕的是,即使我们基于NOT门非常快而排除了1的互补或,我们的新实现的最坏情况的路径(通过两个互补或的路径)现在涉及三个从主要输入到主要输出的延迟阶段(甚至更悲伤)。

那么,我们为什么要在这些问题上喋喋不休呢?好吧,深呼吸,准备好迎接另一个“特拉”时刻,因为一切即将揭晓……

二进位数的1补数减法(这才是正确的方法!)

到目前为止,我们已经将Cin输入与原始的4位加法器连接到0。我们想一下。如果我们把这个和1连起来会有什么影响?事实上,这就像给最终结果加1。

嗯。如何生成二进制值的二补?天哪,你说得对!我们把这个值的1补加1。这意味着我们可以用1的补数替换2的补数,并使用1位2:1的多路复用器将Cin输入输入到4位加法器,如下图所示。

使用1的补数实现4位二进制加减法(来源:Max Maxfield)

相同的Sel信号可用于控制两个多路复用器。如果我们希望执行加法(Sel = 0),我们选择B[3:0]输入,并将0赋值给加法器的Cin输入。相反,如果我们希望执行减法(Sel = 1),我们选择B[3:0]输入的1的补数(我们称之为ocB[3:0]),并将1赋值给加法器的Cin输入。

如果我们排除用于形成1的互补门和1位2:1多路复用器的门,我们的新解决方案可以同时执行加法和减法,同时只消耗A + M逻辑门,并且只涉及两个从主要输入到主要输出的延迟阶段(最快乐的笑脸)

现在大家一起:“特——拉——啊!”

无符号、符号幅度和有符号BCD数字

我知道我们在讨论中已经跑题了,但是希望您没有忘记本文的主要主题是二进制编码的十进制(BCD)。问题是,到目前为止,我们所看到的一切都将使我们的大脑更容易理解恐怖即将到来的快乐。

在本文前面,我们介绍了BCD 8421代码,其中每个十进制数字使用四个二进制位进行编码。让我们假设这就是我们正在使用的代码,除非我另有说明。此外,为了便于讨论,让我们假设我们处理的是4位数的BCD值。

如果我们决定使用这些数字来表示正数(无符号),那么我们可以表示十进制值0000到9999。这如下图(a)所示。

无符号、符号幅度和有符号的4位BCD数的比较(来源:Max Maxfield)

您肯定还记得,在4位二进制值的情况下,从最高有效位(MSB)到最低有效位(LSB)的列权重为23., 22, 21,和20,分别等于8、4、2和1。相比之下,在4位无符号BCD值的情况下,从最高有效位数(MSD)到最低有效位数(LSD)的列权重为103., 102, 101,和100,分别等于1000、100、10和1。

如果我们希望使用BCD来表示正数和负数,那么有两种常用的方法。第一个叫做sign-magnitude BCD.如上图(b)所示。在这种情况下,MSD充当符号位,用于表示正数和负数。在这个图中,我用0(二进制0000)和1(二进制0001)分别表示正数和负数。在实践中,更常见的是使用两个未使用的二进制代码,通常是1100和1101,它们分别用于表示正数和负数。其余的数字与之前的列权值相同,用于表示数字的大小。使用这个方案,我们可以表示从-999到+999的值。至于符号大小二进制,我们最终会得到两种零(+0和-0),这可以让我们的生活变得“有趣”。

表示正负值的另一种方法是使用BCD签署格式。如上图(c)所示。在这种情况下,基于数字本身和列权值的组合,MSD可以表示正数或负数。对于一个4位有符号的BCD数,MSD中的0、1、2、3、4值分别代表0、+1000、+2000、+3000和+4000。但是,MSD中的5表示-5000,6表示-5000 + 1000 = -4000,7表示-5000 + 2000 = -3000,8表示-5000 + 3000 = -2000,9表示-5000 + 4000 = -1000。所有剩余的数字继续表示正值。因此,我们现在可以使用4位字段来表示从-5000到+4999的值。

手工添加BCD编号

这就是事情变得如此酷的地方,我兴奋地在我的座位上扭动,因为我们可以对无符号和有符号BCD值执行加法,就像我们对无符号和有符号二进制数执行加法一样。

考虑将无符号BCD值2354 +6430 = 8784相加,它等于十进制形式的(+2354)+(+6430)=(+8784)。如下图(a)所示。

现在考虑将带符号的BCD值2354 + 6430 = 8784相加,它等于十进制形式的(+2354)+(-3570)=(-1216)。如上图(b)所示。这意味着不管我们认为BCD值是无符号的还是有符号的,我们仍然以完全相同的方式执行加法。

手工减去BCD数字

手工减去BCD数字很容易,即使它涉及到执行借位操作,因为我们以与处理普通十进制数字相同的方式处理这些值,而不管我们将它们视为无符号BCD值还是有符号BCD值。考虑一个涉及4354 - 2430 = 1924的简单示例,它在十进制中等于(+4354)-(+2430)=(+1924),如下所示。

在某些阶段,我们需要决定如何使用逻辑门执行减法运算。我们可以复制之前所有以二进制为中心的讨论,但是——相反——让我们简单地承认,我们将使用九和十的补技术。

让我们回到最初的4354 - 2430 = 1924的计算。同样,另一种看待它的方法是4354 +(-2430)= 1924。因此,我们要做的是在BCD中创建与-2430等价的数(即+2430的十的补数)。根据我们之前的讨论,我们知道这在BCD中是7570,这相当于-5000 + 2570 = -2430。

有三种方法可以做到这一点。首先,我们有如下(a)所示的“减法和加法”方法。这涉及到我们用9999(所有9)减去2430(+2430)来生成9的补数7569(-2431)。接下来,我们加上0001(+1)来生成十的补数7570(-2430)。

生成9和10的补语(来源:Max Maxfield)

或者,我们有如上(b)所示的“补加”技术。在这种情况下,我们只需记住0的补数是9,1的补数是8,2的补数是7,等等,然后我们将补数记下来,生成9的补数7569(-2431)。和前面一样,我们然后加上0001(+1)来生成十的补数7570(-2430)。

第三种方法是一个有用的捷径,如上文(c)所示。同样,我们从2430(+2430)值开始。从LSD开始,我们复制到(但是不包括)第一个非零数字。然后用10减去第一个非零数字,然后用9减去其余数字,得到10的补数7570(-2430)。

和前面一样,这反过来也适用。如果我们从7570(-2430)开始,生成它的10个补数,我们将得到2430(+2430)。和前面一样,关键是我们可以实现所有这些,而不需要执行借位操作。

好的,让我们回到4354 - 2430 = 1924的原始问题,如下面的(a)所示。如果我们将其改写为4354 +(-2430)= 1924,那么使用10的补数,我们的BCD计算可以执行为4354 + 7570 = 1924,这等于(+4354)+(-2430)=(+1924)的十进制,如下面的(b)所示。

用十的补数做减法(来源:Max Maxfield)

再一次,记住我们处理的是4位数的值,我们丢弃任何进位到第五列的值,只留下1924(+1924)的预期结果。

创建1位BCD 8421加法器

当涉及到使用逻辑门进行BCD数字的加减法时,我们的第一步将是创建一个1位的完整BCD 8421加法器(记住,每个BCD数字使用四个二进制位表示)。

1位全BCD 8421加法器的符号(来源:Max Maxfield)

确定我们将使用哪个逻辑门的常见方法是为函数创建一个真值表,然后执行布尔和/或Karnaugh映射最小化,那么为什么我没有在上面的图中包含一个真值表呢?

那么,请记住,如果我们希望将两个BCD数字相加,有100种不同的可能性,0 + 0 = 0,0 + 1 = 1,0 + 2 = 2…1 + 0 = 1,1 + 1 = 2,1 + 2 = 3…2 + 0 = 2,2 + 1 = 3,2 + 2 = 4等等,这相当于我们真值表中的100行。我们还需要考虑Cin的输入。由于Cin可能是0或1,这意味着我们的真值表现在将包含200行。如果您愿意,您可以创建这个表并使用它来生成一个门级实现,但我想我就不讨论了。

另一种可能是使用某种形式的只读存储器(ROM)作为查找表(LUT)。我们可以使用加法器的输入作为指向LUT中的5位字的地址。由于加法器有9个输入位(A3.. .一个0B3.B . .0,和Cin),这意味着我们需要一个ROM 29= 512个单词。当然,记住一个BCD数字只使用16个可能的4位二进制组合中的10个,我们将有许多与未使用的组合相关的浪费行。此外,由于内存的宽度通常以8位字节的倍数来衡量,而我们只有5个输出位,因此每个字节将浪费3位。

我们能想出更好的办法吗?好吧,命中注定,一个相当有趣的实现可能使用两个4位二进制加法器,如下所示。

使用两个4位二进制加法器实现1位BCD 8421加法器
(来源:Max Maxfield)

左边的真值表显示了我们可以从第一个4位二进制加法器获得的输出,该加法器基于我们的A的所有可能(合法)组合3.. .一个0B3.B . .0,和Cin输入。右边的真值表显示了我们希望从1位BCD 8421加法器获得的相应结果。

让我们从右边真值表中的Cout(“执行”)信号开始。我们希望前10行为0后10行为1。我们可以通过与左侧真值表中突出显示的红色、蓝色和绿色的输入组合相关联的行进行OR来实现这一点。红色区域对应的行可以使用来自第一个4位二进制加法器的Co(“执行”)信号的副本来识别。与蓝色区域对应的行可以使用输出S的AND来标识3.和S2从第一个4位二进制加法器。类似地,绿色区域对应的行可以使用输出S的AND来标识3.和S1从第一个4位二进制加法器。

现在让我们把注意力转向第二个二进制加法器,它的右输入集由S提供3.S . .0第一个4位二进制加法器的输出。正如我们在右边的真值表中看到的,对于前10行,对应于Cout = 0, R3.R . .0第二个4位二进制加法器的输出与S3.S . .0第一个4位二进制加法器的输出。我们可以通过强制第二个二进制加法器的左侧输入集为0000来实现这一点。

现在考虑右边真值表中的最后10行,它们对应于Cout = 1。在这种情况下,R3.R . .0第二个4位二进制加法器的输出等于S3.S . .0第一个4位二进制加法器加上0110(或十进制6)的输出。我们可以通过强制第二个二进制加法器的左侧输入集为0110来实现这一点。

这里的聪明之处在于,我们使用Cout信号本身来确定第二个二进制加法器的左输入是0000还是0110。

用逻辑门进行BCD数字的加减法

与我们使用4位1的补数来实现4位二进制加减法求解相同,我们可以使用4位BCD 8421 9的补数来实现4位BCD 8421加减法求解,如下所示。

使用9的补数实现4位BCD的加减法(来源:Max Maxfield)

一方面,这真的很好吃。另一方面,房间里有一头大象,汤里有一只苍蝇(我从来没有比喻过我不喜欢)。在我们的1补码的情况下,我们所要做的就是使用NOT门翻转(反转)每个二进制位。遗憾的是,我们的BCD 8421 9的补体并非如此,原因很明显,当我们看下面的表格时。

bcd8421数字及其9个补位的位模式
(来源:Max Maxfield)

当然,我们可以用4个BCD 8421比特作为输入,对应的4个BCD 8421 9补位作为输出,创建一个真值表,然后用它来确定从一种形式转换到另一种形式所需的逻辑门,但出于速度、功率和减少门数的考虑,只使用NOT门更可取。如果我们能获得像自我补充的BCD代码这样的东西……

自我补充(和其他)BCD代码

所以我们回到古人的智慧。正如我们之前讨论的,BCD 8421据说是一种加权代码,因为它的每一列都有一个与之相关的“权重”。还有许多其他可能的权重,包括BCD 4221, BCD 4311, BCD 5421, BCD 7421,等等。其中一些编码是自我补充的,如BCD 2421(又名Aiken)和extra -3,如下表所示。

自补(和其他)BCD代码(来源:Max Maxfield)

请注意,通过向每个BCD 8421代码添加0011(3)而获得的extra -3没有被归类为加权代码,因为不可能分配相加的列权重,如果您明白我的意思的话。

在这个表中包含十进制数字0到9的美国信息交换标准代码(ASCII)编码的唯一原因是强调这也是一种BCD编码形式。事实上,这也被称为a区位十进数字表示,其中每个十进制数字存储在一个字节中,下面四位以BCD形式编码数字,而上面四位称为“区域”位(通常)设置为固定值。

像extra -3这样的自补BCD代码的伟大之处在于,我们可以通过简单地使用NOT门反转它们的位来生成它们的9个补。当然,切换到像extra -3这样的加法器确实意味着我们必须用它的1位BCD extra -3加法器替换我们的1位BCD 8421加法器,但是我们将把这个作为练习留给读者(也就是您)。

用BCD表示定点数和浮点数

很多人认为BCD只能用于表示无符号整数和有符号整数,但事实绝对不是这样。实际上,BCD可以用来表示我们想要的任何形式的数字。例如,正如我们在下面的插图中所看到的,BCD可用于表示定点值和浮点值。

使用BCD表示定点数和浮点数
(来源:Max Maxfield)

在定点的情况下,我们有一般形式,包括这两个整数部分和小数部分。此外,我们还可以有表示只有整数部分或小数部分

值得注意的是,尽管在这个示例中我选择使用16位二进制和16位BCD值,但我们在这里并不是将苹果与苹果进行比较(苹果与食土豚将是更接近的类比)。例如,一个16位的二进制数可以表示216= 65,536个不同的值。相比之下,一个16位的BCD数字可以表示1016= 10,000,000,000,000,000个不同的值。

在二进制浮点的情况下,我在这里选择了两种常见的格式。FP16是来自IEEE 754标准的半精度浮点格式,有一个符号位,五个指数位和十个分数位。相比之下,由谷歌Brain(谷歌的人工智能(AI)研究小组)开发的BF16 (BF代表“Brain float - point”)拥有一个符号位、8个指数位和7个分数位。

BF16具有更大的动态范围,但精度低于FP16,它在AI应用程序中越来越多地使用,它通常与32位IEEE FP32单精度浮点格式一样执行,同时提供更高的性能和更低的内存使用。

老实说,我对浮点格式的理解有点模糊,所以请在上面的示例中使用“盐粒“因为我把它们拼凑在一起,就是为了让我们有话题可聊。

BCD过去和现在的用法

20世纪40年代初,当人们第一次开始建造机电和电子数字计算机时,他们认为将它们实现为电子计算机是有意义的小数的机器;也就是说,以十进制表示数字和地址的计算机,并直接以十进制提供对这些数字和地址进行操作的指令,而不需要转换为纯二进制表示。

早期专门使用十进制的计算机包括ENIAC、IBM NORC、IBM 650、IBM 1620、IBM 7070和UNIVAC Solid State 80。在这些机器中,数据的基本单位是十进制数字,以几种方案之一编码,包括BCD。

有趣的是,在第二次世界大战结束后,人们发现德国在战争开始前已经制造出了一台名为Z1的成熟机械计算机。ZI是由德国工程师Konrad Zuse创建的,它建立在使用二进制浮点表示进行计算的基础上。

到微处理器出现的时候,二进制表示已经崭露头角,但是一些家族以BDC加减法的形式提供有限的十进制支持和/或将字节范围的BCD数据(打包和解包)转换为二进制格式的指令。

与二进制系统相比,BCD的主要优点是十进制数的更准确表示和舍入,以及易于转换为传统的人类可读表示。例如十进制的0.1(1/10)很容易理解,而二进制的0.1是0.00011001100110011…(即0011的模式无限重复)。例如,最重要的是不可能存储十进制0.1的二进制等效值。

因此,尽管BCD本身不像过去那样广泛使用,尽管在新的指令集中它受到限制或不可用,但十进制定点格式和十进制浮点格式仍然很重要,并继续在许多金融、商业和工业计算应用中使用,在这些应用中,二进制格式固有的微妙转换和小数舍入错误是不能容忍的。

例如,许多国家法律规定,在计算机上进行的金融计算结果与用铅笔和纸手工进行的结果完全相同。反过来,这意味着这些计算必须使用某种形式的BCD来执行。虽然大多数计算机对在BCD中执行的计算只提供有限的硬件支持,但这种计算可以使用软件技术实现。

同样有趣的是,世界上大多数电子袖珍计算器——它们的使用涉及大量输入和输出,而计算相对较少——仅使用BCD表示来执行它们的魔力(出于某种原因,大多数用户更喜欢像0.1 + 0.2这样的计算,以提供0.3而不是0.299999……)。

这只是一个离我们家很近的现实例子,在写这篇专栏文章的时候,我抽空和朋友聊了聊乔尼什么他是巴西GridVortex Systems公司的创始人兼首席执行官。GridVortex为安全关键型和任务关键型系统提供深度嵌入式工程设计和咨询服务。

当我告诉乔尼我在做什么时,他回答说:“太巧了!我刚刚花了10个小时把我的单时钟周期二进制到bcd逻辑移植到一个完整的串行处理逻辑实现。这是我的FPGA嵌入式框架的一部分。BCD算法在PRINT_BIN2ASC块中起着核心作用,它采用一个可配置宽度的二进制数,并以与C printf(" %d ", var)大致相同的方式将完全格式化的ASCII字符流打印到流FIFO中;声明。”

我让乔尼多告诉我一些,他提出用我能用的形式写下来。我打算在这里包括Jonny的产品,但由于这个专栏已经变得面目全非,我决定将其作为一个独立的专栏发布GridVortex遇上BCD在我的Cool Beans博客上。

黑匣子问题的解决方案

最后,但肯定不是最不重要的,有几种方法可以解决本专栏开头提出的问题。我最喜欢的解决方案是我的朋友提出的乔治·哈珀.在我把这个谜题拿给乔治看后不久,他就通过电子邮件回复说:“我认为这个谜题做不出来。”过了一会儿,又有一条消息说:“我接受纠正,我对如何做有了一个粗略的想法。”第二天早上,在一个不眠之夜之后,一封得意的电子邮件来了:“这是可以做到的,你就是这样做的!”

在这种情况下,' & '代表AND, ' + '代表OR, ' !'代表NOT。特别地,观察到George的解决方案只使用了两个非门,我们看到这与内部信号的方程有关0 or1ones而且0 or2ones

提出并解决这样的问题曾经是过去逻辑设计师们流行的消遣方式。你呢?你有什么类似的谜题想和我们分享吗?还有,你有什么宝贵的知识吗?或者是关于BCD的无稽之谈?

关于“古人之谜:二进制编码十进制(BCD)”的10个思考

  1. 麦克斯,这篇文章一如既往地好。这并不是因为你如此慷慨地发表了我关于FPGA框架的文章:^)

    我不得不说,我决定放弃二进制和十进制加法器逻辑,只是为了重新学习你对一个人的补码+进位链的迷人构造,以及对九的补码+ bcd加法器链的应用。

    纯粹数字设计的乐趣。

      1. 我用过很多次黑客之乐的算法。
        从用常数除法的技巧到更神秘的东西,比如小8的平方根。
        这是一本可以放在床边书架上的书。

  2. 关于Decimal早期机器的相关说明,在Decimal Computers上有一个1951年的有趣的英国机器值得一提。
    这就是WITCH计算机,一种为英国原子能计划进行长时间计算而建造的自动计算机器。
    它有继电器控制程序排序,和德卡特龙阀门作为十进位数字存储和处理。
    它只需要10秒钟就能完成一个计算,但在一长串的小数计算上可能要折腾好几天。
    值得注意的是WITCH仍然在运行,实际上是有史以来最古老的原始计算机,并在布莱切利公园的国家计算博物馆中运行。
    10年前,我亲自去那里看了它的重启。

    1. 我去过布莱切利公园,但我不记得看到过女巫——如果我知道的话,我会要求去看的——也许下次吧

  3. 嗨,麦克斯,这是一个很好的“参考专栏”。早在20世纪80年代,Flowpro控制软件实际上就有BCD寄存器类型,因为当时七段显示器和BCD开关非常普遍。当数据移动到二进制寄存器或I/O时,BCD转换是自动的。我们最终删除了它,以便为时间格式、整数和其他子类型腾出空间。我还有一些BCD的拇指轮开关。顺便说一句,我可以不使用任何非盖茨解决谜题。我会使用三个并行的Flowpro Machine流程图。

留下回复

有特色的博客
2023年1月19日
本周周二,Future Horizons的马尔科姆•佩恩(Malcolm Penn)就半导体行业前景发表了年度三场演讲之一的演讲。我上次写马尔科姆的演讲时,感觉像是“最近”,但实际上是在2021年。那个帖子叫做Se…
2023年1月18日
GridVortex的工作人员因其在安全关键和任务关键系统上的工作而闻名,被一些人称为“故障安全裸金属家伙”……
2023年1月18日
了解为什么2023年将是多模系统的重要年份,因为芯片设计人员使用芯片技术和UCIe标准来满足高性能计算及其他领域日益增长的PPA需求。文章《为什么2023年对多芯片系统有很大的希望》首先出现在从硅到软件....上
2023年1月16日
所以你的网迹有太多的寄生虫抗性。它来自哪里?你运行了... ...

有特色的视频

Synopsys 224G和112G以太网PHY IP OIF在ECOC 2022互操作

Synopsys对此

这段特色视频展示了Synopsys 224G和112G以太网PHY IP中长到达性能的四个演示,与第三方通道和serde互操作。

了解更多

特色粉笔谈话亚博里的电子竞技

ROHM汽车LED驱动IC

逮老鼠的电子产品而且罗姆半导体

在过去的几年里,汽车设计领域有了很多创新,这些创新也包括我们汽车后部的LED灯。在这一期的Chalk Talk节目中,亚博里的电子竞技Amelia Dalton和来自ROHM半导体的Nick Ikuta聊了聊ROHM的汽车LED驱动器ic。他们仔细研究了为什么他们的四通道输出、能量共享功能和集成保护功能使这些新的驱动ic成为后车灯设计的绝佳解决方案。

点击这里了解更多关于ROHM半导体汽车照明解决方案的信息

Baidu