FC2カウンター FPGAの部屋 2009年04月18日
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

同期FIFOと非同期FIFO

”Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのシミュレーション2”でCore Generatorで生成したFIFOがフリーランクロックでないとおかしくなる件だが、結局、XilinxCoreLibフォルダのFIFO_GENERATOR_V4_4.vを見てもよくわからなかった。
この上は、自分で非同期FIFOを作ろうか?と思って、調べていたら、Asynchronous FIFO(verilogのサンプル)を見つけたが、これを非同期リセットに書き換えてやってみたが、まだシミュレーション結果がおかしい。
そのほかに、非同期FIFOの資料はSunburst Design, Inc.のSimulation and Synthesis Techniques for Asynchronous FIFO Designがあったが、結構長いので、あまり読む気がせずに困っていた。
検索していると、なつたんさんの”FPGAで非同期のクロックを扱う方法”がヒット。そういえば、私も"Advanced FPGA Design: Architecture, Implementation, and Optimization"を買ったんだった。
さっそく、職場にあったので、取りにって見てみると、96ページにありました。そのものばっちりの図が。Figure 6.14 Simplified asynchronous FIFO.です。図を見たら一発でわかりました。(誤解しているかもしれませんが。。。)初めてこの本を買ってよかったと思いました。

ちょっと説明を加えると、非同期FIFOはWriteのクロックとReadのクロックが非同期だ。なので、普通の同期FIFOの構成だと、たぶんたまに動作がおかしくなる。
私の考える同期FIFOは下の図のように、Dual-Port Memoryがあって、そのアドレスはBinaryカウンタのWrite CounterとRead Counterから入力している。各カウンタの値でEmptyかFullかを判定するロジックがある。
Synchronus_FIFO_090418.png

ここで、例えば、書き込み側のWrite Counterの値と読み出し側のRead Counterの値が等しくなるときはEmpty、 Read Counter - 1 = Write CounterのときにFullとする。ここで各Counterは4ビットアドレスだとmodulo=16で演算されているのでリングバッファになる。(この辺で図がほしいところだが、面倒なので割愛する)
さて、この同期FIFOの回路でWriteとReadのクロック領域を分けると、Wirte Counterのアドレスの変化とRead Counterのアドレスの変化が同期しなくなる。バイナリカウンタは例えば、"0111"という値の次は"1000"になる。その時に、配線遅延などのために、ビット2~0が"111"から"000"に変化するj時間よりも、ビット3番目の0が1に変わるのが速かったとしよう。そのような仮定に基づくと、ある時間カウンタの値が"1111"に見えるときが出てきてしまう。同期クロックの場合はそのような時間はクロックのすぐ後となり、次のクロックまでには"1000"に安定している。しかし、非同期クロックの場合はタイミングによってはそのような状況が反対側のクロック領域へ影響してしまう。なので、1カウントに1ビットしか変化しないグレイコードを用いる。グレイカウンタならば、一回に1ビットしか変わらないので、"0111"の次を"1111"に間違うようなことは起こらない。よって、非同期FIFOはグレイコードカウンタを使う可能性が大きい。
私の考えた非同期FIFOは以下のようになった。これは上記の本の図を参考にしている。
Asynchronus_FIFO_090418.png

ここで、わざわざグレイコードをバイナリに直して演算しなくてもいいかも?とは思った。4ビットなのでテーブル持っていてもそんなに大変じゃないと思う。とりあえず上図で作ってみることにしようと思う。
バイナリ-グレイコード変換についてはここグレイコード‐バイナリ変換についてはここを参照する。

ちなみに、相手側のクロック領域のカウンタのカウント値がFFが2つ入ることになる。それによって、Full flagやEmpty flagにどんな影響が出てくるかを考えてみよう。Full GeneratorやEmpty Generatorに入力されるカウント値が遅れるわけだ。Full Generatorで考えると、Read Counter値が遅れてくる。その間にWrite Counterが進むとするとFullが出力されるのが速くなって、Write側の書き込みが、必要以上に早期に止まる可能性がある。これは、フェールセーフの面から言っても安全方向に振れているわけで不正に書き込みができるということはない。Empty Generatorはどうかというと、これも同様で必要以上に早期にEmptyとなる可能性はあっても、データがないのにReadする可能性はない。かくして安全面に振れるのでどちらもOKということになる。

何か間違いがあったら、指摘してください。
  1. 2009年04月18日 22:05 |
  2. IP
  3. | トラックバック:0
  4. | コメント:9