ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

排列组合思维:数字电路组合逻辑设计的隐藏主线与实战技巧

2026/9/5 8:58:58 拓冰建站 浏览量
排列组合思维:数字电路组合逻辑设计的隐藏主线与实战技巧 很多学数字电路的朋友一开始接触的都是分立的小规模逻辑门比如74LS系列里的与非门、或非门、反相器。那时候觉得挺简单一个芯片里就那么几个门连线也不复杂。可一旦开始做课程设计、参加竞赛或者接触稍微复杂一点的工程板卡就会发现事情没那么简单了一个功能模块动不动就要处理十几路信号、几十种状态如果还抱着一个功能画一片原理图的老思路板子会越画越乱时序收敛更是遥遥无期。这时候用排列组合的思路去重新审视逻辑器件的选型和连接方式就成了一个非常实用的突破口。我当年第一次认真琢磨这个主题是在做一个多路数据采集板的时候。板卡上要同时处理8路模拟开关的通道切换、3组编码器的正交脉冲计数、还有一大堆状态指示LED。如果每个功能都用独立的逻辑芯片堆出来光是器件数量就够让人头疼的。后来我换了个思路先把需求抽象成真值表再按排列组合的规律去合并、化简、复用逻辑资源一下子就把设计简化了大半。这篇文章就把我这些年在这条路上攒下的经验做个系统梳理从基本原理到器件选型再到具体的组合设计案例和调试心得一次说清楚。1. 为什么排列组合是数字电路设计的隐藏主线很多人看数字电路教材开篇就是布尔代数、逻辑门电路然后就是组合逻辑、时序逻辑。但教材里很少直说一个底层道理数字电路里所有的组合逻辑本质上都是在做排列组合的映射——输入信号的全排列对应输出信号的全组合。你设计的每一张真值表其实就是在穷举输入端所有可能的取值组合然后为每一种组合指定输出电平。1.1 排列组合与真值表的对应关系先看一个最简单的例子两个输入A和B每个输入只有0和1两种状态那么它们的组合一共有2²4种。这就是排列组合里的乘法原理——每个输入自由变化整体组合数是各输入状态数的乘积。放在数字电路里这个关系可以写成一个很直白的公式n个输入变量对应的全部输入组合数为2ⁿ种。这2ⁿ种组合恰好构成一张完整真值表的行数。比如2个输入4行真值表对应4种排列组合3个输入8行真值表对应8种排列组合4个输入16行真值表对应16种排列组合也就是说排列组合是描述组合逻辑输入空间的一种数学语言。你列的每一行真值表都是对输入端某个具体排列组合状态的响应定义。不把这条主线理清楚后面设计多输入逻辑函数时就容易挂一漏万——漏一项功能就错了。1.2 从组合数理解逻辑器件的门数上限排列组合还决定了另一件重要的事一个逻辑函数的复杂程度由输入组合数决定。输入变量越多真值表越庞大对应的逻辑表达式就越长需要的逻辑门就越多。这直接影响器件选型。一个3输入的函数理论上最多需要8个最小项而一个6输入的函数最小项数就膨胀到64个。你要是全用4输入与非门去搭先不谈门数光连线就可能把人绕晕。这也是为什么工程上超过4输入的组合逻辑一般不建议用分立门电路去拼——排列组合的数量爆炸让手工设计变得不现实需要换用译码器、数据选择器、可编程逻辑器件等更高抽象层次的元件。从这个角度看排列组合不仅是一个题目里计算概率的公式更是数字电路设计中的工程边界判断工具。先数一数输入变量的个数再算一算组合数你大概就能判断这个逻辑该用什么级别的器件了。2. 用最小项展开式拆解任意逻辑需求不管需求多复杂组合逻辑设计的正规流程是先做逻辑抽象、列真值表、写逻辑函数、化简最后映射到具体器件。这个流程的每一步都在跟排列组合打交道。2.1 从文字需求到真值表举个例子假设要设计一个三人表决器3个输入A、B、C输出Y当2个或2个以上输入为1时输出1。这个需求听起来很生活化但落到电路上第一步就是把所有输入组合列全ABCY说明00000人同意00101人同意01001人同意01112人同意10001人同意10112人同意11012人同意11113人同意注意这张表的行数正好就是2³8种排列组合一种不多一种不少。很多新手容易犯的错误是只列自己关心的几种输入状态比如101输出1110输出1111输出1剩下的组合不写或者写了但对不齐最后逻辑函数一化简就出错了。我的习惯是列真值表时永远从000开始按二进制递增的顺序一直列到全1像数数一样把每一个排列组合都列出来。这个方法笨但最可靠能保证输入空间一个不漏。2.2 最小项与标准与或式的写法真值表列好之后接下来是把输出为1的那些行对应成最小项。三个变量的最小项有8个分别是m0 ABCABC000m1 ABCABC001m2 ABCABC010m3 ABCABC011m4 ABCABC100m5 ABCABC101m6 ABCABC110m7 ABCABC111所谓最小项就是包含了所有输入变量的一个与项每个变量以原变量或反变量的形式出现且只出现一次。而最小项这个名字的来历跟排列组合也有关n个变量能组成的所有这样的与项正好是2ⁿ个每个与项对应着输入排列组合中的一种。上面表决器的例子Y为1的行是m3、m5、m6、m7所以标准与或式就是Y ABC ABC ABC ABC这个式子可以直接用与门和或门搭出来但显然不够简洁。这时候就要用到卡诺图化简一种把几何相邻关系转化成逻辑化简的工具。排列组合在这里的妙处是卡诺图的格子排列其实精心设计过相邻格子的最小项只有一位变量不同。正因为有这个排列上的特性你才能圈出那些可以合并、消掉变量的相邻最小项。2.3 卡诺图化简的本质是寻找组合冗余回到表决器例子把8个最小项排进3变量卡诺图你会看到m3、m5、m7可以圈成一个组m6、m7也可以和m3、m5交叉圈出一个更大组。化简结果是Y AB BC AC对比一下标准与或式和化简后的式子门数从4个与门加1个或门变成3个与门加1个或门。看起来省得不多但如果把输入变量扩展到5个、6个化简带来的资源节省就是数量级的了。我见过不少同学做实验明明化简一步就能做出来的东西非要按标准与或式硬搭结果芯片多了好几片板上飞线密密麻麻还总出接触不良的故障。化简这步不光是省门更是省事、省调试时间。我在实际操作中的经验是化简以后尽量再看一眼化简结果的物理意义。比如ABBCAC这个东西它语义上就是任意两路为1就输出1跟一开始的文字需求是对得上的。如果化简结果跟直觉明显不符那大概率是之前真值表或者化简本身的某一步出了偏差。3. 器件选型的排列组合策略从小规模逻辑门到可编程器件需求抽象和化简完成以后接下来就是让逻辑落到实际的元器件上。这一节聊聊选型的问题面对同一个真值表你有多少种实现的手段它们各自适合什么样的排列组合规模。3.1 分立逻辑门适合4变量以下的简单组合小规模逻辑门芯片比如74LS08四重2输入与门、74LS32四重2输入或门、74LS04六反相器、74LS00四重2输入与非门在变量少、逻辑简单的时候依然是很好使的。拿表决器YABBCAC来说用3个2输入与门和1个3输入或门就能搭出来。如果是实验箱上验证这是最直观的做法每个与门对应一个乘积项输入端接对应的输入变量输出汇总到或门。但要注意74LS系列里常见的或门是2输入的3输入或门要另外找或者用2输入或门级联——比如74LS32里两个2输入或门串联也能做3输入或。这些都是小问题真正需要警惕的是输入变量一多门数需求立刻爆炸。一个简单的估算方法如果化简后的与或式里总的乘积项数量超过10个或者单个与项涉及的变量数超过4个我就建议换一种实现方案了。因为分立门搭到这种复杂度布线混乱、功耗上升、传输延迟不一致带来的毛刺问题都会冒出来。3.2 译码器/数据选择器天生就是排列组合的最佳载体中规模集成电路里3-8译码器74LS138和8选1数据选择器74LS151是我特别偏爱的一类器件因为它们本身就建立在排列组合的基础上。3-8译码器的工作原理就是把3位输入的全排列组合8种一一对应到8个输出端。每一个输出端低电平有效正好对应该输入组合下的一个最小项。换句话说译码器可以直接输出全部最小项你再把需要的几个最小项用与非门合并起来就能得到任意3变量组合逻辑函数。8选1数据选择器更有意思它通过3个选择端从8个输入通道里选一个连接到输出。如果你把变量接到选择端把常数0或1按真值表的输出规律接到数据输入端那么这个芯片本身就实现了一个任意3变量逻辑函数。不用额外的门电路一片74LS151加几个上拉/下拉电阻就搞定了。数据输入端接地表示逻辑0接VCC表示逻辑1。举个例子还是表决器YABBCAC。把A、B、C接到74LS151的选择端数据输入端D0~D7分别接选择端C,B,A对应最小项Y值Dn接法000m00接地001m10接地010m20接地011m31接VCC100m40接地101m51接VCC110m61接VCC111m71接VCC这样连完了以后74LS151的输出端就直接等于表决器的输出了。整个过程连一个逻辑门都不用加而且绝对不会出毛刺问题因为选用的是同一片芯片内部的固有逻辑路径。这种真值表直接映射到数据选择器的方法我觉得是理解排列组合在器件层面应用的最好例子。3.3 可编程逻辑器件组合数爆炸时的终极方案当输入变量继续增加到5个、6个以上真值表的排列组合数到了32、64种无论是分立门还是数据选择器都会变得难以招架。这时候该上可编程逻辑器件了从CPLD到FPGA它们内部有大量可配置的逻辑单元理论上可以表示任意复杂的组合逻辑函数。FPGA里实现组合逻辑的底层结构叫查找表LUT这个东西的原理本质就是SRAM里存一张真值表。一个4输入LUT里面有16个SRAM单元正好对应4位输入的全排列组合2⁴16。你在综合工具里写一句always组合逻辑或者assign语句工具就会自动把你的逻辑函数编译成一张查找表的内容。所以从某种意义上说FPGA设计组合逻辑直接就是在查排列组合表硬件门级结构被软件隐藏了。这就带来一个很实用的小技巧你在写Verilog或VHDL的时候与其费劲化简逻辑表达式不如直接用case语句把真值表原样写出来让综合工具帮你做优化。比如always (*) begin case ({A, B, C}) 3b011: Y 1b1; 3b101: Y 1b1; 3b110: Y 1b1; 3b111: Y 1b1; default: Y 1b0; endcase end这种写法在可读性和可维护性上比手推化简表达式要好得多。而且因为FPGA底层LUT本身就是一张真值表case语句和LUT的映射关系非常直接很少会出现综合结果不理想的情况。4. 组合逻辑器件级联中的排列转移多路选择与优先编码实战学会了单个器件实现组合逻辑下一个问题是一个功能模块内部器件与器件之间该怎么级联这里同样藏着排列组合的思想而且比单器件设计更容易踩坑。4.1 多片数据选择器的扩展从8选1到16选1设计中经常遇到输入信号通道数超过单芯片能力的情况。比如8个传感器信号要选一路输出用一片74LS151就够了但项目里实际有16路信号这时候就得扩展。16选1的思路不复杂用两片8选1再加一个额外的选择位。16路信号分成两组各接一片74LS151的数据输入。两个芯片的选择端A0、A1、A2并接在一起作为16选1的低3位地址第4位地址S接到其中一片的使能端低有效和另一片的使能端通过反相器接高有效。当S0时第一片工作第二片禁止S1时反过来。最终两片芯片的输出再用一个2选1合并。这种结构的本质是把16种排列组合拆分成两个8组的子排列。低3位地址在组内选择最高位地址在组间选择。你可以在脑袋里把它理解成一个二维矩阵4位地址构成了行和列组合寻址这样去想就不会乱。不过这里面有一个工程细节很容易翻车2选1合并用与门和或门搭的话要么两个与门的传输延迟不一致导致尖峰毛刺要么使能端翻转的瞬间两片芯片出现了短暂的同导通状态。我在实验里遇到过两片74LS151的使能端响应时间不完全一致的情况导致输出低电平瞬间被短暂拉高接到计数器上就产生了误计数。更稳的做法是用三态门或者直接选用带扩展功能的数据选择器。74LS150是16选1的片子内部已经处理好了扩展逻辑一片搞定省去级联的麻烦。所以我的建议是能用单片高位数选择器就别用多片低位数级联芯片价格差距通常很小但可靠性差距不小。4.2 优先编码器的排列降维几十种状态只需几位编码再说说优先编码器它是另一类与排列组合强相关的器件。74LS148是8-3优先编码器输入8根线I0~I7低有效输出3位二进制码。它做的事情是把输入端的哪一根线有效这一种排列状态编码成对应的3位组合值。8种输入状态对应8种输出编码本质上就是一组一一对应的排列映射。优先编码器特别适合处理中断优先级、按键扫描这类场景。你不需要知道全部按键的状态只需要知道优先级最高的那个是谁。电路里常见的一个问题是想扩展输入数量比如16路中断源要用两片74LS148级联。级联的方式有点巧妙两片的输出直接并接低优先级片的EO输出使能接到高优先级片的EI输入使能。这样当高优先级片没有输入时它允许低优先级片工作一旦高优先级片有输入就会禁止低优先级片。优先级的排列就这样被硬件实现了。类似的还有二-十进制优先编码器74LS147把10路输入编码成BCD码。它实际上是在做10取1到4位码的组合映射。虽然现在MCU很少用这种芯片了但在硬件面试、竞赛方案中依然能看到优先编码器处理输入压缩的影子。4.3 奇偶校验器中的排列奇偶性奇偶校验是一个很有代表性的组合逻辑应用它直接用到了排列组合里奇偶性的概念。9位奇偶校验器74LS280可以接受9路输入输出端分别给出1的个数为奇数和1的个数为偶数两个信号。它的内部实现其实是把9个输入的所有排列分组凡是输入中1的个数为奇数归入一组输出奇数标志1的个数为偶数归入另一组。这个分类完全是对输入排列组合的一种划分。用布尔代数的语言说它实现了9个变量的异或运算——因为是逐级异或而异或本身就是判断两个数是否不同的基本门。在串行通信里发送端和接收端都需要做奇偶校验。发送端计算数据位的奇偶性把校验位附加到数据后面接收端对整个数据加校验位做奇偶校验如果结果与预定模式不符就知道传输过程中有一位发生了翻转。这种在传输层保障数据完整性的做法底层逻辑就是排列组合的奇偶性判断。写代码的话一个for循环异或所有位就能实现但在高速接口里硬件逻辑器件处理这种排布方式是有明显速度优势的。5. 时域上的排列组合从竞争冒险到对数字电路音乐电路的启发到现在为止聊的都是静态的、纯组合的逻辑设计。但工程上有个绕不开的问题组合逻辑虽然有输出却不代表它一定稳定无毛刺。当输入信号不是同时跳变的时候组合逻辑内部各路径的传输延迟不同就会导致短暂的错误输出。这个现象叫竞争冒险它同样可以用排列组合来理解。5.1 竞争冒险不同路径延迟的组合差异考虑最简单的表达式Y A A。按照逻辑Y恒等于1没有输入能让它变成0。实际电路里A由反相器产生信号到达或门输入的时间会比原信号A晚一个反相器的传输延迟。在A从1跳变到0的那一瞬间或门两个输入端可能出现一小段同时为0的情况输出Y就会产生一个短暂的负脉冲毛刺。这个现象的本质是两种可能的信号路径A直达路径和A经过反相器的路径在时间轴上形成了不同延迟的组合排列。如果A的跳变速度足够慢或者两条路径延迟恰好相差较大毛刺就更明显。消除毛刺的常用办法是增加冗余项。比如表决器化简成YABBCAC后实际上还会在A、B、C变化的某些瞬间出现毛刺加上AB这个冗余项通常来不及覆盖所有跳变。真正的可靠做法要么是增加一个输出滤波电容要么是在输出端用D触发器打一拍让毛刺在时钟边沿到来之前消失。说到这我想起一个很常见的实际场景数字电路的实验箱上接了音乐电路。网上流传的数字电路音乐电路设计原理其实是用计数器产生不同分频去控制蜂鸣器的输出频率。不同音符对应的是不同的计数循环长度这本质上也是一种计数排列的变化。频率越高计数值越小输出翻转越快音调越高。这些分频和计数值的排列组合决定了乐曲能不能正确播放。如果你在实验里遇到了蜂鸣器声音不对音符顺序乱了这种问题最值得怀疑的地方不是蜂鸣器本身而是控制音符切换的逻辑。要是用组合逻辑直接驱动蜂鸣器切换音符的瞬间因为计数器的各个输出位不是同时翻转的音符频率会瞬间乱跳听起来就是滋滋的杂音。处理方法也很简单让控制音符的寄存器只在时钟边沿更新相当于把组合逻辑输出的毛刺与外部世界隔离这就属于从竞争冒险角度去优化一个已经能工作的音乐电路。5.2 时序逻辑中的状态计数排列组合的循环再往深一层时序逻辑里也有排列组合的影子。在一个模8计数器中Q2Q1Q0三个触发器的状态从000到111循环正好是3位二进制数的一个完整排列。格雷码计数器则是每次只改变一位本质上是一种保证相邻状态距离为1的排列规则。这些状态本身都是排列组合的具体实例。设计有限状态机时状态编码方案的选择同样是一种排列组合。以四状态为例状态码有000、001、010、011四种常用编码以及格雷码00、01、11、10这四种相邻变化。不同编码方案的优劣在组合逻辑资源消耗和时序可靠性上有明显差异。格雷码在电机编码器、异步FIFO指针等场景中是主流选择因为它能保证快到快读的场景下不产生非法状态跳变。另外异步FIFO的老生常谈问题——读写指针跨时钟域同步——实际也是一种特殊的排列组合问题。两个时钟域的读写指针各自在自己的域内递增只有在同步之后才能做比较。处理不好指针错位FIFO就会溢出或者下溢。这也是为什么很多工程师提到cdc mailbox这个概念跨时钟域传递邮箱消息本质上要求消息在目的时钟域中稳定可见而稳定的前提是信号跳变时刻不能落在采样的触发沿上。排列组合在这里表现为什么时刻采样什么信号是一种动态的时序组合。6. 可复用的设计套路从真值表到电路的提效方法聊了这么多原理接下来说几个可以直接抄作业的方法。这些套路是我在实验室和项目中反复验证过的能实打实减少设计时间。6.1 最小项查表法设计组合逻辑当你拿到一个功能需求先别急着画门电路。我的做法是严格按照下面四步走把需求抽象成输入输出信号明确变量个数列全真值表一行不漏在真值表里找到所有输出为1的行写最小项决定实现方式表达式化简、数据选择器直连、还是写case语句这个方法对新手特别友好不容易出错。熟练了以后甚至可以跳过第3步的文字形式直接盯着真值表心中就有电路。6.2 用数据选择器快速搭建任意3变量逻辑如果手头正好有74LS151而且逻辑函数不超过3个输入变量就直接用查表法一分钟接完电路把变量A、B、C接到选择端对照真值表把数据输入端D0~D7接VCC或GND输出端Y就是函数值这个方法比画门电路快得多而且调试极其方便只要检查数据端接对不对就行了。数据端接线一目了然出错了也能瞬间定位到具体那一行真值表。变量超过3个的时候也别急着放弃。4变量的函数可以用两片74LS151加额外逻辑实现但性价比会下降。更实用的做法是用手头现成的LUT型FPGA写4行case语句。我经常拿着小脚丫FPGA或者Artix-7的开发板做原型验证综合后的资源报告里能看到每个LUT的利用率稍微优化就能得到漂亮的布线结果。6.3 信号命名与模块划分中的组合管理最后一个套路听起来比较软但实际收益巨大。在模块化设计时把相关联的组合逻辑信号按位宽分组命名并对每组信号的排列顺序做统一约定。比如多路选择器的选择端按A[2:0]命名数据端按D[7:0]命名所有真值表里位序和总线位序保持一致。这样一来写验证testbench的时候穷举输入组合只需写一个循环和位移操作不易出错在仿真波形里观察信号恢复起来也直观。我在维护一个多人协作项目时深深体会过这个约定的价值。有人习惯把使能信号叫EN有人叫en有人叫ENABLE信号位序有的从高到低有的从低到高结果组合逻辑的排布五花八门最后联调时花了好多时间对齐接口。后来统一规范所有使能叫en所有数据总线按bit0在最右所有状态标志按bit位与事件编号一致整个项目的排错效率瞬间提升了一截。7. 一次真实的调试经历数据选择器级联中的地址组合错乱前面讲了很多理论最后分享一个实际的排查案例。这是我在设计一块数据采集板时遇到的正好能串起排列组合与器件级联的所有要点。7.1 现象通道选择与预期不符的诡异错位板卡上一共有16路模拟信号我按前面的方案用了两片74LS151通过一个反相器控制使能端组成了16选1。测试时发现选择地址0x0和0x1时输出的是正确的通道但选择了0x2之后输出就错乱了而且错乱规律看起来毫无章法——不是简单的高位地址反了也不是个别通道接反。这个现象让我第一反应就是查接线。但查了几遍数据端和选择端都没有发现焊错。最后用示波器逐个引脚测量才定位到问题根源。7.2 排查从排列组合矩阵找突破口我先列了一张表把实际输出与预期通道一一对照然后把错误模式写下来。结果发现错误的通道选择和预期通道之间的差总是一个固定的偏移量而且只出现在高位地址为1的情况。这个规律让我开始怀疑不是接线问题而是两片芯片的使能逻辑有问题。翻看数据手册74LS151的使能端是低电平有效但它的输出并不是简单的三态——当使能无效时输出并不是高阻态而是固定逻辑0。我之前的设计是让两片输出直接短接再用与门/或门合并。当使能无效的那片输出固定0确实不会影响有效的另一片这个思路本身没错。但问题出在我用来生成使能信号的反相器上。我用的反相器是74LS04输入从高到低跳变时传输延迟大约十几纳秒但另一个芯片的使能路径上经过了两个门的延迟。这样在高位地址S翻转的瞬间两片芯片的使能端有一个短暂的重叠窗口导致两片芯片同时处于有效状态。此时两片输出直接短接在一起一个输出0一个输出1低的被高的拉高了一瞬或者高的被低的拉低了一瞬产生了毛刺。如果这个毛刺落在后续电路采样的时钟沿上就可能被记录成完全不同的通道地址。7.3 修复给使能路径做延迟对齐定位到问题后修复反而简单了。两个方案在输出端加一个8选1的额外组合逻辑避免输出端直接短接。但这个方案会增加一片芯片不值得。把反相器换成同相缓冲器74LS244并人为地在另一条路径上也加一个同相缓冲器保证两条使能路径延迟严格一致。这样无论地址怎么翻两片芯片的使能状态不会出现同时有效的情况。我采用了第二个方案改完以后用示波器反复触发地址切换再也没看到毛刺。后来我又把这套延迟对齐的思路用到其他项目里只要是多条并行信号路径无论它们是地址线、数据线还是控制线都要尽量保证各条路径的传播延迟一致。这其实也是高速PCB设计中等长布线思想的逻辑门级版本。8. 动手做一个小项目用74LS151实现4变量多数表决器理论说了不少最后来一个可复现的小项目。4变量多数表决器输入A、B、C、D输出Y要求4个输入中有3个或以上为1时输出1。这个项目用分立门做很麻烦但用两片74LS151可以做得又快又好。8.1 逻辑到芯片的映射4变量函数如果用一片8选1需要把4个变量都接进去一片不够。我的做法是用两片74LS151把高两位变量C、D作为片选控制低两位变量A、B作为每片内部的选择地址。更具体地把两片的选择端A0、A1分别接A、B然后用C、D经过简单组合逻辑切换两片的输出。但这样连线依然复杂。另一个更优雅的做法是利用数据选择器的高级用法——把一部分输入变量接到数据输入端而不是选择端。这本质上是对排列组合的一种降维处理。以4变量多数表决器为例先固定两个变量比如C、D为分组变量它们形成4种组合CD00、01、10、11。在每一种CD组合下输出Y仅由A、B决定于是可以写出一张关于A、B的小真值表当CD00时A、B无论怎样都不可能有3个1所以Y恒为0当CD01时要总共至少有3个1需要A和B都为1所以YAB当CD10时同样需要A和B都为1YAB当CD11时已经有两个1了再加A或B任意一个1即可YAB这个分解很有意思原本16种输入组合的4变量函数被拆成了4组2变量的子函数。这4个子函数可以用74LS151的数据输入端来实现——每个数据输入端接一个关于A、B的组合逻辑。8.2 具体接线步骤手头有一片74LS151时接线如下把A、B接到74LS151的选择端A0、A1把D0接0对应CD00的情况D1、D2通过一个2输入与门74LS08产生A和B相与对应CD01、10D3通过一个2输入或门74LS32产生A和B相或对应CD11C、D通过一个2线-4线译码器或者用74LS139双2-4译码器产生四路分组选通信号分别接到74LS151的四个选通使能端这个方案用了一片74LS151、一片74LS08、一片74LS32、一片74LS139一共4片小芯片比起直接用门电路搭4变量真值表需要十几个门已经省了不少。而且调试起来非常直观通道0异常就查D0的接线通道3异常就查D3的或门输出。8.3 验证与测试建议上电以后建议按下面的表一项一项测试ABCDY000000111110111110111110111111特别提醒测试时不要跳过恰好3个输入为1和全1这两种情况。多数表决器最容易出错的边界就是这里。9. 最后的经验补充组合逻辑排布中的几个常见坑文章最后把这几年来在组合逻辑排布上踩过、见过的一些坑集中说一下字不多但每条都是真金白银。9.1 使能端的悬空数据选择器、译码器这类的使能端无论你用不用都一定要接到确定的电平上。悬空相当于输入浮空噪声一拉就可能让芯片误动作。特别是CMOS器件悬空输入还会导致静态功耗上升更严重的可能会损伤芯片内部结构。这个经验我在一次多路采集板调试中体会很深使能端悬空导致的偶发错通道故障花费了我一整个下午去定位。9.2 输出端不要长期短接前面提到过让两个芯片的输出端直接短接在使能路径时间差存在的情况下是危险的。标准的做法是用三态门配合输出使能信号或者用多路选择器在外部合并。如果实在要直接短接一定要确认两片器件在任何时刻最多只有一片处于输出有效状态。9.3 注意数据手册里的输出特性很多器件的输出在高阻态时其实不是真正的高阻而是一个很大的电阻输出端还会带上一点残余电压。在高速开关场景下这个残余电压叠加到其他信号上可能造成逻辑误判。所以我一般只在低频或纯数字逻辑场景里直接并接芯片输出高速场景一定会加缓冲或三态隔离。9.4 不要轻视真值表的完整性最后还是回到这个主题的根本一张完整的真值表是你和电路之间的契约。任何一行遗漏都会导致逻辑函数与真实需求不符。列真值表不是走过场它本身就是设计的一半。我见过太多项目出问题最后追根溯源就是当初某个输入组合的输出值没定义清楚。把排列组合这个概念吃透了你会发现数字电路的世界并没有那么复杂。从最小的与非门到上百万门的FPGA底层遵循的规律其实是一样的穷举输入空间映射输出行为再用合适的器件把这张映射表物化出来。希望这篇整理能对你理解数字电路、驾驭逻辑器件有所帮助。有疑问欢迎在评论区交流我会尽量回复那些我实际碰到过、有具体场景的问题。