「Latch inferred 地獄から脱出した3日間」もふねこの実験ログ

もふねこ

「Warning: Latch inferred for signal 'xxx'」──この警告を見た瞬間の絶望感、もふねこも知ってるよ🐾
このページは、実習で丸3日間ラッチ地獄にハマった学生と一緒に解決した実験ログ。「直したはずなのに消えない!」を3段階で追体験しながら、最終的にはラッチの正体まで理解できる構成にしたよ!

⚠️
この実験ログについて 以下の内容は、もふねこが大学の実習指導で実際に遭遇したケースを元に、学習用に再構成したものです。ラッチ生成の3つの原因を「Day 1 → Day 2 → Day 3」の時系列で追体験できるようにまとめています。

1. はじめに:Warning地獄の3日間

実習で、ある学生がデコーダ回路を書いていました。シミュレーションは完璧に通る。波形も綺麗。なのに、論理合成をかけるとWarningの嵐が出る──。

Warning: Latch inferred for signal 'Z'
Warning: Latch inferred for signal 'DATA2'

「Warningだから動くんですよね?」と学生は言いました。もふねこは首を横に振りました。

もふねこ

🐾 もふねこ:
「Latch inferred」のWarningは絶対に無視しちゃダメ。意図しないラッチは、ノイズで誤動作したり、タイミング解析を破綻させたり、実機で再現性のないバグを生み出す元凶なんだ。Warningが0になるまで、一緒にデバッグしよう。

ここから、3日間の格闘が始まりました。

2. Day 1:「elseを書いたのに消えない」

🔴 症状

学生が書いたANDゲート相当の組合せ回路に「Latch inferred」のWarningが出る。

🔍 原因:if文のelseが抜けていた

// ❌ Day 1 のコード:else不足
always @(A, B) begin
    if (A == 1'b1 && B == 1'b1)
        Z = 1'b1;
    // A=0 や B=0 のとき Z はどうなる?→ 抜けている!
end
⚠️ なぜラッチが生まれるのか

A=1, B=0 のとき、Z の値が定義されていません。合成ツールは「値が定義されていないなら、前の値を保持(記憶)しなければならない」と解釈し、記憶素子であるラッチを作ってしまいます。

✅ Day 1 の修正

// ⭕ 修正後:elseで残りの条件をすべてカバー
always @(A, B) begin
    if (A == 1'b1 && B == 1'b1)
        Z = 1'b1;
    else
        Z = 1'b0;   // ← これでラッチは消える!
end
もふねこ

🐾 もふねこ:
「よし、これでWarning消えた!」と学生は喜んだ。でもまだ終わりじゃなかったんだ……。

📌 Day 1 の教訓
  • if 文の最後には必ず 単独の else を書く
  • case 文の最後には必ず default を書く
  • 条件分岐に「抜け」があると、合成ツールは自動的にラッチを推論する

3. Day 2:「全部の分岐を網羅したのにまだ出る」

🔴 症状

Day 1 の修正で一部のWarningは消えたが、別の信号で「Latch inferred」が再発。学生は「elseもdefaultも全部書いたのに!」と混乱。

🔍 原因:複数出力時の代入漏れ

// ❌ Day 2 のコード:DATA2 の代入漏れ
always @(A) begin
    case (A)
        1'b0: DATA1 = 1'b1;   // ← DATA2 がない!
        1'b1: begin
            DATA1 = 1'b0;
            DATA2 = 1'b1;
        end
        default: begin
            DATA1 = 1'b0;
            DATA2 = 1'b0;
        end
    endcase
end

A=0 のとき、DATA2 はどうなるでしょうか? DATA1 には 1 が入りますが、DATA2 の記述がないため、「前の値を保持」→ ラッチが生成されます。

⚠️ 見落としやすいポイント

条件分岐の網羅(else/default)は完璧でも、すべての分岐ですべての出力信号に値を代入しているかを確認しないと、ラッチが生まれます。出力信号が増えるほどこのミスは起きやすくなります。

✅ Day 2 の修正:先頭初期化テクニック

// ⭕ 修正後:always文の先頭で全出力を初期化
always @(A) begin
    DATA1 = 1'b0;   // ← まず全出力をデフォルト値で初期化!
    DATA2 = 1'b0;   // ← これが最強のラッチ防止策

    case (A)
        1'b0: DATA1 = 1'b1;   // DATA2 は初期化済みなので記述不要!
        1'b1: begin
            DATA1 = 1'b0;
            DATA2 = 1'b1;
        end
        // default すら不要になる(全出力が初期化済みのため)
    endcase
