「シミュレーションは通ったのに実機で動かない」を解剖する

もふねこ

「シミュでは完璧に動いたのに、実機だけ壊れる」──これ、毎年必ず誰かがハマるんだ🐾
このページでは、もふねこが実習の現場で実際に見てきた「Sim/Synthミスマッチ」の3大原因を、チェックリスト形式で体系的にまとめたよ。実機に書き込む前に、ここを一通り確認する習慣をつけてほしいな!

📌 このページの概要

シミュレーション(RTL検証)では完璧に動くのに、実機(FPGA / ASIC)だけ壊れる現象を「Sim/Synthミスマッチ」と呼びます。このページでは、もふねこが大学の実習指導や就職した学生からの相談で実際に遭遇した3つの主要原因を体系的に整理し、実機書き込み前に使えるチェックリストとしてまとめます。

1. Sim/Synthミスマッチとは何か

HDL設計の開発フローでは、まずシミュレーションで回路の機能を確認し、次に論理合成で実際のゲートに変換します。この2つの工程で結果が一致しない現象を「Sim/Synthミスマッチ」と呼びます。

⚠️
なぜ「最悪のバグ」と呼ばれるのか シミュレーションでは何度テストしても正常に動作するため、設計者は「問題ない」と確信して実機に書き込みます。しかし実機でだけ誤動作が発生し、しかも再現性が低いため、原因特定に数日〜数週間かかることもあります。エラーメッセージも出ないため、経験がないと「どこを見ればいいかすらわからない」状態に陥ります。

以下の3つが、もふねこが現場で実際に見てきた主要原因です。

#原因壊れ方の特徴検出の難しさ
センシティビティリストの漏れ特定の入力変化に反応しないWarningを見れば気づける
リセット忘れによるX伝搬電源投入直後だけ暴走する波形にXが隠れていることがある
ゲートレベル検証の省略数分後にカウンタが暴走などRTL検証では絶対に再現しない

2. 原因①:センシティビティリストの漏れ

もふねこ

🐾 もふねこの現場メモ:
これが一番多い。always @(A) と書いて B を入れ忘れるやつ。シミュレータは「Aが変化したときだけ計算する」という挙動になるけど、合成ツールは右辺の論理式を見て普通にANDゲートを作ってしまう。結果、シミュの動きと実機の動きが全く別物になるんだ。

❌ NG例:Bがリストから漏れている

// シミュレータ → Aが変わったときだけ計算(Bの変化は無視)
// 合成ツール  → AとBのANDゲートを普通に生成
always @(A) begin
    Z = A & B;   // ← Bがセンシティビティリストにない!
end
⚠️ 何が起きるか
  • シミュレーション:Bが変化してもZは更新されない(Aの変化でしか動かない)
  • 実機(合成後):AとBのどちらが変化してもZは即座に更新される
  • 結果:シミュレーション結果と実機の動作が完全に不一致

⭕ OK例:always @(*) を使う

// Verilog-2001以降:ツールが自動で全入力を拾ってくれる
always @(*) begin
    Z = A & B;   // ← AもBも自動で検出!
end

✨ ベストプラクティス:always_comb(SystemVerilog)

// 「ここは組合せ回路です」とツールに明示的に宣言
always_comb begin
    Z = A & B;   // ← ラッチが生まれそうになるとエラーで教えてくれる!
end
💡 対策まとめ
  • 組合せ回路では手書きのセンシティビティリストを使わない
  • Verilog-2001以降なら always @(*) を原則にする
  • SystemVerilog環境なら always_comb が最強(ラッチ生成時にエラーが出る)
  • 合成ツールのWarningに「signal not in sensitivity list」があれば即座に修正

3. 原因②:リセット忘れによるX伝搬

もふねこ

🐾 もふねこの現場メモ:
「電源を入れた直後だけ壊れて、リセットボタンを押すと直る」という相談も何度か受けたことがあるんだ。原因は、一部のフリップフロップにリセットを入れ忘れていたこと。シミュレーションでは全信号が最初から x(不定値)として表示されるけど、波形ウィンドウで x が赤く表示されても「まあ最初はそうだよね」と見過ごしてしまうんだ。

X伝搬の恐ろしさ

シミュレーションの世界では、リセットされていない信号の初期値は x(不定値)です。この x は演算に使われると後段にも伝搬します(これを「X伝搬」と呼びます)。

