这篇文章分为三个部分,解读某个学生在EDN姐妹媒体EEWeb论坛上所提出的一个问题,其核心如下:他的老师布置了一个布尔方程式;然后要求他创建相应的真值表;然后再告诉他要进行卡诺图化简;最后要他必须只使用与非(NAND)门或只使用或非(NOR)门来实现这个电路。
因此,一开始要做的就是考虑为什么首先要提出这种问题。接下来就是更详细地研究这个学生的特定问题,并将其转换成最初的与或解决方案。然后,就是考虑将与或电路转换为与非-或非对应电路的一般概念。最后,就是用所学的知识来解决这个学生的最初问题。
那么,为什么老师都会要求他的学生只使用与非门或只使用或非门来实现逻辑函数?(请注意,我特地不说“只使用与非门或或非门”,因为这有可能被理解成可以使用与非门和或非门,而不使用与门和或门。)
尽管学生可能对此感到惊讶,但不一定就说明老师是个不成功的人,他生活中唯一的乐趣就是去折磨学生。话虽这么说,但回想起我自己还是一名学生的日子,我们最好不要实际排除这种可能的动机。
我不由自主地想到老师给学生布置这个作业可能有以下原因:
1.给出一个用与门或或门(乘积的和或和的乘积形式)描述的电路,然后要求学生将其转换成只使用与非门、只使用或非门或使用与非门和或非门组合的另一种表现形式,是确保让学生了解各种逻辑门如何工作的好方法。它还有助于确保让学生了解德·摩根变换之类的内容。
2.如果你想使用简单的逻辑器件——例如包含六个非门或四个2输入与门、或门、与非门或或非门的双列直插(DIL)封装集成电路(IC)——来设计印制电路板(PCB),而你可能正好没有与门之类的东西,但是碰巧有一个与非门和一个非门备用(或者可能是一个或门和三个非门),那么在这种情况下,你对逻辑门的理解就可能扭转局面。
3.最简单的逻辑门是非门。假设是CMOS电路,那么一个非门需要两个晶体管。与非门和或非门要复杂一些,这两种门每种包含四个晶体管。然后是与门和或门,这两种门每种包含六个晶体管。也就是说,如果使用与非门或或非门代替与门或或门,那么所使用的晶体管数量可以减少三分之一。
4.关于上一点,与门实际上是由一个与非门后接一个非门构成的(同样,或门是由一个或非门后接一个非门所组成)。除了使用4+2=6个晶体管外,这还说明与门(和或门)具有两级延迟。因此,如果可以使用与非门取代与门(或用或非门取代或门),所得到的电路会运行得更快。
5.顺便稍微说一句,本文所讨论的所有内容在我的书“Bebop to the Boolean Boogie”中都有详细描述。
实际上,现在已很少有人在门级进行设计。取而代之的是以较高层级的抽象捕获设计,然后使用逻辑综合引擎生成相应的门级等效设计。这说明上述第2点到第4点不再像以前那样重要。
你可以争辩说,第1点也是如此,但我不太同意。我的想法是,它类似于使用计算器进行计算的概念。如果你有一个计算器,那你实际上就不需要知道如何对整数、实数和浮点数进行加减乘除运算,但是,如果你掌握了这类知识,那么当你计算器的电池没电时,它就可以派上用场。同样,尽管你可能不需要每天处理布尔结构,但是在需要时知道如何处理就会非常方便。
所以,下面是那个学生给我的。他首先说,老师向班级展示了以下方程式:
那个学生还告诉我,他已经使用这个方程式生成了下面的真值表,但是从这时起,他遇到了麻烦而做不下去了。
好吧,我不得不告诉他,我对他遇到的问题一点都不感到惊讶,因为在他的方程式里有六个乘积项,每个乘积项在他的真值表的输出列中都应该有一个对应的1,但是实际上,他的真值表的输出列中只有五个1。
我对这个情况进行了反复考虑,我认为潜在的问题是他缺乏对基本原理的理解。还有一点是,如果有一个学生感到困惑,那么就很可能不止他一个人。最后但同样重要的是,我记得我刚开始时有点困惑不解,所以我会花一点时间逐步解决这个问题(如果你感到无聊,请随时跳过;或者,你也可以随时试着发现我可能引入的任何故意的错误,以便了解你是否有集中精力)。
我要做的第一件事就是在方程式中对乘积项进行编号,以便可以对我们所处的位置和所做的事进行跟踪(如果我们是来真的,那么就不必费心对乘积项进行编号):
下一步是创建真值表。可以从以标准二进制数表示的所有输入组合开始,如下面的(a)所示;然后将与六个乘积项相对应的六个1加起来,如(b)到(g)所示;最后把任何剩余的输出“位置”都填入0,如下面的(h)所示。
这里要注意的重点是,将方程式转换为真值表确实一点也不困难。话虽如此,但无论谁这样做,都必须了解这个过程背后的基本逻辑。再看一下这个方程式,其本质可以这样来表达:“如果第一个乘积项(第一个与函数)为真,则输出为真(逻辑1),或者如果第二乘积项为真,则输出为真,或者如果第三乘积项为真……)。这就是为什么可以在与每个乘积项相对应的输出列中简单地填写1——如果这些乘积项中的任何一项为真,则输出为真(1),否则输出为假(0)。
下一步是创建卡诺图。首先是创建网格本身。由于总共有三个输入,因此可以使用两种方法(方案)来做这一步,如下所示:
选择使用哪种方案都没有关系。这两种情况下答案都是相同的(如果不是,那就确实有问题)。这里使用方案1,这种方法我比较喜欢。如果有任何学生正在阅读本文,我建议你在这步完成后从此处开始,自己使用卡诺图方案2进行重做,以便确保你真正了解这个过程。
查看卡诺图方案1,观察“AB”所处的位置。右侧是与AB输入相关的0和1的四种组合:“00”、“01”、“11”和“10”。请务必注意,这四种组合是以格雷码形式进行排列,这样就可以让我们从一个值移到相邻值时,只会有一位发生变化。这是卡诺图运作的关键。
在二进制代码中,当从01过渡到10时,会有两位发生变化。相比之下,如果查看格雷码(01至11)中的相应转换,则只有一位发生变化。
此外,请注意二进制代码的最后一行。如果要从这一行转而过渡到第一行(11到00),那么就会再次有两位发生变化。但是,如果查看格雷码中的相应行(10到00),则会再次看到只有一位发生变化。
好了,现在来填充卡诺图。这一步是向方程式中的乘积项所对应的每个方框中填入1。这里再次按照下面的步骤逐步填写(圆圈中的小数字1到6与初始方程式中的乘积项相对应):
这里需要注意的另一点是,不需要真值表即可填充卡诺图。这里要做的只是沿着方程式一项一项来,对每个乘积项在对应的卡诺图“方框”中填入1。
下一步是使用卡诺图来化简逻辑表达式。从上面的最终卡诺图(f)可以立即看出,可以将其简化为三个项。像往常一样,我们一次一次地完成每一步。
观察下图中用红色圈出的两个1,我们知道,这两种情况下的输出均为1。对于这两个框中的每个框都有A=0,C=1,因此这两个值很重要。但是,这两个框中有一个是B=0,另一个则是B=1。这就是说,只要A=0,C=1,那么我们就不在乎B是0还是1。
接下来看一下下图中用红色圈出的第二组两个1。对于这两个框中的每个框都有A=1,C=0,因此这两个值很重要。但是,这两个框中也是有一个是B=0,另一个是B=1。这就是说,只要A=1,C=0,那么我们就不在乎B是0还是1。
最后但同样重要的是,下面来看一下下图中用红色圈出的一组四个1(卡诺图的技巧之一是可以将相同的1用作多个组的一部分)。
在这种情况下,这四个框中有两个框是A=0,另外两个框则是A=1,这就是说我们不在乎A是0还是1。类似地,这四个框中有两个框是C=0,另外两个框是C=1,因此我们就不在乎C是0还是1。实际上,对于所有这四个框而言,唯一恒定的输入是B,它始终为1。
这样,就可以使用卡诺图最简表达式来编写优化的乘积和方程,如下所示:
由此就可以使用非门、与门和或门轻松绘制相应的门级原理图,如下所示:
至此,我知道你会跟我说我们没有使用!B信号(这里使用“!”字符来表示非B,因为在文本里在字母上画一条横线有点难),但我们将在不久的将来使用它。说到这,未来比你想象的要近。这是我们必须考虑的重点,因为那位令人讨厌的老师他所布置的作业是只使用与非门或或非门来展示最终电路。
让我们从容易的开始,先解决本例中的三个非门。首先我们先回忆一下,五种常见基本门的真值表如下所示:
也就是说,如果将与非门的输入捆绑(连接)在一起,那么得到的功能就是非门。如果将或非门的输入捆绑在一起,那么得到的结果也相同。也就是说,以下功能相同:
奥古斯都·德·摩根(Augustus DeMorgan,1806至1871年)是乔治·布尔(George Boole)的同龄人。他在符号逻辑领域做出了重大贡献,尤其是我们现在在用的一组规则——德·摩根变换。
为了对布尔表达式进行德·摩根变换,需要按以下步骤进行:
1.将所有的与运算符换成或运算符,反之亦然。
2.将所有的输入变量反转,也可将任何0换成1,反之亦然。
3.将整个函数反转。
4.减少任何多次反转。
一般而言,我们倾向于对多项式进行德·摩根变换,但是也可以对单个门进行变换,这样就得到以下结论:
我不了解你,所以没办法解释,但是在查看了上面的德·摩根变换后,我感觉很满意,并且感觉在(逻辑)世界中一切都是对的。
老实说,现在我们已奠定了基础,这个部分非常容易。让我们回忆下,使用非门、与门和或门实现的电路是什么样的:
我对它们进行了颜色编码,以便让我们清楚了解自己在做什么。下面就来做出决定,我们只希望使用与非门。因此,使用前面讨论的所有内容,就可以将非门、或门和与门换成与非门。
和往常一样,我们一步步来做。首先从左边用粉红色表示的三个非门开始。我们知道,可以将这三个门中的每一个换成一个2输入与非门(它们的输入是捆绑在一起),所以这里没有问题。
接下来来研究电路右侧用绿色表示的3输入或门。根据德·摩根变换,我们知道,可以用一个3输入与非门(其输入带有非门)来代替它,如下所示。
当然,可以将这三个非门中的每一个再次用一个2输入与非门来替换,如下所示:
因此,现在只需要考虑电路中间两个用蓝色表示的与门了。当然,德·摩根变换在这里帮不上忙,因为与门的等效电路是将或非门的所有输入都加上非门,但这个作业不允许我们使用或非门。
有时,我们倾向于使事情变得比所需要的更复杂。在这种情况下,要做的就是记住,与门实际上是由与非门后接一个非门形成的(同样,或门是由或非门后接一个非门所组成)。也就是说,可以像下面这样来替换与门:
当然,由于作业要求只使用与非门,因此必须将非门替换成其等效的2输入与非门,如下所示:
现在,万事大吉了。因此,如果把上述所有变换结合起来,那么只使用与非门的实现就如下所示:
虽然上面的电路可以执行所需的功能,但是这里有几个门浪费了,因为如下面用红色框框出的部分所示,有两个地方出现了非门接非门的情况(当然都是用与非门来实现):
每当以非函数形式出现偶数次反转时,都可以用一条简单的线来代替它们。因此,稍作修改就得到如下所示的最终电路:
如果非门、与非门和或非门分别等于一级延迟,与门和或门分别等于两级延迟,那么在最初的非门、与门和或门电路实现中,最坏情况的输入到输出路径就等于1+2+2=5级延迟。相比之下,经过优化的只使用与非门的实现则仅会发生最多1+1+1=3级延迟。
再说一次,如果有任何学生正在阅读本文,只是为了确保你100%掌握以上所有内容,建议你以以上讨论为基础创建只使用或非门的实现。在此期间,欢迎提出任何意见和问题,也希望能有更多有经验的读者愿意分享任何相关的提示与技巧。
(本文授权编译自EDN姐妹网站EEWeb,原文参考链接:Implementing Logic Functions Using Only NAND or NOR Gates,由赵明灿编译)
本文为《电子技术设计》2021年1月刊杂志文章,版权所有,禁止转载。免费杂志订阅申请点击这里。
(责编:赵明灿)