Appearance
锁存器与触发器:如何"记住"一位
概念
上一篇的 ALU 算得再快,也有一个致命缺陷:算完就忘。加法的进位链一断电就消失,"上一次算出来是多少"它完全记不住。
如何让电路"记住"一位? 答案只有四个字:引入反馈。
回忆上一篇给的判据:
**锁存器(latch)与触发器(flip-flop)**就是"最小可用的记忆单元"——它们内部只有两个反相器首尾相接,却能稳定地把一个比特存住。
| 锁存器(latch) | 触发器(flip-flop) | |
|---|---|---|
| 敏感方式 | 电平敏感( | 边沿敏感(只在时钟沿采样) |
| 何时能变 | 使能有效整段时间内都可能变 | 只在时钟沿那一瞬变 |
| 教科书外的叫法 | 门控锁存器、透明锁存器 | 主从触发器、边沿触发器 |
| 抗干扰 | 差(会"透传"毛刺) | 好(沿前后数据无关) |
一句话:锁存器 = 门开着的房间,谁都能进;触发器 = 只在时钟敲响的那一瞬开门。这一篇讲的就是"从锁存器到触发器"这一步进化——为什么必须有触发器。
本层(L1 电路)在这里回答了上一层(L2 组成原理)最根本的问题:寄存器、PC、Cache 的状态位、标志位……这些"记得住"的东西,到底靠什么电路实现。
原理
一、双稳态:两个反相器就够了
把两个反相器首尾相接(NOR/NOT 均可,这里用最形象的一对反相器):
┌───────┐ ┌───────┐
┌───→│ NOT │───→ Q ────→│ NOT │───┐
│ └───────┘ └───────┘ │
│ │
└─────────────── Q̄ ←──────────────────┘这个电路有两个稳定的平衡状态:
| 状态 | Q | 含义 | |
|---|---|---|---|
| 状态 A | 1 | 0 | 存 "1" |
| 状态 B | 0 | 1 | 存 "0" |
为什么叫"双稳态"? 因为它要么在 A,要么在 B,不会停在中间。
- 如果 Q 被瞬间干扰往上抬一点 → 反相器把它放大、再放大 → 自动冲到 1(A 态)
- 如果被往下压一点 → 自动塌到 0(B 态)
"自动放大"正是记忆的本质:小扰动被正反馈放大到两个极端之一,从而"锁住"。这也是为什么亚稳态(第 16 篇)如此可怕——它是"卡在中间既不像 0 也不像 1"的非法状态。
电压
↑
1├──────●━━━━━ A 态(稳定)
│ ↑ ↑
│ 正反馈把状态往外推
0.5├──────┴────┴── 不稳定平衡点(亚稳态,任何扰动都会离开)
│ ↓ ↓
0├──────●━━━━━ B 态(稳定)
└──────────────→ 状态二、SR 锁存器:给双稳态装上"控制门"
光有双稳态没用——没法往里面写值。给它加两个"推手":
NOR 版(高有效)
┌───────┐
R ──→│ NOR │───→ Q ──┐ Q = ¬(R + Q̄)
└───┬───┘ │
↑ │
└─────────────┼── Q̄
┌───┴───┐ │
S ──→│ NOR │←────────┘ Q̄ = ¬(S + Q)
└───────┘接线要点(最容易画反):
驱动的是输出 的那个门, 驱动输出 的门。 直觉:要把 置 1,先得让 变 0;而 NOR 门"见 1 出 0",所以 先把 拉成 0, 才被迫变成 1。
功能表:
| 说明 | ||||
|---|---|---|---|---|
| 0 | 0 | 保持(记住旧值) | ||
| 1 | 0 | 1 | 0 | 置 1(Set) |
| 0 | 1 | 0 | 1 | 置 0(Reset) |
| 1 | 1 | 0 | 0 | 禁态 ⚠️ |
为什么
NAND 版(低有效)
把 NOR 换成 NAND,输入变低有效(记作
| 说明 | |||
|---|---|---|---|
| 1 | 1 | 保持 | |
| 0 | 1 | 1 | 置 1 |
| 1 | 0 | 0 | 置 0 |
| 0 | 0 | 1, 1 | 禁态(两个输出都是 1) |
两种版本的禁态表现形式相反(NOR 版是"都是 0",NAND 版是"都是 1"),但本质一样:两个输出不再互补。做题先看清是高有效还是低有效。
特性方程
验证
三、门控 SR 锁存器:加上"使能"
裸 SR 锁存器一直在听输入,实际系统需要一个"什么时候才准改"的闸门:
┌──────┐
S ──┬──→[AND]──────│ SR │
│ ↑ │ 锁存器│
EN ─┼─────┤ └──────┘
│ ↓
R ──┴──→[AND]功能表:
| 说明 | ||||
|---|---|---|---|---|
| 0 | × | × | 保持 | |
| 1 | 0 | 0 | 保持 | |
| 1 | 1 | 0 | 1 | 置 1 |
| 1 | 0 | 1 | 0 | 置 0 |
| 1 | 1 | 1 | 禁态 | 仍存在 ⚠️ |
禁态还没解决。而且
四、D 锁存器:从根上消灭禁态
思路:既然禁态来自"
┌──────┐
D ──┬──→[AND]───────│ 门控 │──→ Q
│ ┌─────│ SR │
└──→[NOT]┴──→[AND] └──→ Q̄
│ ↑
EN ───────┴────────┘功能表(只有两行,干净):
| 状态 | |||
|---|---|---|---|
| 1 | 0 | 0 | 跟随(透明) |
| 1 | 1 | 1 | 跟随(透明) |
| 0 | × | 保持 |
特性方程:
"透明"的直观理解:
EN ──┐ ┌────────────────┐
└────┘ └──────
↑ EN=1 期间"门开着",D 怎么变 Q 就怎么变
D ────┐ ┌──┐ ┌─────────
└──┘ └──┘
Q ────┐ ┌──┐ ┌───────── ← 与 D 完全重合(透明!)
└──┘ └──┘D 锁存器的缺陷:
五、主从触发器:把"透明"切成两半
思路:用两个锁存器串联,让它们的使能反相,任何时刻只有一个"开门":
┌──────────┐ ┌──────────┐
D ───→ │ 主锁存器 │───┬───→│ 从锁存器 │───→ Q
│ (EN=CP) │ │ │ (EN=CP̄) │
└──────────┘ │ └──────────┘
│
CP ───┬────────────────┘
└──→[NOT]──→ 从锁存器的 EN工作过程(以"高电平采入、低电平输出"的主从 D 触发器为例):
| 阶段 | 主锁存器 | 从锁存器 | ||
|---|---|---|---|---|
| ① | 1 | 透明,跟随 | 保持 | 不变 |
| ② | 0 | 保持(锁住 | 透明,把主的值送出去 | 更新为采到的 |
关键:
只在 下降沿更新一次, 期间不管 怎么折腾, 都稳如泰山。"透明窗口"被切成两半,毛刺进不来了。
六、空翻与"一次翻转":主从结构的残留毛病
主从结构解决了 D 触发器的透明问题,但对 JK 触发器留下了个尾巴。
主从 JK 触发器:主锁存器的
理想: CP=1 期间 Q 稳定,只在下降沿翻一次
空翻: CP=1 期间 Q 抖一下 → 主锁存器又翻 → 到下降沿多翻了 ⚠️根治办法:边沿触发。用两个串联的锁存器 + 时钟延迟(或电容/传输门结构)做成真正的边沿触发器:
| 触发方式 | 采样时刻 | 抗空翻 | 典型器件 |
|---|---|---|---|
| 电平触发(锁存器) | 使能期间一直跟随 | ✗ | 74LS373 |
| 主从触发 | 时钟沿(但内部有"一次翻转"隐患) | △ | 74LS112(主从 JK) |
| 边沿触发 | 仅时钟跳变沿那一瞬 | ✓ | 74LS74(上升沿 D) |
边沿 D 触发器的特性方程,简单到极致:
"仅在时钟有效沿"这半句才是精髓——它把"什么时候可以变"从数据通路上剥离出去,交给了时钟。同步数字系统的全部秩序,都建立在这一句上。
七、四种触发器的全家福
| 类型 | 特性方程 | 约束 | 口诀 |
|---|---|---|---|
| SR | 置位优先,但会打架 | ||
| JK | 无 | ||
| D | 无 | 直通,最听话 | |
| T | 无 |
读 JK 方程:
互推关系(考试常考):
把 JK 的 J、K 接到一起当 T 用: T 触发器 = JK(J = K = T)
把 JK 加一个反相器: D 触发器 = JK(J = D, K = D̄)
验证:J=D, K=D̄ 代入 Q* = JQ̄ + K̄Q = DQ̄ + DQ = D(Q̄+Q) = D ✓八、激励表:从"要变到哪"反推"该给什么输入"
设计时序电路时,已知的是"现在是什么、下一步要变成什么",要反推触发器输入。这就是激励表(excitation table):
| 现态 | SR 的 | JK 的 | D 的 | T 的 |
|---|---|---|---|---|
| 0 | 0 | |||
| 1 | 1 | |||
| 0 | 1 | |||
| 1 | 0 |
记忆法:
表示"随意(don't care)",用来化简电路。D 触发器没有 ——因为它只有一个输入,必须给确定值。这也是"D 触发器最省事、JK 最灵活"的来源。
九、建立时间与保持时间:从哪来?
边沿触发虽然好用,但它对数据提出了要求:在时钟沿附近,
┌──────────────────┐
时钟 ─────┘ └─────
↑
│←tsu→│
│ │←th→│
D ───────┴─────┴────┴─────
▓▓▓▓▓▓▓▓▓ ← 这段区间内 D 必须稳定("禁止翻转窗口")| 参数 | 含义 | 违反后果 |
|---|---|---|
| 时钟沿之前 | 新值来不及传进主锁存器 | |
| 时钟沿之后 | 旧值被过早冲掉 | |
| 时钟沿到 | 影响下一级时序 |
物理来源:触发器内部的门有延迟,
这三个参数是下一篇(
16-timing.md)的主角:它们决定了整个同步电路的最高时钟频率。
示例
例 1:NOR SR 锁存器的全部输入组合(逐行验证)
用"求稳定解"的方式,把所有 4 组
输入的最终状态全部算出。
完整过程(两个 NOR 门:
情形 1:
试探
试探
结论:
情形 2:
先看输出
再看
回代验算:
情形 3:
情形 4:
两个输出都是 0,违反互补前提 → 禁态。
撤销时的竞争:
| 时序 | ||
|---|---|---|
| 撤销瞬间 | 0 | 0 |
| 0 | ||
| 再看 | 1 |
结果
验证表汇总:
| 结论 | ||||
|---|---|---|---|---|
| 0 | 0 | 保持(双稳态) | ||
| 1 | 0 | 1 | 0 | 置 1 ✓ |
| 0 | 1 | 0 | 1 | 置 0 ✓ |
| 1 | 1 | 0 | 0 | 禁态,撤销后结果随机 |
例 2:D 锁存器的"透明"会造成什么(波形对比)
设
线上带一个窄毛刺,比较锁存器与边沿触发器的输出。
时钟/使能 EN ─┐ ┌──────────┐ ┌────
└────────┘ └────────┘
数据 D ────┐ ┌┐ ┌────────────────
└───┘└───┘ ↑ 毛刺
D 锁存器 Q ────┐ ┌┐ ┌──────────────── ← 毛刺原样传出 ⚠️
(EN 高时透明)└───┘└───┘
↑时间轴横向展开
D 触发器 Q ────┐ ┌──────────────── ← 只在时钟沿更新,毛刺被忽略 ✓
(边沿采样) └────────┘| 器件 | 毛刺出现时刻 | 结果 |
|---|---|---|
| D 锁存器 | 使能有效期间 | 被采入,状态出错 |
| 边沿 D 触发器 | 非时钟沿 | 被忽略,状态安全 |
| 边沿 D 触发器 | 恰在禁止窗口内 | 亚稳态(最危险) |
这就是"同步设计只用边沿触发器"的根本原因:把"何时可以变"从数据通路剥离,交给时钟,毛刺自然被过滤掉(承接上一篇"同步电路靠时序余量免疫冒险"的结论)。
例 3:主从 D 触发器为什么能躲开透明(分阶段推导)
从 0 升到 1, 在 期间变化三次( ),求最终 。
第一步:
第二步:
第三步:
第四步:结论汇总。
| 时刻 | 主锁存器 | 从锁存器 | ||
|---|---|---|---|---|
| ↑ | 开门, | 关门 | 保持 | |
| 1 | 跟随 | 关门 | 保持 | |
| 1 | 跟到最后一次(0) | 关门 | 保持 | |
| ↓ | 关门,锁 0 | 开门,送出 0 | 0 ✓ |
关键洞察:
期间的多次变化,只留下最后一次。 这叫"边沿采样"的效果。但注意——如果 恰在下降沿附近变化,主锁存器锁到的值就可能不确定,这正是 / 要解决的问题。
例 4:JK → D 与 JK → T 的等价性验证(逐项覆盖)
验证
时,JK 触发器等价于 D 触发器。
完整验证(对
| 期望 | |||||||
|---|---|---|---|---|---|---|---|
| 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 ✓ |
| 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 ✓ |
| 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 ✓ |
| 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 ✓ |
代数验证更干脆:
同理验证
(这正是"异或"的定义式
结论:JK 是"万能触发器"——加两根线就能变成 D 或 T。这也是实际芯片里 JK 与 D 都长盛不衰的原因。
例 5:建立/保持时间违例的时序推演
某上升沿 D 触发器,
, 。时钟周期 。 在时钟上升沿前 才开始变化,问是否违例。
第一步:确定禁止窗口。 禁止窗口 = 沿前
第二步:
第三步:判定 → 违反建立时间。
第四步:后果推演。
| 结果 | 概率 | 表现 |
|---|---|---|
| 采到新值 | 较大 | 功能正常但"碰运气" |
| 采到旧值 | 较小 | 结果错一拍 |
| 亚稳态 | 不可忽略 | 输出在 0/1 之间摇摆,下游电路全部采样到随机值 |
第五步:修正方案。
这条不等式就是下一篇(时序分析)的核心公式的雏形。
例 6:用程序复算
#include <stdio.h>
/* ---- NOR SR 锁存器:迭代求稳定解 ---- */
static int nor(int a, int b) { return !(a || b); }
static void sr_latch_nor(int S, int R, int q0, int qb0,
int *q, int *qb, int *stable) {
int Q = q0, Qb = qb0;
for (int it = 0; it < 20; it++) {
int nq = nor(R, Qb); /* Q = NOR(R, Qb) */
int nqb = nor(S, Q); /* Qb = NOR(S, Q) */
if (nq == Q && nqb == Qb) { *stable = 1; *q = Q; *qb = Qb; return; }
Q = nq; Qb = nqb;
}
*stable = (Q + Qb == 1);
*q = Q; *qb = Qb;
}
int main(void) {
printf("--- 例1 NOR SR 锁存器 ---\n");
int tbl[4][2] = {{0,0},{1,0},{0,1},{1,1}};
for (int k = 0; k < 4; k++) {
int S = tbl[k][0], R = tbl[k][1];
for (int q0 = 0; q0 <= 1; q0++) {
int q, qb, st;
sr_latch_nor(S, R, q0, !q0, &q, &qb, &st);
printf(" S=%d R=%d 初态 Q=%d -> Q=%d Qb=%d %s\n",
S, R, q0, q, qb, st ? "" : "(不互补=禁态)");
}
}
printf("\n--- 特性方程 Q* = S + ~R*Q 覆盖检查 ---\n");
int bad = 0;
for (int S = 0; S <= 1; S++) for (int R = 0; R <= 1; R++) for (int Q = 0; Q <= 1; Q++) {
if (S && R) continue; /* 约束 SR=0 */
int eq = S | ((!R) & Q);
int q, qb, st;
sr_latch_nor(S, R, Q, !Q, &q, &qb, &st);
if (!st || q != eq) { bad++; printf(" MISMATCH S=%d R=%d Q=%d\n", S, R, Q); }
}
printf(" %s\n", bad ? "FAIL" : "PASS(7 组合全部一致)");
printf("\n--- 例4 JK->D / JK->T 覆盖检查 ---\n");
bad = 0;
for (int D = 0; D <= 1; D++) for (int Q = 0; Q <= 1; Q++) {
int J = D, K = !D;
int qn = (J & !Q) | ((!K) & Q);
if (qn != D) { bad++; printf(" D-MISMATCH D=%d Q=%d\n", D, Q); }
}
for (int T = 0; T <= 1; T++) for (int Q = 0; Q <= 1; Q++) {
int qn = (T & !Q) | ((!T) & Q);
if (qn != (T ^ Q)) { bad++; printf(" T-MISMATCH T=%d Q=%d\n", T, Q); }
}
printf(" %s\n", bad ? "FAIL" : "PASS");
printf("\n--- 例5 建立/保持窗口 ---\n");
double tsu = 2.0, th = 1.0, T = 10.0, arrive = -1.0; /* 相对时钟沿 */
printf(" 禁止窗口 = [%.1f, +%.1f] ns ; D 变化于 %.1f ns -> %s\n",
-tsu, th, arrive,
(arrive > -tsu && arrive < th) ? "违例(违反建立时间)" : "合规");
printf(" 要求 D 到达 <= T - tsu = %.1f ns\n", T - tsu);
return 0;
}
c 本站为静态站,不提供在线运行;可复制到本地用 gcc / python 执行
预期输出:
--- 例1 NOR SR 锁存器 ---
S=0 R=0 初态 Q=0 -> Q=0 Qb=1
S=0 R=0 初态 Q=1 -> Q=1 Qb=0
S=1 R=0 初态 Q=0 -> Q=1 Qb=0
S=1 R=0 初态 Q=1 -> Q=1 Qb=0
S=0 R=1 初态 Q=0 -> Q=0 Qb=1
S=0 R=1 初态 Q=1 -> Q=0 Qb=1
S=1 R=1 初态 Q=0 -> Q=0 Qb=0 (不互补=禁态)
S=1 R=1 初态 Q=1 -> Q=0 Qb=0 (不互补=禁态)
--- 特性方程 Q* = S + ~R*Q 覆盖检查 ---
PASS(7 组合全部一致)
--- 例4 JK->D / JK->T 覆盖检查 ---
PASS
--- 例5 建立/保持窗口 ---
禁止窗口 = [-2.0, +1.0] ns ; D 变化于 -1.0 ns -> 违例(违反建立时间)
要求 D 到达 <= T - tsu = 8.0 ns# ============ 例1:NOR SR 锁存器 ============
def nor(a, b):
return 0 if (a or b) else 1
def sr_latch(S, R, q0=0, qb0=1):
Q, Qb = q0, qb0
for _ in range(20):
nQ, nQb = nor(R, Qb), nor(S, Q) # Q = NOR(R,Qb) ; Qb = NOR(S,Q)
if (nQ, nQb) == (Q, Qb):
return Q, Qb, True
Q, Qb = nQ, nQb
return Q, Qb, (Q + Qb == 1)
print("=== 例1 NOR SR 锁存器 ===")
for S, R in [(0, 0), (1, 0), (0, 1), (1, 1)]:
for q0 in (0, 1):
Q, Qb, ok = sr_latch(S, R, q0, 1 - q0)
tag = "" if ok else " <-- 不互补,禁态"
print(f" S={S} R={R} 初态Q={q0} -> Q={Q} Qb={Qb}{tag}")
print("\n=== 特性方程 Q* = S + ~R·Q 覆盖 ===")
bad = []
for S in (0, 1):
for R in (0, 1):
if S and R:
continue # 约束 SR = 0
for Q in (0, 1):
eq = S or ((not R) and Q)
Q2, _, ok = sr_latch(S, R, Q, 1 - Q)
if (not ok) or Q2 != int(eq):
bad.append((S, R, Q))
print(f" {'PASS' if not bad else 'FAIL ' + str(bad)} (7 组合)")
# ============ 特性方程全家福(穷举验证) ============
print("\n=== 四种触发器特性方程穷举 ===")
# JK
bad = []
for J in (0, 1):
for K in (0, 1):
for Q in (0, 1):
qn = int((J and not Q) or ((not K) and Q))
ref = {0: J, 1: (not K)}[Q] # Q=0 -> J ; Q=1 -> ~K
if qn != int(ref):
bad.append((J, K, Q))
print(f" JK : Q* = J·Q' + K'·Q {'PASS' if not bad else 'FAIL'}")
# D
bad = []
for D in (0, 1):
for Q in (0, 1):
if D != D:
bad.append((D, Q))
print(f" D : Q* = D {'PASS' if not bad else 'FAIL'}")
# T
bad = []
for T in (0, 1):
for Q in (0, 1):
qn = int((T and not Q) or ((not T) and Q))
if qn != (T ^ Q):
bad.append((T, Q))
print(f" T : Q* = T ⊕ Q {'PASS' if not bad else 'FAIL'}")
# ============ 例4:JK -> D / JK -> T ============
print("\n=== 例4 JK 变 D / 变 T ===")
bad = []
for D in (0, 1):
for Q in (0, 1):
J, K = D, 1 - D
qn = int((J and not Q) or ((not K) and Q))
if qn != D:
bad.append(("D", D, Q))
for T in (0, 1):
for Q in (0, 1):
J = K = T
qn = int((J and not Q) or ((not K) and Q))
if qn != (T ^ Q):
bad.append(("T", T, Q))
print(f" {'PASS' if not bad else 'FAIL ' + str(bad)}")
# ============ 激励表互查 ============
print("\n=== 激励表(由特性方程反解,穷举验证) ===")
def jk_next(J, K, Q):
return int((J and not Q) or ((not K) and Q))
def sr_next(S, R, Q):
return S or ((not R) and Q)
for q, qn in [(0, 0), (0, 1), (1, 0), (1, 1)]:
# SR
sr = [f"S={S},R={R}" for S in (0, 1) for R in (0, 1)
if not (S and R) and sr_next(S, R, q) == qn]
jk = [f"J={J},K={K}" for J in (0, 1) for K in (0, 1)
if jk_next(J, K, q) == qn]
print(f" {q}->{qn} SR: {sr}")
print(f" JK: {jk} D: D={qn} T: T={q ^ qn}")
# ============ 例5 建立/保持 ============
print("\n=== 例5 建立/保持窗口 ===")
tsu, th, T, arrive = 2.0, 1.0, 10.0, -1.0
viol = (-tsu < arrive < th)
print(f" 禁止窗口 [{-tsu:+.1f}, {th:+.1f}] ns, D 变化于 {arrive:+.1f} ns -> "
f"{'违例:违反建立时间' if viol else '合规'}")
print(f" 数据必须满足:到达时刻 <= T - tsu = {T - tsu:.1f} ns")
# ============ 时钟频率与禁止窗口占比(接下一篇) ============
print("\n=== 禁止窗口占比随频率变化(预告 16-timing) ===")
for f in (1e6, 10e6, 100e6):
Tn = 1 / f # 秒
ratio = (tsu + th) * 1e-9 / Tn * 100 # tsu/th 单位是 ns,需换算
print(f" f = {f/1e6:6.0f} MHz -> 周期 {Tn*1e9:7.2f} ns, "
f"禁止窗口({tsu+th:.0f} ns)占比 {ratio:5.2f}%")
print(" 占比随频率线性上升:频率越高,留给数据稳定的时间越少")
python 本站为静态站,不提供在线运行;可复制到本地用 gcc / python 执行
输出要点:
考点
考点
1. 必背特性方程与激励表
激励表见正文第八节,D 列没有
2. 锁存器 vs 触发器(判断/简答必考)
| 判据 | 锁存器 | 触发器 |
|---|---|---|
| 敏感方式 | 电平 | 边沿 |
| 输出何时可变 | 使能整段时间 | 仅时钟沿 |
| 抗毛刺 | 差(透明) | 好 |
| 器件 | 74LS373(D 锁存器) | 74LS74(上升沿 D)、74LS112(下降沿 JK) |
一句话:触发器 = 两级反相使能的锁存器,把"透明窗口"切成两半。
3. 三个"形状相同、本质不同"的坑
| 概念 | 现象 | 根因 | 解法 |
|---|---|---|---|
| 禁态 | 输入组合本身非法 | 加约束 | |
| 透明 | 使能期间 | 锁存器电平敏感 | 换边沿触发器 |
| 空翻 / 一次翻转 | 主从 JK 在一个时钟内翻多次 | 主锁存器在 | 用边沿触发 |
4. 高频陷阱
- NOR 版与 NAND 版的禁态表现形式相反。NOR 版禁态是"两输出都为 0"(高有效输入
);NAND 版是"两输出都为 1"(低有效输入 )。做题第一步先标极性。 - 禁态撤销后结果不确定,不是"保持原值"。它是竞态,由器件延迟差异决定,必须回避。
- "触发器"三个字不保证边沿触发。主从 JK(74LS112)是边沿触发的,但主从结构在主锁存器内部有"一次翻转"隐患;考试要看清楚说的是"主从"还是"边沿"。
- D 触发器只有一个
都没有的列——激励表里它必须给确定值,所以要额外一根反相器才能从 JK 转换过来。 - 建立时间在沿之前,保持时间在沿之后,别记反。禁止窗口 =
。沿 沿 与 的读法: 是"下一个时钟沿之后的态"(次态), 是现态。特性方程描述的是"沿到来时的跳变",不是"一直成立"。- 锁存器不是"没用":它在 CPU 里大量存在(如寄存器堆的透明写、锁存地址总线的 74LS373)。只是不能用来做同步状态。
5. 与后续章节的接口
- D 触发器是下一篇
circuit/14-register.md的积木: 个并联 = 寄存器。 - 特性方程 + 激励表是
circuit/15-fsm.md(状态机设计)的核心工具:由状态表反推触发器输入。 / / 是circuit/16-timing.md的全部素材,直接决定最高时钟频率。- 亚稳态在 L2 会以"跨时钟域同步器"的面目再次出现。
小结
- 记忆的本质是反馈:两个反相器首尾相接产生双稳态,小扰动被正反馈放大到两个极端之一——这就是"锁住一位"。
- SR 锁存器给双稳态装上控制门,但有禁态(
)和撤销后的竞态。 - 门控 SR → D 锁存器用"
与其反相"从根上消灭禁态,代价是透明:使能期间输入的任何变化(含毛刺)都会传到输出。 - 主从触发器用两个反相使能的锁存器把透明窗口切成两半,
只在时钟沿更新;但主从 JK 仍有**一次翻转(空翻)**隐患。 - 边沿触发器(74LS74)做到"只在沿的那一瞬采样",特性方程简到
——同步数字系统的全部秩序都建立在"仅在时钟有效沿"这半句上。 - 四种触发器(SR/JK/D/T)通过特性方程与激励表互相转换:JK 是万能的,加两根线就是 D 或 T。
/ / 来自触发器内部的门延迟。违反它们会导致亚稳态——输出卡在 0 与 1 之间,下游全部采样到随机值。这是下一篇的主角。
回到主线:现在我们有了"记住一位"的元件。但一位远远不够——CPU 要存 32 位 PC、32 位指令、几十个通用寄存器、成千上万个 Cache 行。
把
下一篇:寄存器、计数器与移位寄存器
评论(0)
当前浏览器不允许本地存储,评论无法保存。
还没有评论,来说两句。