状況シミュレーション実機
リセット忘れのFF初期値 = x(不定値)ASICでは電源投入時のランダム値。FPGAではコンフィグレーション時の初期値(多くは0)になるが、初期値頼みの設計は危険
X伝搬の影響後段の演算結果もすべて x になるランダムな値で動くため「たまたま動く」ことがある
発見しやすさ波形を注意深く見れば x で気づける再現性が低く原因特定が困難
⚠️
「実機で動いたから大丈夫」は最も危険な思い込み ASICでは電源投入時にフリップフロップが 01 のどちらかにランダムに初期化されます。たまたま正しい値になれば動いてしまうため、「何度か試して動いた」だけでは安全とは言えません。温度変化や電源電圧の変動で初期値が変わり、突然壊れることがあります。FPGAではコンフィグレーション時に既定の初期値(多くは0)が入りますが、リセット解除のタイミングや別ボード・別デバイスへの移植で挙動が変わるため、「初期値頼みの設計」が危険であることは同じです。
💡 対策まとめ
  • すべてのフリップフロップに非同期リセットまたは同期リセットを入れる
  • シミュレーション波形でx が残っているFFがないか確認する
  • テストベンチの最初に必ずリセットシーケンスを入れる
  • 合成ツールのWarningに「initial value」「uninitialized」があれば確認

4. 原因③:ゲートレベル検証の省略

もふねこ

🐾 もふねこの現場メモ:
就職した学生から「論理合成も通ったしシミュレーションで動作確認したので実機に書き込もうとしたら、先輩に『ゲートレベル検証は?』と止められました。シミュレーション、もう一回やるんですか?」と言われたことがあるんだ。この「2回目の検証」を飛ばして実機で数日溶かすケースを、何度も見てきたよ。

RTL検証とゲートレベル検証の違い

項目RTL検証(1回目)ゲートレベル検証(2回目)
タイミング論理合成の論理合成の
確認する対象回路の機能(動作)タイミング(遅延)を含めた動作
信号の遅延理想的(瞬間移動)実際のゲート遅延を含む
入力ファイルRTLソースコードネットリスト + シミュレーション用ライブラリ
検出できるバグ論理エラータイミング違反・セットアップ/ホールド違反

RTL検証では信号が「理想的に瞬間移動」する前提でシミュレーションが行われます。しかし現実の回路では、ANDゲートやフリップフロップを通るたびにわずかな遅延が生じます。この遅延が積み重なると、「クロックが来た瞬間、まだデータが届いていない」というタイミング違反が発生します。

⚠️
RTL検証では「何回やっても絶対に再現しない」 タイミング違反はRTLレベルのシミュレーションでは原理的に検出できません。「シミュでは綺麗にカウントしていたのに、実機では数分後にカウンタが暴走する」──こうした壊れ方をします。再現条件も不安定なため、経験なしでの原因特定は非常に困難です。
💡 対策まとめ
  • 実機に書き込む前に必ずゲートレベル検証を実施する
  • シミュレーション用ライブラリは論理合成用ライブラリとは別物(間違えやすい)
  • テストベンチはRTL検証のものをそのまま流用できる
  • 現代のFPGA開発ではSTA(静的タイミング解析)ツールも活用する

5. 実機書き込み前チェックリスト

もふねこが実習の現場で使っている「実機に書き込む前の最終確認リスト」をまとめました。1つでも「いいえ」があれば、実機書き込みは待ったほうがいいです。

#チェック項目対応する原因
1組合せ回路のalways文で @(*) または always_comb を使っているか?原因①
2合成ツールのWarningに「sensitivity list」関連の警告がないか?原因①
3すべてのフリップフロップにリセット(非同期 or 同期)が入っているか?原因②
4シミュレーション波形でリセット後に x が残っているFFがないか?原因②
5論理合成後にゲートレベル検証(またはSTA)を実施したか?原因③
6ゲートレベル検証でシミュレーション用ライブラリ(合成用とは別)を使っているか?原因③
7if文/case文でdefault/elseを省略していないか?(ラッチ生成防止)共通
もふねこ

🐾 もふねこの現場メモ:
「7つも確認するの大変じゃない?」と思うかもしれないけど、これをサボって実機デバッグに3日溶かすのと、5分でチェックリストを確認するのと、どちらがいいかは明らかだよね。最初は面倒でも、これを習慣にした学生は実機デバッグで圧倒的に速くなっていったんだ🐾

6. まとめ

📝 Sim/Synthミスマッチ 3大原因と対策

原因症状対策
センシティビティリスト漏れ特定信号の変化に反応しないalways @(*) or always_comb を使う
リセット忘れ(X伝搬)電源投入直後に暴走全FFにリセットを入れる。波形でXを確認
ゲートレベル検証の省略数分後に突然壊れる合成後にGL検証 or STAを必ず実施
📌 このページで一番覚えてほしいこと

「シミュレーションで動いた ≠ 実機で動く」。この認識があるだけで、実機でトラブルが起きたときに「どの工程に問題があるか」を絞り込めるようになります。RTL検証・論理合成・ゲートレベル検証を、頭の中で「3つの別工程」として分けて考えることが出発点です。

関連するページ: 文法実験3: シミュレーションと論理合成を体験する | 応用実験5: ラッチを生む3つの原因と対策 | 合成実験1: 論理合成の仕組みを知る