久々の日記、グレイコード

ネジを締めたかどうかは 9月まで分からないので :)、とりあえず別のことを考えます。
以前から保留になっていた、周波数カウンタの実装を少しずつ考えています。アナログフロントエンドは QEX から借りることにして、あとは 3.3V のロジックレベルに整合してシミュレーションするくらいでしょうか。(実は、あの回路は結構細かいチューニングが入っていて、バイアスの計算に分かりづらい点もあります。設計者に聞けばいいんでしょうけど、たぶん、設計者自身もカットアンドトライでしょう。)
マイコン部は、Atmel の ATmega を使おうと思っています。Arduino を使えば試作が楽なことと、C コンパイラの利用に比較的不安がないことが理由です。
あとは、高速カウンタ部分ですが、以前から書いているように CPLD で実装しようと思っています。理由の一つは CPLDVerilog の勉強をしたいことですが、Microchip PIC の非同期カウンタよりも高速な実装を目指していることも理由の一つです。
Verilog で書いていて問題になったのは、対象信号の計数は非同期で実現したいのですが、それを読み出すクロックはマスタクロックに同期させたいという点です。対象信号の立ち上がりエッジでカウントして、同立ち下りエッジで読み出すという方法も考えたのですが、対象信号がなくなると読み出せなくなる点(これは最後のカウント値をそのまま使えば良いので大したことない)と、シフトレジスタのシフトクロックと読み出すクロックが二重に必要になって、普通の CPLD のマクロセルでは実現が困難なことです。
そんな訳で、プロの助言を仰ぎました。それによると、これは clock domain crossing 問題の基本的なケースで、非同期 FIFO を使う方法とグレイコードカウンタを使う方法が考えられるが、この場合は後者のほうが良いだろう、ということでした。すばらしい! グレイコードというのは習ったことがありますが、こういうときに使うとは想像してませんでした。
というわけで、グレイコードの復習です。グレイコードのまま計数をするのは大変だそうで、多ビットの場合は、通常のバイナリカウンタで計数して、それをグレイコードエンコードするのが一般的なようです。グレイコードを別クロックで読み出そうとすると、グリッチを避けるために FF の数がカウンタビット数の 2倍必要になるようです。
なお、バイナリからグレイへの変換(エンコード)は、カウンタのビット数に関わらず、1ビットエンコードするのに 1ビット論理の XOR で実現できますが、デコードには、1ビット毎に多入力の XOR、あるいは逐次的な演算が必要で、回路規模が大きくなってしまいます。デコードはマイコン側で実現するほうが現実的かも知れません。
今日は、ここまで。とりあえず汎用的に使える試作ボードでも起こしてみようかなあ。その前に CoolRunner II の評価ボードを動かしてみるのと、3.3V の Arduino を入手せねば。。。(やや現実逃避)