end
もふねこ

🐾 もふねこ:
「先頭初期化」を覚えた瞬間、学生の顔がパッと明るくなったんだ。「これなら分岐の中で『DATA2書いたっけ?』って悩む必要がない!」って。そう、この「先頭で全出力をデフォルト代入する」テクニックは、ラッチ防止の最強パターンだよ🐾

📌 Day 2 の教訓
  • always文の先頭で、すべての出力信号にデフォルト値を代入する
  • その後のcase/if文では、変更が必要な信号だけ上書きすればよい
  • この方法なら、出力信号が何本あってもラッチが生まれない

4. Day 3:「そもそもラッチって何だったの?」

Warningは全て消えました。しかし学生は、ふと疑問を感じます。

ラッチを作っちゃダメ!って言われるけど、そもそもラッチって何?フリップフロップと何が違うの?

もふねこ

🐾 もふねこ:
いい質問!「なぜダメなのか」を理解せずにルールだけ覚えても、応用が効かないよね。ここが一番大事なところだから、しっかり説明するね。

D-FFとラッチの決定的な違い

項目D-FF(フリップフロップ)ラッチ(Dラッチ)
動作タイミングクロックのエッジ(瞬間)でデータを読み込むイネーブル信号がHighの間ずっとデータを素通しにする
イメージ「せーの!」の合図で全員一斉に動く優等生合図を待たずに勝手に動く自由人
ノイズ耐性エッジの瞬間以外のノイズは無視ゲートが開いている間のノイズを全部拾ってしまう
タイミング解析STA(静的タイミング解析)が容易タイムボローイング等の特殊解析が必要で極めて複雑
FPGA適性FPGA内部はD-FF前提で設計されている → 最適不自然な回路が割り当てられ、リソース無駄遣い → 不適

なぜ「意図しないラッチ」が危険なのか

⚠️
意図しないラッチの3つの危険
  1. ノイズで誤動作:ゲートが開いている間、一瞬のヒゲ信号(グリッチ)もラッチが拾って記憶してしまう
  2. タイミング解析が破綻:D-FFだけなら「次のクロックまでに間に合えばOK」と簡単に計算できるが、ラッチが混ざると計算が非常に複雑化する
  3. FPGAのリソースを無駄遣い:FPGAは「LUT+D-FF」のセットが敷き詰められた構造。ラッチを無理やり作ると非効率な回路になる
もふねこ

🐾 もふねこ:
「論理合成ツールが『Latch inferred』と怒るのには、こういう深い理由があったんだね!」と学生は納得してくれた。3日間の苦労が、ここで一気に報われた瞬間だったよ🐾

5. 二度とハマらないための3つの鉄則

3日間の実験ログを踏まえて、もふねこが実習で教えている「ラッチ0件にするための鉄則」をまとめます。

#鉄則対応するDay
1 if文の最後に必ずelseを書く。case文の最後に必ずdefaultを書く
条件分岐に「抜け」があると即ラッチ生成
Day 1
2 always文の先頭で全出力をデフォルト値に初期化する
複数出力の代入漏れを根本的に防止する最強パターン
Day 2
3 Warningが0件になるまで絶対に実機に書き込まない
「Latch inferred」は「動いているように見えるバグ」の温床
Day 3

6. まとめ

📝 Latch地獄 脱出マップ

Day問題原因解決策
1else不足でラッチ生成条件分岐の網羅漏れif → else / case → default を必ず書く
2複数出力で代入漏れ一部の分岐で一部の出力が未定義always文の先頭で全出力を初期化
3なぜラッチがダメなのか不明D-FFとラッチの違いを知らなかった「エッジ vs レベル」「ノイズ耐性」を理解
📌 このページで一番覚えてほしいこと

先頭初期化」を癖にすれば、ラッチ地獄はほぼ確実に回避できます。always文を書くときは、まず全出力にデフォルト値を入れてから、その後のif/case文で上書きする──この順序を体に叩き込んでください。

関連するページ: 応用実験5: ラッチを生む3つの原因と対策 | 実験ログ1: Sim/Synthミスマッチを解剖する | 実験ログ3: Warning放置で溶かした話 ベスト5