
数字电子这门课我见过太多人卡在时序逻辑这一章。前面组合逻辑学得还挺顺与或非门、译码器、选择器真值表一套就出结果结果一到时序逻辑电路看到波形图、状态表、触发器这些东西立刻开始怀疑人生。其实问题不在于时序逻辑有多难而在于触发器的概念没有真正吃透。你把触发器的原理和特性搞明白了后面计数器、寄存器、状态机、数字钟全部都是在这个最小记忆单元上面长出来的东西。这篇文章我就围绕数字电子里最核心的两个关键词——时序逻辑电路和触发器把“记忆”这件事彻底讲透。不管你是在准备考试还是想自己动手搭一个数字时钟只要你愿意把触发器这几个模型弄明白时序逻辑这道坎就过了。1. 组合逻辑靠“算”时序逻辑靠“记”——先看两类电路的本质差异1.1 组合逻辑一锤子买卖组合逻辑太友好了输出永远只取决于当前的输入。一个与门两个输入都是1输出就是1哪怕是在上电瞬间也是这样。它没有任何“记忆”没有“历史”输出跟过去发生的事情毫无关系。这就是为什么组合逻辑好学好懂它就是你输入什么它立刻输出什么一台纯计算器连内存条都没有。所以组合逻辑的分析方法也简单列真值表、写逻辑表达式、化简、画电路图。每一步都有固定套路只要细心基本不会出错。你很少听说有人在组合逻辑上“莫名其妙出bug”因为它的因果关系是静态的、确定的。1.2 时序逻辑输出要看“之前发生过什么”时序逻辑不一样它的输出不仅要看现在的输入还要看之前存下来的状态。举个最直白的例子——计数器每一秒加1。计数器的输出必然是“之前数到几”加上“现在有没有来一个时钟脉冲”共同决定的。少了“之前数到几”这个历史信息计数器根本无从谈起。这个差别用一张表就能看得很清楚维度组合逻辑时序逻辑输出依据只看当前输入当前输入 历史状态有没有记忆没有有靠触发器保存典型电路与或非门、译码器、选择器计数器、寄存器、状态机对时钟的依赖可有可无通常必须有分析工具真值表、逻辑表达式状态表、状态图、时序图生活化的类比组合逻辑就像一台不带内存的计算器你按什么键它显示什么数关掉电源一切归零时序逻辑像一个记流水账的账本你问它“现在余额多少”它得把之前每一笔账都考虑进去。账本最核心的东西不是笔而是“已经记下的内容”——这就是状态而触发器就是保存状态的那个设备。1.3 时钟信号给记忆打节拍既然时序逻辑要保存历史状态那什么时候保存、什么时候更新必须有一个统一的规则否则整个电路会乱套。绝大多数时序逻辑电路采用同步方案所有触发器共用同一个时钟信号时钟每跳一次大家统一采样输入、统一更新状态。时钟信号的高电平、低电平其实好理解但对时序逻辑来说最重要的是边沿——电平从0变1的上升沿或者从1变0的下降沿。边沿触发的设计理念后面讲触发器时会反复出现。你只需要先记住一个结论同步时序电路是踩着时钟的节拍工作的就像军训走正步口令喊“一、二、一”大家一起迈腿步调才一致。要是每个人想什么时候迈就什么时候迈整个队伍就散架了。2. 触发器凭什么“记住”一个比特双稳态与边沿触发的底层逻辑2.1 双稳态两个反相器互相“撑腰”要理解触发器先要理解它为什么能记住信息。最简单的存储单元是把两个反相器首尾相接第一个反相器的输出接到第二个反相器的输入第二个反相器的输出再接回第一个反相器的输入。假设第一个反相器输出1那么第二个反相器输入1输出0这个0反馈回第一个反相器维持它的输入为0、输出为1。于是整个环路稳定在“第一个输出1、第二个输出0”的状态。反过来也能稳定在“第一个输出0、第二个输出1”的状态。两种状态都是稳定的外力不去推它它会一直保持住。这就是双稳态结构它揭示了“存储”的本质用两个互相反馈的反相器构成两个稳定状态0代表一个状态1代表另一个状态。你想让它从0变1就在外面推一把推完之后反馈环路会自己维持新的状态。这个过程就像跷跷板的两端要么左高右低要么右高左低你把它拨到哪边它就待在那边不会自己慢慢回到中间。实际电路里的RS触发器本质就是把这两个反相器用与非门或或非门实现出来同时留出外部输入端允许你去“推”它、去改变它。你可以用两个与非门自己搭一个基本RS触发器两个与非门交叉耦合一个门的输出接另一个门的输入端。这个交叉耦合结构是所有触发器芯片的核心雏形。2.2 电平触发不靠谱边沿触发才靠谱早期的锁存器是电平触发的使能信号为高电平时输出就跟着输入走。这种做法有一个致命的问题叫做“透明”。什么意思使能期间输入端变化多少次输出就跟着变多少次你根本没法让它在某一个确定时刻拍板。放在同步时序电路里这种不确定性会带来雪崩式的混乱。工程人员的解决办法是边沿触发只有在时钟信号上升沿或下降沿到来的那一瞬间才把当时的输入“拍”进触发器其余时间输入再怎么跳变输出都稳如泰山。这个思路就像拍合照快门按下的瞬间大家的表情被定格快门没按之前你随便动都没关系。边沿触发让触发器有了精确的采样时刻也让我们能设计出真正意义上的同步时序电路。现代工程中用的D触发器、JK触发器基本都是边沿触发。记住这一点再去看任何触发器的时序图脑子里就有了主线看时钟边沿边沿处输入是什么输出就变成什么其他时间输出不变。2.3 建立时间和保持时间触发器的“规矩”触发器虽然能采样但不是神仙。输入信号必须在时钟边沿到来之前提前稳定一小段时间这个时间叫建立时间setup time时钟边沿过去之后输入信号还必须继续保持稳定一小段时间这个时间叫保持时间hold time。这两个时间参数芯片数据手册里都会写它们是判定电路能否可靠工作的核心依据。为什么必须有这两个时间因为触发器内部那双稳态结构要靠反馈环路完成状态的翻转这个翻转需要物理时间。如果输入信号在采样瞬间还在跳变触发器的内部节点就可能陷入既不是0也不是1的中间状态专业叫亚稳态。亚稳态的输出可能乱跳可能缓慢恢复也可能在几个周期后才稳定而且恢复时间完全随机。这种不确定性对数字系统来说是很要命的。在设计同步电路时要检验时序裕量时钟周期必须大于组合逻辑的传播延迟加上建立时间否则输入信号来不及稳定就被采样了。很多“偶尔出错、时好时坏”的电路排查到最后大概率就是时序裕量不足。这句话等你以后调FPGA或者高速单片机电路时会有深刻体会。提示碰到莫名其妙的随机错误先别怀疑芯片坏了用示波器或者逻辑分析仪看看时钟沿前后的输入信号是不是刚好在建立保持时间窗口内跳变。3. 四种触发器逐个拆RS、D、JK、T到底该怎么用3.1 RS触发器最朴素的置位复位单元RS触发器是触发器家族的老祖宗。S代表置位SetR代表复位Reset。用与非门搭的基本RS触发器是低电平有效S端来一个低电平输出Q置为1R端来一个低电平Q清为0S和R都保持高电平时输出维持不变。这里有个必须注意的特殊情况S和R同时为低两个与非门的输出都会被迫变1这违背了Q和/Q互为反相的约定属于禁用状态。实际工程芯片里很多RS触发器做成了复位优先当R和S同时有效时强制让电路进入复位状态Q0这样就消除了不确定的禁用态。这类芯片学名叫复位优先RS触发器在需要“急停优先”的控制电路里很实用。RS触发器的价值不在它本身有多常用而在它把“置位”“复位”“保持”这三个动作讲得明明白白为你理解后面所有触发器打下基础。3.2 D触发器最常用的数据暂存器D触发器比RS简单只有一个数据输入D。时钟边沿到来时Q就变成D的值边沿之外Q完全保持。功能一句话D是几时钟沿到来后Q就是几。因为简单直观D触发器成了工程中使用最多的一种触发器。经典芯片74HC74就是双D触发器上升沿触发还带异步置位和异步复位端。很多初学者会问D触发器和寄存器有什么区别其实寄存器就是把多个D触发器并排放在一起共享同一个时钟和复位信号每一位用一个D触发器保存。一个8位寄存器内部就是8个D触发器。你以后写FPGA代码时一个always (posedge clk)块里定义的寄存器变量综合出来就是一堆D触发器原理完全一致。D触发器还有一个非常巧妙的接法把/Q反馈到D输入端。假设当前Q0那么/Q1D1下一个时钟沿到来后Q变成1这时候/Q变成0D也变成0再下一个时钟沿Q又变回0。所以每来一个时钟沿Q就翻转一次输出频率正好是输入时钟频率的一半。这就是大名鼎鼎的D触发器二分频任何计数器、分频器的基础。3.3 JK触发器把RS的禁用态变成翻转JK触发器是对RS触发器的改良。J类比置位端K类比复位端但它没有禁用态。J1、K0时钟沿到来后置位J0、K1时钟沿到来后复位J0、K0保持最妙的是J1、K1时钟沿到来后输出翻转。原来看起来最麻烦的“同时置位复位”被JK触发器变成了翻转功能。JK触发器的状态表一点也不难记JKQn100Qn保持010复位101置位11/Qn翻转因为JK触发器功能完备在状态机设计里特别灵活。设计一个状态转移不规律的序列检测器JK触发器配合卡诺图能很方便地写出驱动方程。以我个人的经验考试也罢、实际设计也罢JK触发器是“上限最高”的一种触发器掌握了它反过来再理解D触发器会简单很多。3.4 T触发器专职翻转计数器的最爱T触发器就是翻转触发器。T端为1时每个时钟沿翻转一次T端为0时保持输出不变。它的状态方程是Qn1 T⊕Qn简洁到不能再简洁。实现T触发器的标准方法把JK触发器的J、K短接在一起或者用D触发器加一个异或门做反馈。把T端固定接高电平就成了T触发器也就是前面提到的二分频器每个时钟沿必翻转。计数器之所以好设计正是因为T触发器天然适合“数到某个值就翻转”这种需求。你看看二进制加法计数器最低位是每个脉冲都翻转第二位是第一位翻转的下降沿触发第三位是第二位翻转的下降沿触发——全是一连串T触发器在干活。4. 从触发器到计数器把“记忆”变成“数数”4.1 一位计数器就是二分频理解了D触发器二分频你已经拥有一位二进制计数器。每来一个时钟脉冲Q翻转一次Q的波形就是输入时钟的二分之一频率。它能记录两个状态0和1。要数更多数字就把多个触发器级联起来。最简单的级联方式Q0的翻转输出接到后一级触发器的时钟端。Q0每翻转一次Q0的下降沿驱动Q1翻转一次这样一级级接下去就构成了一个二进制计数器。这种由前一级输出驱动后一级时钟的做法叫异步计数器也叫行波计数器。教科书上的波纹计数器讲的就是它。4.2 从二进制到十进制反馈清零纯二进制计数器从0数到15一共16个状态可人类最习惯的是十进制。一个十进制计数器需要在4位二进制的基础上从0000到1001一共10个状态到了9就得想办法回到0。工程上的标准做法是反馈清零当电路检测到计数到1001也就是9时让所有触发器复位。市场上有现成的十进制计数器芯片比如74HC390内部已经做好了模10逻辑你接好电源、时钟和使能它自己就会0到9循环输出。74HC161这种4位二进制计数器则可以通过预置端和进位输出来搭出任意模数的计数器灵活得多。搭计数器的过程其实就是训练你“把触发器按规则连起来”的能力。见得多了你会发现所谓数字电子里的各种计数器本质上就是触发器加一点反馈逻辑。4.3 同步计数和异步计数高速场合怎么选异步计数器结构简单但有一个明显的毛病每个触发器的时钟不是同时到达的。前一级翻转要经过自己的传输延迟才能带动后一级翻转。所以整个电路状态切换的时候会有短暂的时间窗口输出会出现不是目标状态也不是初始状态的中间值这就是毛刺。毛刺这个词你在书本上看到可能没什么感觉真接上数码管很可能有奇效。高速时钟下异步计数器的输出毛刺会让后级译码器误动作数码管显示乱跳。同步计数器则把同一个时钟接到所有触发器大家同时采样只是靠每个触发器自己的J、K输入决定翻不翻状态切换的一致性就好得多。现代稍微跑得快一点的设计一律用同步计数器异步计数器只用在低速、简单的场合。这也是考试和面试的高频考点同样实现计数功能为什么同步方案在高速下更可靠答案就在毛刺和状态切换的一致性上。5. 实战串联用触发器思路看懂数字时钟的完整链路5.1 1Hz秒脉冲是怎么来的数字时钟说白了就是数秒、数分、数时第一步必须有一个精准的1Hz脉冲。最常见的方案是拿32.768kHz晶振加一个分频链先用CD4060这种14级二进制分频器把它分到2Hz再经过一个D触发器二分频变成1Hz。这里D触发器二分频的用武之地非常直观。很多人会问晶振频率为什么选32.768kHz不选个整数因为2的15次方正好等于32768用二进制分频器一路二分到底就能得到精确到1Hz的脉冲。你不需要任何复杂的数学运算纯数字分频就能实现高精度的定时这也是数字时钟、电子表几十年经久不衰的方案。5.2 模60和模24分频链背后的计数器设计有了1Hz脉冲后面就是纯计数器串联。每来一个秒脉冲秒计数器加1秒计数器数满60个向分计数器进一位分计数器也是数满60向时计数器进一位时计数器数到24一天结束归零。因此一个完整的数字时钟数字电路方案需要两个模60计数器和一个模24计数器。模60计数器怎么做用两个十进制计数器串联就行了低位做0到9循环高位做0到5循环再加点反馈进位逻辑。模24计数器则是小时位0到23循环。你如果把这一层想明白了就会意识到所谓数字时钟这个大项目拆开看就是“分频器 三层计数器 译码显示”每层都是触发器在按照既定规则同步翻转。这个认知的提升很关键它会把“时序逻辑很难”的畏惧感变成“哦原来就是分模块搭积木”的工程思维。以后不管你是用74系列芯片搭还是用FPGA写Verilog设计思路一脉相承。5.3 显示驱动、复位和校时细节决定成败计数器输出的4位BCD码通常要经过译码器才能驱动数码管。74LS47对应共阳极数码管74HC4511对应共阴极数码管选用时一定看清楚数码管是共阴还是共阳接错了一通电数码管不是全亮就是全灭新手很容易栽在这个地方。校时电路也是数字时钟必做的功能。按键切换“时钟调整”“分钟调整”“秒清零”然后用一路手动脉冲去手动“加1”。这里有一个经典坑按键是机械触点按下和松开的瞬间会产生抖动前后持续几毫秒到几十毫秒如果不做消抖一次按键会被计数器当成好几次脉冲时间数字乱跳。解决办法是用RC低通滤波加施密特触发器或者用触发器做延时消抖。复位信号也是一样上电瞬间的毛刺、校时操作引入的干扰都可能让计数器状态错乱最好做一次统一的上电复位用一个RC延时电路给计数器异步复位端一个可靠的复位脉冲。提示搭数字时钟的时候先把秒脉冲调准再搭秒计数器每调通一级再接下一级。分段调试能帮你快速定位问题比全部搭完再查错高效得多。6. 学触发器和时序逻辑最容易踩的五个坑6.1 不在乎建立保持时间结果被亚稳态折磨这是实际调试中最隐蔽的坑。你的系统内部触发器都用同一个时钟老老实实满足时序约束但外部输入信号比如按键、外部设备发来的脉冲和你的全局时钟是完全异步的它落在时钟边沿附近哪一刻都有可能。一旦采样时刻正好撞上输入信号翻转触发器就进入亚稳态输出不像0也不像1还可能在恢复过程中来回抖动。处理手段是异步信号同步化外部信号进来之后先经过两级触发器打两拍让亚稳态在第一级触发器里逐步恢复第二级触发器采到的基本就是稳定值。这个“打两拍”的做法在FPGA和异步接口设计中是基本功初学数字电子时就该有这个意识。6.2 只背真值表不读时序图真值表告诉你“什么输入对应什么输出”但没告诉你信号在时间轴上的先后顺序和相对关系。实际调试时出问题靠真值表往往定位不到原因得看时序图。初学阶段建议自己动手画波形。就拿D触发器画输入时钟、D端信号、Q端信号标出上升沿的位置看Q是如何在时钟沿之后才更新的。画不顺说明理解还有缺口画顺了再去看JK触发器、计数器的波形图会轻松很多。示波器观察时也要刻意把时钟通道和输出通道接上去对比形成看时序图的直觉。6.3 复位信号处理不当电路一上电就乱套触发器和计数器芯片的复位端分两种异步复位和同步复位。异步复位是复位信号一到立刻清零不等时钟同步复位是复位信号来了但要等到下一个时钟沿才生效。两者各有用途混用容易出问题。尤其要注意异步复位信号撤销的时刻。复位信号变无效的一瞬间如果刚好有毛刺或者电压处于中间电平触发器就可能进入亚稳态。处理办法是让复位信号经过一个同步器再进系统或者保证复位信号是干净陡峭的沿。我自己用74HC390搭计数器时清零信号带了一点毛刺计数器就不按套路走排查了好久才发现是复位信号不干净。6.4 不注意输出驱动能力电平被拉垮时序电路的输出负载能力没你想的那么强。LED指示灯几十毫安的电流直接用触发器输出脚去驱动会把输出高电平拉低到不满足后级逻辑阈值的程度后级电路误判。继电器、蜂鸣器就更不用说了。正确做法是加缓冲器、三极管或者专用驱动芯片。手册里通常会给出输出高低电平的电流参数IOL、IOH接负载前先算一算总电流超过规格就要加驱动。这一点虽然是常识但我见过不少新手栽在通电调试这一步明明逻辑设计没问题就是带不动。6.5 不肯动手只想靠背题过关这是最大的坑可能没有之一。数字电子这门课触发器章节尤其需要动手验证。你可以在面包板上用74HC74、74LS112这些小芯片搭电路亲手测一遍真值表也可以装个仿真软件把D触发器二分频接出来看看波形。我建议的做法是每学一种触发器就做一个最小实验把它跑通。比如搭一个D触发器二分频输入1kHz方波示波器看输出是不是500Hz方波。这个实验成本极低、成就感极高而且会让你对“边沿触发”产生最直观的肌肉记忆。等搭数字时钟的时候你会感谢当初在面包板上反复折腾的自己。最后说一点个人感受。我碰到太多人到了时序逻辑就心虚总觉得自己逻辑思维不行、数学基础不好。其实时序逻辑反而比组合逻辑更贴近人的思维因为它天然带着“历史”“状态”“节奏”这些概念很像我们日常记账、排队、组织活动。你只要把触发器这个最小的记忆单元吃透把“双稳态”“边沿触发”“建立保持时间”这三个底层概念理解到位后面计数器、寄存器、状态机其实都是一个套路给触发器接上不同的反馈和组合逻辑让它按照你定的规则一步步走。真到了自己动手撸一个数字时钟、跑一段FPGA代码的时候你会回过来发现时序逻辑电路确实不难难的是从来没有认真理解过触发器。