そもそもラッチとは?
- ラッチ = 1ビットの記憶回路
- 組み合わせ回路は「今の入力だけ」で出力が決まる(過去を覚えない)
- ラッチは 出力を入力にフィードバック することで「さっきの状態」を覚えられる
- 順序回路のいちばん基本的な構成要素
┌──────┐
入力 ─→│ 回路 │──→ 出力
└──┬───┘
↑ フィードバック(出力を入力に戻す)
───┘
- これがあるおかげでCPUは計算途中の値を保持したり、レジスタやメモリを実現できる
- 「覚える」という機能をデジタル回路で実現した最小単位
ゲート付きDラッチの回路図
flowchart TD subgraph "ゲート付きDラッチ (Gated D Latch)" INV["NOT"] AND1["AND1"] AND2["AND2"] N1["NOR1"] N2["NOR2"] end D["D"] --> AND2 D --> INV INV --> AND1 G["G (Enable)"] --> AND1 & AND2 AND1 --> N1 AND2 --> N2 Q["Q"] --> N2 Qb["Q'"] --> N1 N1 --> Q N2 --> Qb style INV fill:#ff9,stroke:#333 style AND1 fill:#9f9,stroke:#333 style AND2 fill:#9f9,stroke:#333 style N1 fill:#bbf,stroke:#333 style N2 fill:#bbf,stroke:#333
動作のイメージ
- G=0 → ANDが閉じてる → 何も変わらない(保持モード)
- G=1 → ANDが開く → Dの値がNOR側に届く(透過モード)
- 透過モード中にDが変わるとQも変わってしまう → これが「信頼性の低さ」の原因
ゲート付きDラッチ
透過型ラッチとして扱える
入力動作を格納するレジスタとして動作する
| G | D | Q | Q+ |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 |
信頼性の低いDラッチ
QとDをつなぐとクロックによってQが発振することになる
発振すると値が保持できなくなってしまう
→エッジトリガー型とマスター・スレーブ型のフリップフロップで対策する
エッジトリガー型フリップフロップ (D-FF)
なんでQ+ = Dで意味があるのか?
- エッジトリガD-FFは クロックエッジの瞬間だけDを取り込む
- それ以外の時間は Dが何回変化しようがQは不動(完全にシャットアウト)
- 透過型ラッチはG=1の間ずっとDがQに通り抜ける → 信頼性が低い
ラッチ(G=1の間):
CLK ──┬──────────────────────
D ──┴─ 0 ── 1 ── 0 ── 1 ──
Q 0 1 0 1 ← Dの変化が全部Qに出ちゃう
エッジトリガD-FF(立ち上がりエッジ):
CLK ↑ ↑ ↑
D ── 0 ── 1 ── 0 ── 1 ── 0 ─
Q 0→1 変わらない ↑
次のエッジまでQは絶対に変わらない
なぜこれが同期回路の要になるのか
もし全部ラッチだったら:
- CLK=1の間にFF1の出力が変わると、その変化がそのままFF2に伝わる
- FF2も変わるとそれがFF3に… → レースコンディション(暴走)
エッジトリガなら:
- CLK ↑の瞬間に全FFが一斉にDを取り込む
- その後は次のCLK ↑まで各FFの出力は完全に固定
- その間に組み合わせ回路の結果を確定させられる
- 次のCLK ↑でまた全FFが一気に次の値を取り込む
→ これがあるから同期設計が成り立つ! 「エッジの瞬間だけ影響を受け、それ以外は外界を完全にシャットアウトする」のがD-FFの本質的な役割
イネーブル(CE)はオプション
- イネーブルがなくても「毎クロック更新するレジスタ」として十分役立つ
- カウンタやシフトレジスタはCEなしで動く
- CEは「更新したくないときもある」→ それ用の付加機能
- エッジトリガそのものに意味があって、CEはその上の機能
真理値表
| D | Q | Q+ |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
- 特性方程式:Q⁺ = D
- Qの現在値に一切関係なく、Dの値がそのまま次の状態になる
- これが「エッジの瞬間にDを取り込むだけ」という動作を正確に表している
透過型ラッチ vs エッジトリガD-FF
| 透過型Dラッチ | エッジトリガD-FF | |
|---|---|---|
| 取り込みタイミング | G=1の間ずっと | クロックエッジの瞬間だけ |
| Dの変化の影響 | G=1なら即座にQに反映 | 次のエッジまで完全に無視 |
| 同期回路での使いやすさ | ❌ レースしやすい(駆け抜け) | ✅ これが同期設計の根幹 |
タイミング図(エッジトリガ動作)
stateDiagram-v2 direction LR state "CLK↑ 待機" as wait state "立ち上がり検出" as edge state "Dを取り込み\nQ←D" as capture state "Qを保持\n(次の↑まで不動)" as hold [*] --> wait wait --> edge : CLKが0→1に変化 edge --> capture : エッジ検出! capture --> hold : Dの値をQに書き込み完了 hold --> wait : CLKが0に戻る or Dが変化しても無視 note right of wait : この間はDが何回変わっても<br/>Qは絶対に変わらない note right of edge : 🔺 この瞬間だけ<br/>Dの値を見る
または波形比較として:
sequenceDiagram participant CLK participant D participant Q Note over CLK,Q: === ラッチ(透過型)=== CLK-->>CLK: 1 (G=1の間ずっと) D-->>Q: 値が通り抜ける Note over Q: Dの変化に追従 Note over CLK,Q: === エッジトリガD-FF === CLK->>CLK: ↑ (立ち上がりの瞬間だけ!) D->>Q: この瞬間のDをQに書き込み Note over Q: その後は次の↑まで<br/>絶対に変わらない
- CLKが↑のときのDの値だけがQに反映される
- CLKが↑以外のときのDの変化はQに影響しない
- 透過型ラッチと違い、CLK=1の間にDが何回変わってもQは次のエッジまで固定
マスター・スレーブ型フリップフロップ Dフリップフロップ
構成
- 透過型Dラッチを2つ直列に繋いだもの
- マスターのG = CLK、スレーブのG = NOT CLK(クロックが反転)
- レベルセンシティブな部品だけで「エッジトリガもどき」を例外的に作り出している
flowchart LR subgraph "マスター・スレーブD-FF" subgraph "マスター (G=CLK)" ML["透過Dラッチ"] end subgraph "スレーブ (G=NOT CLK)" SL["透過Dラッチ"] end INV["NOT"] end D["D"] --> ML CLK["CLK"] --> ML CLK --> INV INV --> SL ML --> SL SL --> Q["Q"] style ML fill:#bbf,stroke:#333 style SL fill:#bbf,stroke:#333 style INV fill:#ff9,stroke:#333
動作(CLK=1 → CLK↓ → CLK=0 の順で追う)
CLK = 1 のとき
| G | 状態 | |
|---|---|---|
| マスター | 1 | 透過(Dを追いかける) |
| スレーブ | 0 | ラッチ(値を保持、Qは動かない) |
- Dが何回変化しても、外に見えるQは完全に静止
- 透過型ラッチの「G=1の間はDがQに透ける」性質が、スレーブでブロックされている
CLKが 1→0 になった瞬間(立ち下がりエッジ)🚀
CLKが落ちる──
マスター:G:1→0 → 「今のDの値」でラッチ(固まる!)
スレーブ:G:0→1 → 透過に切り替わる → マスターの値をQに映す
→ この瞬間だけQが更新される! → エッジトリガ動作が実現!
CLK = 0 のとき
| G | 状態 | |
|---|---|---|
| マスター | 0 | ラッチ(Dが変わっても無視) |
| スレーブ | 1 | 透過(マスターの値をQに出し続ける) |
- マスターがラッチしてるから、Dが暴れてもQは不動
- 次のCLK↑まではこの状態
CLKが 0→1 になった瞬間
マスター:G:0→1 → 透過に戻る → Dを追いかけ始める
スレーブ:G:1→0 → ラッチ → 今のQの値を保持
Qは変わらない。次のCLK↓でまた更新されるまで保持し続ける
なぜ「例外的にエッジ駆動」なのか
- 普通:レベルセンシティブな部品(ラッチ)を繋ぐと → レベルセンシティブな回路になる
- 例外:クロックを逆相にして2段カスケードすると → 全体がエッジトリガになる
- レベルセンシティブ(=信号のレベルで動作が決まる)なラッチだけで、**エッジ(変化の瞬間)**で動作するFFを「例外」的に作れる
レベルセンシティブ vs エッジトリガ おさらい
| レベルセンシティブ | エッジトリガ | |
|---|---|---|
| 反応するもの | 信号が1の間(レベル) | 信号が変わる瞬間(エッジ) |
| 代表例 | ラッチ(透過型Dラッチ) | フリップフロップ |
| 制御信号 | G(ゲート/イネーブル) | CLK(クロック) |
マスタースレーブの注意点(セットアップ/ホールドタイム)
- CLK↓の直前(セットアップタイム)と直後(ホールドタイム)はDの値を固定しないといけない
- この間にDが変わると、マスターが正しくラッチできず誤動作する
- 真のエッジトリガFFよりも制約が厳しい場合がある
ディレイとセットアップの和が最短のクロック周期
S-Rラッチ(再入門)
S-Rラッチはラッチの原点。NORゲート2つを十字フィードバックした、最もシンプルな記憶回路。
flowchart LR subgraph "NOR版 S-Rラッチ" S["S (Set)"] --> N1["NOR1"] R["R (Reset)"] --> N2["NOR2"] Q["Q"] --> N2 Qb["Q'"] --> N1 N1 --> Q N2 --> Qb end style N1 fill:#bbf,stroke:#333 style N2 fill:#bbf,stroke:#333
動作(たった4パターン)
| S | R | Q | Q’ | 動作 |
|---|---|---|---|---|
| 0 | 0 | 保持 | 保持 | 保持(前の値を覚え続ける) |
| 0 | 1 | 0 | 1 | リセット(Q=0) |
| 1 | 0 | 1 | 0 | セット(Q=1) |
| 1 | 1 | 0 | 0 | 禁止(NORだとQもQ’も0→矛盾、使えない) |
- S(Set)が1 → Qが1(セット!)
- R(Reset)が1 → Qが0(リセット!)
- 両方0 → 今のまま(記憶)
- 両方1 → 禁止
- 特性方程式:Q⁺ = S + R’Q
S-Rフリップフロップ(S-Rラッチのマスタースレーブ)
D-FFと同じマスタースレーブ構造。中身のラッチをD→S-Rに置き換えただけ。
flowchart LR subgraph "マスター・スレーブSR-FF" subgraph "マスター (G=CLK)" MSR["S-Rラッチ"] end subgraph "スレーブ (G=NOT CLK)" SSR["S-Rラッチ"] end INV["NOT"] end S["S"] --> MSR R["R"] --> MSR CLK["CLK"] --> MSR CLK --> INV INV --> SSR MSR --> SSR SSR --> Q["Q"] SSR --> Qb["Q'"] style MSR fill:#bbf,stroke:#333 style SSR fill:#bbf,stroke:#333 style INV fill:#ff9,stroke:#333
真理値表(CLK↑のときだけ有効)
| CLK | S | R | Q+ | 動作 |
|---|---|---|---|---|
| ↑ | 0 | 0 | Q | 保持 |
| ↑ | 0 | 1 | 0 | リセット |
| ↑ | 1 | 0 | 1 | セット |
| ↑ | 1 | 1 | - | 禁止 |
| それ以外 | - | - | Q | エッジ以外は無視 |
SR-FF特有の問題:「1s catching problem」
- CLK=1の間、マスターは透過状態
- ここでSやRが一瞬でも1になると、マスターがその値を拾って覚えてしまう(キャッチ)
- 特に S=1(セット)をキャッチすると、マスターは元に戻らない(SRラッチはS=0,R=0で保持だから)
- → CLK↓でその値がスレーブに映り、想定外のQ=1が出力される
SR-FFはD-FFと違って、CLK=1の間にS/Rを変化させてはいけないという制約がある。
sequenceDiagram participant CLK participant S as S participant R as R participant Q as Q Note over CLK,Q: CLK=1の間にSが一瞬1になる CLK-->>CLK: 1 (マスター透過中) S-->>S: 1(グリッチ!) Note over S: マスターがS=1をキャッチ! S-->>S: 0に戻る Note over Q: でもマスターはQ=1を覚えたまま CLK-->>CLK: ↓ Note over Q: マスターのQ=1が→スレーブに映る Note over Q: Sは一瞬しか1じゃなかったのに<br/>Qが1で固定されてしまう!
なぜD-FFでは起きないか
- D-FFのDは信号が1本だけ
- CLK=1の間にDが何回変わっても、最後の値だけが意味を持つ
- 途中のグリッチは結果に影響しない
| D-FF | SR-FF | |
|---|---|---|
| CLK=1の間に信号変化 | OK(最後のDだけ採用) | NG(S/Rの変化をマスターが覚えちゃう) |
| 理由 | Dは1本だから影響なし | SとRが独立 → 一度セットされると戻れない |
| 制約 | セットアップ/ホールドのみ | CLK=1の間はS,Rを固定しなきゃダメ |
→ これが実際の回路でSR-FFよりD-FFが好まれる大きな理由!
DラッチのDって何?
- D = Data(データ) → 「1ビットのデータを記憶するから」
- D = Delay(遅延) → 「入力Dが出力Qに1クロック遅れて現れるから」
- どっちの解釈も正しいと言われてる
- SRラッチが「SとRの2本で制御」なのに対して、Dラッチは「D1本で制御」に簡略化したもの
補足:「もとがエッジ駆動だから繋いでもエッジ駆動」の意味
⭐ 正しいのは「S-R FF(マスタースレーブ)がもとがエッジ駆動だから、直列に繋いでもエッジ駆動のまま」。
| 「もと」が指すもの | 繋いだ結果 |
|---|---|
| S-R ラッチ(レベルセンシティブ) | ❌ ラッチ同士はレベルセンシティブのまま。直列にしただけではエッジ駆動にならない(マスタースレーブ構成が必要) |
| S-R FF(マスタースレーブ = すでにエッジ駆動) | ✅ もともとエッジ駆動のFF同士だから、直列に繋いでもエッジ駆動は保たれる。同期回路として安全に使える |
なので文章としては 「S-Rフリップフロップ(マスタースレーブ)はもとがエッジ駆動だから、繋いでもエッジ駆動のまま動作する」 が正確。
J-Kフリップフロップ(S-Rの進化版)
S-R-FFとの違い
| J | K | 動作 | S-Rだと |
|---|---|---|---|
| 0 | 0 | 保持 | 保持 |
| 0 | 1 | リセット(Q=0) | リセット |
| 1 | 0 | セット(Q=1) | セット |
| 1 | 1 | トグル(反転) 🎉 | 禁止だった |
S-R-FFで「使えない」と言われていた(S=1,R=1)に**トグル(反転)**を割り当てたのがJ-K-FF。
JとKの正体
- JとKに正式な略語はない
- S(Set)とR(Reset)の次のアルファベットとしてJKを割り当てたというのが通説
- 覚え方としては J = Set、K = Reset、そして J=K=1 → トグル でOK
真理値表
| J | K | Q | Q+ |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 1 ←トグル! |
| 1 | 1 | 1 | 0 ←トグル! |
特性方程式: Q⁺ = JQ’ + K’Q
J-Kラッチ → J-K-FF(マスタースレーブ)
S-R-FFと同じマスタースレーブ構造:
J ──→ [マスターJKラッチ] ──→ [スレーブJKラッチ] ──→ Q
K ──→ [マスターJKラッチ] ──→ [スレーブJKラッチ] ──→ Q'
CLK ──→ マスターG、NOT→スレーブG
J-K-FF特有の問題:レーシング(発振)
J=K=1(トグル)のとき、CLK=1の間に問題が起きる:
CLK=1 ──────────────────
J=K=1
マスター透過中にトグル発生!
Qが反転 → またJ=K=1を見る → またトグル!
→ CLK=1の間ずっと発振 💥
対策:出力フィードバック
J ──→ AND ──→ [マスターJKラッチ] ──→ [スレーブJKラッチ] ──→ Q
↑ ↓
Q' ←──────────────────────────────────────────┘
K ──→ AND ──→ [マスターJKラッチ]
↑
Q ─────────────────┘
このフィードバックで「JとKが同時に1にならなくなる」:
| J=K=1でQ=0 | J側AND=1·1=1(セット動作)、K側AND=1·0=0(動かない)→ Q=1に |
|---|---|
| J=K=1でQ=1 | J側AND=1·0=0(動かない)、K側AND=1·1=1(リセット)→ Q=0に |
→ 1回だけトグルして、フィードバックで次のトグルはブロックされる!
Tフリップフロップ(Toggle)
J-K-FFのJ=K固定版
J=K=T としたJ-K-FFがT-FF。つまり:
| T | 動作 |
|---|---|
| 0 | 保持 |
| 1 | トグル(反転) |
真理値表
| T | Q | Q+ |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
特性方程式: Q⁺ = T’Q + TQ’ = T ⊕ Q(TとQのXOR)
Tの由来
T = Toggle(トグル)
そのまま。T=1のとき、クロックエッジごとにQが反転するだけ。
使われ方
カウンタに超便利:
T-FFを直列に繋ぐだけで2進カウンタになる
CLK → [T-FF]₀ → [T-FF]₁ → [T-FF]₂
Q₀ Q₁ Q₂ ← 2進数カウンタ
4種のFF比較
| FF | 入力 | 特徴 |
|---|---|---|
| SR-FF | S, R | Set/Reset、でも(1,1)禁止 |
| JK-FF | J, K | 全入力使える。J=K=1でトグル |
| D-FF | D | 一番シンプル、Q⁺=D。実用上主流 |
| T-FF | T | トグル専用。カウンタに最適 |
flowchart LR subgraph "FFの進化系統図" SR["S-R FF\n(1,1)禁止"] JK["J-K FF\n(1,1)→トグル"] D["D FF\nD=J, D'=K\n実用的"] T["T FF\nJ=K=T\nトグルのみ"] end SR --> JK JK --> D JK --> T style SR fill:#f99,stroke:#333 style JK fill:#9f9,stroke:#333 style D fill:#bbf,stroke:#333 style T fill:#ff9,stroke:#333
追加入力を持つフリップフロップ(PR, CLR)
Preset(プリセット)とClear(クリア)
D-FFに非同期(クロック不要)でQを強制書き換えする端子を追加したもの。
| 端子 | 動作 | Qの状態 |
|---|---|---|
| PR (Preset) | Qを1に強制(クロック関係なし) | Q = 1 |
| CLR (Clear) | Qを0に強制(クロック関係なし) | Q = 0 |
優先順位
PR ──── 最優先(Q=1に即座になる)
CLR ─── 次に優先(Q=0に即座になる)
CLK↑ ── PR=CLR=0のときだけ通常のD-FF動作
(PR, CLR) = (1,1) → 禁止(競合して不定)
真理値表(アクティブハイの場合)
| PR | CLR | CLK | D | Q+ | 説明 |
|---|---|---|---|---|---|
| 1 | 0 | - | - | 1 | Preset(強制セット) |
| 0 | 1 | - | - | 0 | Clear(強制リセット) |
| 1 | 1 | - | - | - | 禁止 |
| 0 | 0 | ↑ | 0 | 0 | 通常のD-FF動作 |
| 0 | 0 | ↑ | 1 | 1 | 通常のD-FF動作 |
| 0 | 0 | 0/1 | - | Q | エッジなしは保持 |
※アクティブロー(○付き)の場合はPR=0, CLR=0で有効になるので注意
回路記号
flowchart LR subgraph "D-FF with Preset & Clear" PR["PR (Preset)"] --> FF D["D"] --> FF CLK["CLK"] --> FF CLR["CLR (Clear)"] --> FF FF --> Q["Q"] FF --> Qb["Q'"] end style PR fill:#f9f,stroke:#333 style CLR fill:#f9f,stroke:#333 style FF fill:#bbf,stroke:#333
使われ方:電源投入時の初期化
- 電源ON直後はFFの中身が不定(0か1かわからない)
- CLRに一瞬パルスを入れる → 全FFのQが0に確定!
- これで「確実に初期状態からのスタート」が保証される
- PRは特定のビットだけ初期値1にしたいときに使う
授業の真理値表
| Ck | D | PreN | ClrN | Q |
|---|---|---|---|---|
| - | - | 0 | 1 | 1(Preset) |
| - | - | 1 | 0 | 0(Clear) |
| - | - | 0 | 0 | 禁止 |
| ↑ | 0 | 1 | 1 | 0 |
| ↑ | 1 | 1 | 1 | 1 |
| 0/1 | - | 1 | 1 | Q(保持) |
非同期フリップフロップ
非同期 = クロックを待たない
さっきのPR/CLRが非同期入力そのもの。
| 入力の種類 | 例 | いつ効くか |
|---|---|---|
| 同期入力 | D, J, K, T, CE | CLK↑の瞬間だけ有効 |
| 非同期入力 | PR, CLR | CLKに関係なく即座に有効 |
つまり今までやってきた「PR/CLR付きD-FF」= 非同期フリップフロップ。新しい話は何もない。
同期 vs 非同期
CLK ──┐ ┌──┐ ┌──┐ ┌─
↓ │ ↓ │ ↓ │
同期(D, CE)はCLK↑を待つ
CLR ── 1 ──── ← 非同期はCLKを無視して即座に動く
↓
Q 0(ClrNが来た瞬間0になる!)
クロックイネーブル(CE)付きフリップフロップ
CEとは
「次のCLK↑で更新するか?しないか?」を制御する同期入力。
| CE | CLK↑のときの動作 |
|---|---|
| 0 | 保持(今のQをそのまま) |
| 1 | 更新(Dの値を取り込む) |
実装(MUX + D-FF)
flowchart LR subgraph "CE付きD-FF" MUX["MUX\n0→Q, 1→D"] DFF["D-FF"] end Q_fb["Q(フィードバック)"] -->|0| MUX D["D"] -->|1| MUX CE["CE"] --> MUX MUX --> DFF CLK["CLK"] --> DFF DFF --> Q["Q"] DFF --> Qb["Q'"] style MUX fill:#9f9,stroke:#333 style DFF fill:#bbf,stroke:#333
CE=0 → Dに今のQを入れる → CLK↑でQ⁺=Q(保持)
CE=1 → Dに外部Dを入れる → CLK↑でQ⁺=D(更新)
真理値表
| CE | CLK | D | Q+ |
|---|---|---|---|
| 0 | ↑ | - | Q(保持) |
| 1 | ↑ | 0 | 0 |
| 1 | ↑ | 1 | 1 |
| - | 0/1 | - | Q(エッジなしは保持) |
使われ方
- レジスタ:「書き込み命令のときだけ更新」
- カウンタの一時停止
- 省電力:「更新不要なときはCE=0にしてFFを止める」
実用的D-FFの完全版
現実のD-FFはこれだけの入力を持つ:
flowchart LR subgraph "完全版D-FF" FF["D-FF"] end PR["PR(非同期:1に強制)"] --> FF CLR["CLR(非同期:0に強制)"] --> FF CE["CE(同期:更新ON/OFF)"] --> FF D["D(同期:データ)"] --> FF CLK["CLK"] --> FF FF --> Q["Q"] FF --> Qb["Q'"] style PR fill:#f9f,stroke:#333,stroke-dasharray:5 5 style CLR fill:#f9f,stroke:#333,stroke-dasharray:5 5 style CE fill:#9f9,stroke:#333,stroke-dasharray:5 5 style D fill:#bbf,stroke:#333 style FF fill:#bbf,stroke:#333
| 入力 | 同期/非同期 | 役割 |
|---|---|---|
| D | 同期 | 取り込むデータ |
| CE | 同期 | 更新するかどうか |
| CLK | — | タイミング(↑で取り込み) |
| PR | 非同期 | Q=1に強制(最優先) |
| CLR | 非同期 | Q=0に強制(PRの次優先) |
非同期式順序回路とハザード
ハザードとは
配線やゲートの遅延の違いによって、本来出るはずのない一瞬のパルス(グリッチ)が出力に出てしまうこと。
例:Z = A AND A' は論理的には常に0
でもNOTの遅延でAとA'が一瞬両方1になる瞬間がある
A ──┐ ┌──┐ ┌──
│ │ │ │
A' ──┘ ┘ └──┘
↑ここだけ一瞬AもA'も1!
Z ┌─┐ ← 一瞬1のパルス(ハザード)
同期 vs 非同期での影響の違い
| 同期回路 | 非同期回路 | |
|---|---|---|
| ハザードの影響 | CLK↑までに収まれば無視される | 直接誤動作に繋がる |
| なぜ? | 「CLK↑の瞬間の値」だけ見るから | クロックがないので変化がそのまま状態遷移に使われる |
非同期回路ではハザードが状態遷移を引き起こしたり、誤った状態で停止したりするため、対策が超重要。
ハザードの種類
| 種類 | 内容 |
|---|---|
| 静的1ハザード | 出力が1のはずなのに一瞬0になる |
| 静的0ハザード | 出力が0のはずなのに一瞬1になる |
| 動的ハザード | 0→1や1→0の変化中に何度も振動する |
本質的ハザード
回路の状態遷移そのものに内在するハザード。複数の状態変数が同時に変わろうとするときに、遅延差で一時的に別の状態を経由してしまうことで発生する。
対策
- 冗長項の追加(カルノー図で隣接セルをカバーする項を加えて、遷移中も出力が一定になるようにする)
- 同期回路にする(一番確実。クロックでタイミングを統一)
- 遅延の調整(各パスの遅延を揃える)
- フィルタ回路を入れる
まとめ
非同期回路はハザードに弱いから設計が難しい。だからこそ同期回路が主流になっている。非同期式順序回路を扱うときは、遅延の制御とハザード対策が常に付きまとう。
ラッチ/FFの状態表現
ラッチやフリップフロップは現在の状態 と次の状態 を持つ。
は入力と現在の状態 から特性方程式(またはカルノー図)で求められる。
各ラッチ/フリップフロップのまとめ
ラッチ
種類 制御 特性方程式 特徴 SRラッチ S,R 最もシンプル。(1,1)禁止 Dラッチ D,G G=1で透過、G=0で保持 フリップフロップ
種類 入力 特性方程式 特徴 D-FF D 実用上主流。シンプル SR-FF S,R (1,1)禁止。1s catching注意 JK-FF J,K (1,1)でトグル。出力FBで安定化 T-FF T トグルのみ。カウンタ用 追加端子
端子 種類 動作 CE 同期 0で保持、1で更新 PR 非同期 Q=1に強制(クロック不要) CLR 非同期 Q=0に強制(クロック不要) ハザード
非同期回路ではゲート遅延差によるグリッチ(ハザード)が誤動作の原因になる。
同期回路ならCLK↑までに収まれば無視されるため、同期回路が主流。