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

もふねこ

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

📌 このページの概要

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

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

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

⚠️
なぜ「最悪のバグ」と呼ばれるのか シミュレーションでは何度テストしても正常に動作するため、設計者は「問題ない」と確信して実機に書き込みます。しかし実機でだけ誤動作が発生することがあり、原因によっては再現条件がつかみにくいため、原因特定に数日〜数週間かかることもあります。ただし難しさは原因ごとに違います。下の表の①は合成ツールの警告で気づけることが多く、②は波形にXが残っていないかを見れば追えます。見つけにくいのは、合成後の確認そのものを省いた③です。

以下の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では電源投入時にフリップフロップが 0 か 1 のどちらかにランダムに初期化されます。たまたま正しい値になれば動いてしまうため、「何度か試して動いた」だけでは安全とは言えません。温度変化や電源電圧の変動で初期値が変わり、突然壊れることがあります。FPGAではコンフィグレーション時に既定の初期値(多くは0)が入りますが、リセット解除のタイミングや別ボード・別デバイスへの移植で挙動が変わるため、「初期値頼みの設計」が危険であることは同じです。
💡 対策まとめ
  • すべてのフリップフロップに非同期リセットまたは同期リセットを入れる
  • シミュレーション波形でx が残っているFFがないか確認する
  • テストベンチの最初に必ずリセットシーケンスを入れる
  • 合成ツールのWarningに「initial value」「uninitialized」があれば確認

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

もふねこ

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

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

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

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

⚠️
タイミング違反は遅延ゼロのRTL検証には現れない RTL検証は信号が瞬時に伝わる前提なので、配線やゲートの遅延によるタイミング違反はそこには現れません。実機では「シミュでは正しく数えていたのに、動作条件がそろったときだけ値が飛ぶ」といった壊れ方をすることがあります。どこでどう壊れるかは回路と条件によるので、症状から原因を決めつけず、STAのレポートと合成後の検証で確かめてね。
💡 対策まとめ
  • タイミングはSTA(静的タイミング解析)で確認する。全経路を調べられるので、これが本来の確認手段だよ
  • ゲートレベル検証は、合成の前後で接続と論理が変わっていないかの確認に効く。遅延情報(SDF など)を与えないとタイミングは見られない
  • シミュレーション用ライブラリは論理合成用ライブラリとは別物(間違えやすい)
  • テストベンチはRTL検証のものを流用できることが多い(リセットや初期化の扱いで手直しが必要になる場合もある)

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

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

#チェック項目対応する原因
1組合せ回路のalways文で @(*) または always_comb を使っているか?原因①
2合成ツールのWarningに「sensitivity list」関連の警告がないか?原因①
3仕様で初期値が必要な状態・validにリセットが入っているか?(無効なデータ部まで一律に入れるかは資源と仕様で判断)原因②
4シミュレーション波形でリセット後に x が残っているFFがないか?原因②
5タイミング制約を与えてSTAを実施したか?(必要なら遅延付きのゲートレベル検証も)原因③
6ゲートレベル検証でシミュレーション用ライブラリ(合成用とは別)を使っているか?原因③
7if文/case文でdefault/elseを省略していないか?(ラッチ生成防止)共通
もふねこ

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

6. まとめ

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

原因症状対策
センシティビティリスト漏れ特定信号の変化に反応しないalways @(*) or always_comb を使う
リセット忘れ(X伝搬)電源投入直後に動作が定まらない仕様で必要な状態・validにリセットを入れる。波形でXを確認
合成後のタイミング確認の省略条件がそろったときだけ誤るSTAでタイミングを確認し、合成後の検証も行う
📌 このページで一番覚えてほしいこと

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

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