シンクロナイザ #
非同期のクロック間のデータ転送にはある種のテクニックが必要となってくる。
非同期クロック間のデータ転送問題 #
何も考えずにデータを転送した場合に発生する問題は大きく分けて二つある。互いに非同期なクロックclk_aからclk_bへ1bitの信号を転送する場合を考える。
ハザードの発生 #
組み合わせ回路の出力にハザード(グリッチ)がでることがあるが、非同期なクロック間転送ではこのハザードをサンプリングしてしまうかもしれない
これを回避するために異なるクロック間には組み合わせ回路を配置しないようにする。
メタステーブルの発生 #
前段の信号の変化中に後段がサンプリングしてしまいメタステーブルが発生。この信号を組み合わせ回路に入れてしまうかもしれない。
これを回避するためにメタステーブルが発生した信号を組み合わせ回路に入力しないように設計する。
多ビットのデータ転送 #
これでクロック間のデータ転送ができるようになったが、1bitの場合しか考えていなかった。多ビットになった場合も同様に考えて良いのだろうか。答えはNO!だ。例えば8bitのデータdata[0..7]を転送する場合を考える。clk_aのタイミングで8’b00001111 -> 8'00010000に変化し、これをclk_bでサンプリングすると考えるともしかすると変更中の値8’b00001100をサンプリングしてしまうかもしれない。これはdataの8bit全ての遅延が同一でないために発生する現象である。それではこの問題を解決するにはどうすれば良いだろうか。
上位プロトコルで規定 #
最も簡単な方法は上位のプロトコルでサンプリングのタイミングを明示する方法である。例えばソフトウェアで制御する場合等が該当する。clk_aによるデータサンプリング後のxx秒後にclk_bでデータサンプリングする場合等が該当する。この場合であれば遅延に関しては考える必要がないことは明白である。
Enable信号の利用 #
もう一つの方法が1bitのEnable信号を利用する方法である。このenable信号を使って更新タイミングを生成する。
よく使われる例がBUS_Aで受け取った信号をBUS_Bに伝送する場合等である。
ハンドシェイク #
もう一つがハンドシェイクを利用する方法である。Enable信号を利用した方法であればclk_a, clk_bの周波数が既知である必要があり、その周波数によってFFの数等が変わってる。これを自動調整する方法がハンドシェイクである。ハンドシェイクの信号reqとackを2回FFで転送すれば、出来上がる。ただしこの方法は転送に時間がかかるのが欠点である。