FPGA を学び始めると、異なるクロックドメイン間の信号をやり取りするときにメタステーブルが発生する という問題に直面します。この問題を防ぐために「シンクロナイザ(二段FF)」が必要とされますが、初心者には 「コード上では何も意味がないように見える」 ため、なぜ使うのか理解しづらいことがあります。
本記事では、シンクロナイザの必要性、メタステーブルの仕組み、そして適切な使用方法について詳しく解説します。
1. シンクロナイザとは?
🔹 メタステーブルとは?
異なるクロックドメイン間で直接信号をやり取りすると、セットアップ時間(Setup Time)やホールド時間(Hold Time)が満たされず、FF の出力が不安定な状態(メタステーブル)になる ことがあります。
- メタステーブルが発生すると、信号が 0 でも 1 でもない不定な状態 になり、予測できない誤動作が起きる可能性 があります。
- FPGA では、クロックエッジのタイミングが完全に一致することはないため、異なるクロックドメイン間のデータ転送ではこの問題が必ず発生する可能性がある ということを前提に設計する必要があります。

🔹 シンクロナイザ(二段FF)とは?
シンクロナイザとは、異なるクロックドメイン間の信号を2段のフリップフロップを通して安定化する手法 です。
- 1段目のFF:メタステーブルの影響を受ける可能性がある。
- 2段目のFF:1段目のメタステーブルの影響を受けにくくなり、安定した値を次の回路に伝える。
🔹 シンクロナイザを入れることで、メタステーブルが解消される確率が大幅に向上する!
2. シンクロナイザの実装方法
✅ Verilog のシンクロナイザ実装例
reg d_sync1, d_sync2;
always @(posedge clk_fast) begin
d_sync1 <= d_slow; // 1段目のFF
d_sync2 <= d_sync1; // 2段目のFF
end
assign d_stable = d_sync2;
✅ VHDL のシンクロナイザ実装例
signal d_sync1, d_sync2 : std_logic;
process(clk_fast)
begin
if rising_edge(clk_fast) then
d_sync1 <= d_slow; -- 1段目のFF
d_sync2 <= d_sync1; -- 2段目のFF
end if;
end process;
d_stable <= d_sync2;
💡 これを見ても、コード上では「何もしていない」ように見えるかもしれませんが、物理的なハードウェアの動作としては非常に重要です!
3. なぜ二段FFでメタステーブルが解消されるのか?
メタステーブル状態は、時間が経過することで 指数関数的に解消される 性質を持っています。
⏳ メタステーブルの解消確率
メタステーブルの状態が t
時間後に解消される確率 P(t)
は以下のように表されます。
$$P(t) = e^{-t/\tau}$$
τ
(タウ):メタステーブルが収束する時間定数(FPGA のプロセス技術に依存)t
:経過時間(クロックサイクル)
1段目のFFでメタステーブルが発生しても、2段目のFFで99.9%以上の確率で安定した値になる ため、メタステーブルの影響をほぼ完全に防ぐことができます。
4. シンクロナイザが必要なケース & 不要なケース
✅ シンクロナイザを入れるべきケース
- 異なるクロックドメイン間で単一ビット信号を渡す場合
- 例:
start_signal
やdone_flag
などの制御信号
- 例:
- 外部入力(ボタン、GPIOなど)を扱う場合
- 例: スイッチやセンサーの値をFPGA内部で処理
- FSM(状態機械)の遷移条件が非同期信号に依存する場合
- 例:
state_change
の信号が異なるクロックドメインから来る
- 例:
❌ シンクロナイザを入れなくていいケース
- 同じクロックドメイン内で信号を伝える場合
- マルチビットのデータ転送(代わりにFIFOを使う)
- 短時間の信号で、誤動作の影響がほぼない場合
💡 つまり、「必要な場合にのみシンクロナイザを使う」ことが最適な設計!
5. まとめ:FPGA初心者がシンクロナイザで気をつけること
項目 | シンクロナイザなし | シンクロナイザ(二段FF) |
---|---|---|
メタステーブルの発生 | 高い | ほぼ解消 |
誤動作の可能性 | 高い | 非常に低い |
リソース消費 | なし | 2FF 消費 |
推奨度 | ❌ 避けるべき | ✅ 必須(必要な場合のみ) |
🎯 結論
✔ 異なるクロックドメイン間の信号を直接使わない! ✔ 単一ビットの信号は二段FFで同期する! ✔ マルチビットデータ転送にはFIFOを使う! ✔ シンクロナイザを無闇に増やさず、必要な場合のみ使用!
FPGA設計では 論理回路だけでなく、物理的な動作を考慮することが重要 です!