触发器
复习
- 运算器总装:把运算部件组装成一个能算加减乘除的运算器
- 让电路记住一个比特:用交叉耦合的反馈做出能保存一个比特的锁存器
- 给电路一个共同节拍:用时钟统一各部件交接数据的时机
TL;DR
- 触发器是一种“只在时钟边沿更新”的一位记忆单元
- 它由两级锁存器(主从结构)串联而成,两级用相反相位的时钟控制
- 边沿之间,D 怎么变,Q 都不动;只有边沿那一刻才把 D 搬进 Q
- 触发器让同步电路“一拍一个动作”成为可能,是寄存器与 CPU 的基础
正文
上一章我们拿到了时钟,更早已经造出了锁存器。可真把两者配到一起,会发现一个尴尬:锁存器“开门”的是一整段时间,而时钟的边沿只是一个瞬间。 两者根本对不上。
锁存器在使能为 1 的整段时间里都是透明的——D 一变,Q 就跟着变。时钟明明给了我们“大家统一交接”的时刻,锁存器却根本不听“时刻”,它只听“电平”。所以我们缺的,是一个全新的记忆单元:平时关着门,只在时钟边沿那一瞬间开门,把门口的 D 拉进来,然后立刻关上。
这个部件,就是触发器(flip-flop)。
为什么不能直接拿锁存器顶替
先看一把锁存器的脾气:
E = 1:透明,Q 跟随 DE = 0:保持,Q 不动
那么,直接把时钟接到 E 上会怎样?CLK = 1 的半个周期里,锁存器一直透明,D 在这段时间里的任何变化都会一路传到 Q。我们想躲开的“整段时间都开放”,原封不动地又回来了。
问题的根子在于:锁存器是电平敏感的——它看的是“使能是高还是低”;而我们想要的是边沿敏感——只看“时钟有没有跳变”这一瞬间。电平敏感和边沿敏感,是两种截然不同的脾气,单靠一个锁存器,改不出来。
思考题 1
如果只是把时钟接到 D 锁存器的使能端,能得到“只在边沿更新”的效果吗?为什么?
一个锁存器做不到,那就用两个
回头想想:锁存器之所以“透明”,是因为在使能期间,它一直把输入放行到输出。那么换一个思路——在它放行的时候,把后面死死挡住;等它挡住的时候,再把后面放开。 从外面看,是不是就只剩下“交接的那一瞬间”了?
为了做到“轮流开合”,我们把两个锁存器一前一后串起来,并用相反相位的时钟分别控制它们:
D ──> [ 主锁存器 ] ──> [ 从锁存器 ] ──> Q
使能:时钟取反 使能:时钟
- 主锁存器:时钟为 0 时透明(跟随 D),为 1 时保持
- 从锁存器:时钟为 1 时透明,为 0 时保持
注意两者的使能正好相反:一个开门时,另一个必定关门。 这样串起来的两级,整体上就不再是“电平敏感”的了。
跟着时钟走一遍
把时钟从低到高再走一圈,看看 Q 到底在什么时候变:
| 阶段 | 主锁存器 | 从锁存器 | 结果 |
|---|---|---|---|
CLK = 0 | 透明(悄悄跟随 D) | 保持 | Q 不动 |
CLK 上升沿 | 转为保持 | 转为透明 | 主把边沿前的 D 冻结下来交给从,Q 更新 |
CLK = 1 | 保持 | 透明 | Q 保持,主不再看 D |
CLK 下降沿 | 转为透明 | 转为保持 | Q 冻结,主重新开始跟随 D |
看第一行:CLK = 0 时,从锁存器关着门,所以 Q 不动;与此同时,主锁存器正偷偷跟着 D。到了上升沿,主锁存器“啪”地一下闭上——它把刚刚(边沿前一刻)D 的值锁住,而从锁存器这时打开,把这个值送到 Q。于是 Q 只在上升沿更新,且更新的正是边沿前站稳的那个 D。
这正好接上上一章的结论:D 必须在边沿前稳定一小段时间(建立时间),再在边沿后稳定一小段时间(保持时间)。 主锁存器锁住的,就是这个早已站稳的 D;如果 D 恰好在边沿附近跳变,主锁存器锁到的就是“没站稳”的值,结果便不可靠。
一句话概括:主锁存器负责在边沿“拍照”,从锁存器负责把这张照片一直举在 Q 上。 这里并没有发明新的记忆原理,反馈依旧负责“记住”;两级反相开合,只是把“开门的时间”从一整段,收窄成了一个点。
思考题 2
主从结构里,两级锁存器为什么要用相反相位的时钟?如果两级用同一个时钟,会怎样?
它和锁存器差在哪里
| 锁存器 | 触发器 | |
|---|---|---|
| 敏感对象 | 电平 | 边沿 |
| 使能期间 | 输入一变,输出跟着变 | 与输入无关 |
| 边沿之间 | 输出可能被输入带动 | 输出纹丝不动 |
| 一句话 | “门一直开着” | “只按一次快门” |
触发器可以想成一台相机:D 是镜头前不断变化的景物,时钟上升沿是快门。Q 保存的,是按下快门那一刻的画面,而不是整段过程。快门之外,景物怎么变都无所谓。
看一个具体例子(上升沿采样):
| 上升沿 | 采样时 D | 采样后 Q |
|---|---|---|
| 第 1 次 | 1 | 1 |
| 第 2 次 | 1 | 1 |
| 第 3 次 | 0 | 0 |
第 1 次与第 2 次之间,D 即使来回变化,Q 也一直稳稳停在 1。这正是触发器与锁存器最本质的差别。
为什么非要边沿敏感
到这一步,值得停下来想一想:多花一级锁存器,换来“不透明”,到底值不值?
设想我们要做多步计算。如果用的是锁存器:在一个周期内,信号可能从第一级穿透到第二级、第三级……半拍之间,一个结果还没定,后面已经被它带着变了,我们根本说不清“这一拍算出来的到底是什么”。这叫穿透(race-through),是同步电路的大忌。
换成触发器,一切就清楚了:
- 周期内:组合逻辑慢慢算,触发器一律关着门,谁也不许动
- 边沿一到:所有触发器同时开门,把各自算好的结果一起收下,然后立刻关门
“算”发生在周期里,“交”发生在边沿上。 时间被整齐地切成一拍一拍,每一步都踩在点子上,这正是时钟想要的效果。而触发器,就是把时钟的意图真正落实下去的那个部件。没有触发器,时钟只是一个滴答作响的节拍器,指挥不动任何人。
换个角度看,触发器其实做了一件很了不起的事:它把“连续流逝的时间”,变成了“离散的步骤”。 有了它,机器才能说“第一拍做这个、第二拍做那个”。
思考题 3
为什么边沿触发比“整段时间都开放”的锁存方式更容易组织多步计算?
触发器不止一种
按功能分,触发器还有 JK、T、SR 等多种;但它们的共同点,都是“在边沿更新”。其中 D 触发器只需要一根数据线,用起来最省事,也最常用。本指南之后提到的触发器,一律默认为 D 触发器。
一只触发器,一个比特
触发器只记一个比特。这听起来很少,但已经足够当积木了:要保存一个 8 位数,把 8 只触发器并排放好、共用一个时钟就行。 这,正是下一章要做的事。
小结
知识点
- 触发器是“边沿敏感”的一位记忆单元
- 主从结构:两级锁存器加相反相位的时钟
- 上升沿采样,边沿之间保持
- 触发器让同步电路“一拍一个动作”
参考资料
- Wikipedia(zh):触发器:各类触发器的结构与工作方式
- Wikipedia(zh):时钟信号:同步电路中统一节拍的来源
思考题答案(仅供参考)
思考题 1
不能。锁存器是电平敏感的:把时钟接到使能端后,CLK = 1 的整个半周期它都透明,D 的变化照样传到 Q,“边沿那一刻”对它没有意义。要得到边沿敏感,必须在结构上改变(例如下一节的主从两级)。
思考题 2
如果两级用同一个时钟,它们会同时透明或同时保持:同时透明时,D 直接穿透两级到达 Q,等于一个“加长的锁存器”,边沿敏感无从谈起;同时保持时,值又传不下去。只有让两级反相,才能做到“一级开门时另一级关门”,把交接压缩到边沿那么短。
思考题 3
因为多步计算要求“这一步的结果定下来之后,才进行下一步”。边沿触发把每一拍的交接固定在同一个时刻,级与级之间不会在同一拍里互相穿透,先后关系明确;锁存器则可能在半拍内把变化一级级传下去,几步计算搅在一起,无法可靠地分步。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