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