2007.11.5 新規

DCOとは?

 DCO(DigitalControledOscrator)はデジタル信号で周波数を制御できる発振器の事を指します。
 今回はFPGAのロジックで発振器を作ってしまえという無謀な実験です。

 周波数シンセサイザ(FrequencySynthesizer)といえば、真っ先にPLL(PhaseLockedLoop)を思いつくのではないでしょうか。
 PLLはクロックの位相差を検出することでクロックにもう一方のクロックを同調させる制御装置を指しますが、一般的には周波数シンセサイザそのものやVCO+分周器+PLLをまとめてPLLと呼ぶ事が多いようです。
 これはほとんどのPLL式周波数シンセサイザが、リファレンスクロック、VCO、分周器、PLL、ループフィルタで構成され、そのうちのPLL、分周器、VCO(VoltageControledOscrator)の3つをモジュール化して、リファレンスクロックとループフィルタを外部コンポーネントとして接続することが多い為でしょう。
 しかし、ここではPLLは純粋に制御装置として扱うのでPLLに分周器や発振器が含まれないことを念頭に置いてください。そして発振器はVCOではなくDCOを使います。

ロジックだけで発振する?

 反転ロジックにCRの時定数とヒステリシスを持たせたいわゆるCR発振ではなく、純粋なロジックだけでも発振器を作れます。
 これはリングバッファ式の発振器等と呼ばれるようです。まずはリングバッファ式のVCOの回路の原理を考えます。

 回路の動作を追いかけます。
 ゲート回路には入力から出力へ信号伝達に一定の遅延を持ち、伝達するときに一定時間だけ遅れます。
 また、遅延時間は電源電圧に反比例して増減します。

 ゲート間遅延はとりあえず1nsと仮定してみます。
 @の地点が'L'だとすると、1ns後にAが'L'になり、さらに1ns後にはBが反転出力で'H'になります。
 Bと@は繋がっているので、@が'L'になってから2ns後に'H'になることになります。
 @が'H'になると、その2nsにBが'L'になり、@もまた'L'に戻っています。
 この動作を4ns毎に繰り返すので、4ns周期=250MHzで発振していることになります。

 ここで電源電圧が下がり、ゲート間遅延が2nsに増加するとどうなるでしょうか。
 周期も単純に2倍の8nsとなり125MHzで発振ということになります。電源電圧の増減で周波数が制御できています。

 実際に、こんなにうまく動作するでしょうか?
 答えはYesです。74HC04等の汎用インバータ3段のループでも100MHz前後で発振できますし、50MHz〜150MHz程度の専用VCOチップも存在します。
 ただし、電源電圧の変化やピンの寄生容量、個体差による周波数変動がシビアなので、電圧値に対する周波数の絶対精度は得られません。周波数の安定度もクリスタルやセラロックなどに及びません。そこでVCOを指定した周波数に保つためにPLL等が使用されます。

 簡略化の為にディレイラインは2段としましたが、実際には2段とは限りません。
 また、実際の回路では電源安定化のためのLCフィルタ等も必要です。

 さて、次が本題のリングバッファ式DCOです。


 ゲートの遅延と反転ループによる発振方法はリングバッファ式VCOと同じですが、段数が増えて、データセレクタが追加されています。

 ここでもゲート間遅延を1nsと仮定してみます。(便宜上セレクタの遅延は0を過程します。)
 セレクタで0を選ぶとAからのループバックで段数は2段、2ns x 2 = 4ns(250MHz)です。
 セレクタで2を選ぶとBからのループバックで段数は4段、5ns x 2 =10ns(125MHz)です。
 デジタル信号の選択で周波数が変化します。

 簡略化の為に上記では選択肢を4種類としましたが、実際は選択数を8〜32程度にします。

VCO vs DCO

 DCOは電圧というアナログ要素を持たないためループフィルタのような外部コンポーネントが不要です。
 しかし、周波数の分解能が理論上無限のVCOに対してDCOは1段のディレイ単位未満の調整が出来ません。
 また、DCOの方がループ段数を多く必要なため、最大周波数も低くなります。
 言い換えるとDCOは設計や制御は簡単だが、周波数性能や精度(ジッタ)が悪いということです。
 しかしジッタに目をつぶってしまえば、PLL等でVCOと同様にDCOも正確な周波数を刻むことができるはずです。

 実際の製品としては、Ti社のMSP430シリーズが内部発振器としてDCOを採用しています。フィードバック回路はPLLではなくFLL(FrequencyLockedLoop)という方法だそうです。

 DCOそのものではありませんが、Xilinx FPGAのDLL(DelayLockedLoop)やDFS(DigitalFrequencySynthesizer)もDCOと類似した回路です。
 FPGA専用のDCMを使って教科書通りにDFSを構築しても全く面白くありません。FPGAの内部ロジックをプログラムして外部コンポーネント無しで発振するDCOと制御回路を組み合わせてDFSを作ります。
 まずはDCOで発振させることです。これが出来なければ先に進みません。

FPGAでDCO

 ここからは、あくまでも実験な措置であり、実用性は皆無であることを前記しておきます。
 FPGAは非同期信号をループさせるような使い方は想定されておらず、本来このような使い方をしてはいけません。
 ここではあくまでも実験装置としてFPGAを使うのだと考えてください。

 FPGAの論理回路部分の基礎単位は、大抵4入力1出力のLUTです。4つの入力に対して出力の値が任意に変化する小さな非同期ROMと考えられます。
 LUTにはFF(フリップフロップ)がセットになっていて通常は数段のLUTを通したらFFでラッチさせて同期回路を構成します。しかし今回はFFを使わずにLUTだけを使います。

 LUTも論理回路なので伝達遅延を持っています。LUT=ディレイと考えれば、指定段数のリングバッファオシレータを作れそうです。
 この記事を執筆中、たまたま見たXilinxのアプリケーションノートに同じ構成のディレイ回路が見つかった。DCOとしての使用はどうだか分からないが、LUTを期待されたディレイラインとして使う事はあながち間違った考え方ではないらしい

 さて、FPGAに実装するにあたってはいくつか問題がいくつかあります。順番に解決していいきます。

 まず最初に、FPGAは多入力データセレクタが苦手ということです。
 上図の回路構成ではデータセレクタはディレイループの一環であり、一定のディレイを持つことが必要ですが多入力のデータセレクタの場合、FPGAでは多段化されたMUXやLUTで構成されてしまい、設定値ごとに一定のディレイを持つことを期待できません。
 また、入力信号のどれか一つは常に必ず変化している状態で、グリッジノイズ等の要因で正常動作しないかもしれません。
 そこで、FPGAに適した構成で回路を構築します。

 この回路では、各ディレイをマルチプレクサで構成して、それらを個別のスイッチで切り替えています。
 各ディレイは前段ディレイ出力と、バイパス入力のどちらかを入力することが出来ます。最終段をバイパス入力にすると最短ループ、すべてをディレイ出力に繋ぐと最長ループとなり、設定値でディレイ段数を変更できます。
 ついでにインバーターもMUXで構成してしまいます。これなら3入力1出力のLUTの1種類さえ安定できれば、段数がいくつ増えてもクリティカルなループ内を安定化できます。

 次に選択信号の更新タイミングです。
 信号変化中にディレイラインを切り替えてしまうと不正発振を生み出します。
 そこでスイッチを持たない固定ディレイを数段通して、信号変化が固定ラインを通過中にスイッチの切り替えを行うようにします。
 固定ディレイ通過中であっても、選択信号の変化で可変ディレイ内の信号が変化すると不正発振を生み出します。バイパスされている未使用ディレイラインは、全てバイパス側へスイッチしておきます。
 今回の実験では省略しましたが、ディレイラインは起動時にリセットを行ったほうが安全です。外来ノイズ等でディレイラインが不安定な状態になると、不安定な状態を永遠にループすることになります。
初段インバーターの入力信号のどちらか1つを反転させると、ディレイラインの信号が0か1に固定さ初期化されます。

 最後の大きな問題は、論理合成ツールの自動最適化です。
 FPGAは同期回路を前提としているので、論理合成ツールは遅延が少さく回路が小さくなるようにロジックの最適化を行います。
 各段のディレイラインは論理的に同意なので、この最適化によって一部が消滅してしまうことがあります。
 Xilinx WebPack 7.1iではLUT3ROM16Sの専用プリミティブで記述した場合、三段のディレイラインを1つのLUTに纏められてしまいました。
 最適化のオプション設定を探しましたが、抑制出来たのはシンセサイズ時の最適化だけで、インプリメント時の最適化を抑制するスイッチは見つかりませんでした。
 そこで、プリミティブにRAM16X1Sを使用しました。LUTのロジックが書き換わる可能性があればそこは最適化しようがありません。RAM32Sに任意の初期値を埋め込んでおけばマルチプレクサとして機能します。
 評価デザインでは書き込みクロックを0に固定しています。ISEのバージョンによっては最適化の対象になるかもしれませんので、ディレイラインが物理配置されたかどうかは必ず確認します。Xilinx ISEなら

 からFloorplannerを起動して、ディレイラインのプリミティブを選択します。

 今回のディレイラインは固定8段+可変15段(16段階)の設計です。画面右側がFPGAの内部配置図で実際に23個のLUTが割り当てられていることが確認できます。

 以下、FPGAでフィードバック制御可能なDCOを構成するための要件です。

・各ディレイラインは物理的にLUTに配置して、それぞれが一定の遅延時間を持つこと
・ディレイライン間の配線遅延は、ディレイラインそのものの遅延時間より十分小さいこと
・ディレイラインの2つのMUXの入力に対する出力遅延の差が、配線遅延より十分小さいこと
・周波数の高低が、設定値の順番通りに順序よく変化すること
・発振周波数のジッタ(ゆらぎ)によって、隣接する設定値の周波数を超えないこと

DCOの実験

 さて、机上の空論はこのへんにしておいて実機による実験をします。
 こういったたぐいの実験は設計値やシミュレーターの結果では予測できません。
 実験にはSpartan3StarterKitを使いました。ここからデザインをダウンロードできるのでキットをお持ちの方は実際に試してみることが出来ます。
 このデザインには、PLLによるフィードバック制御回路も既に含まれています。詳しい説明はソース内のコメントを参照してください。

Spartan3StarterKitのスイッチを全てOFFにして電源を入れ、実験デザインをコンフィグレーションします。
この状態で、7セグメントLEDには無安定のDCO発振周波数がMHz単位で表示されるようにしてあります。


 とりあえず動いている様子です。外部クロックを使わずに、Spartan3内部から26.58MHzのクロックが発生しています。
 次は、このDCOの特性を実測して、フィードバック制御可能かどうかを検証します。

−−−現在、記事はここで終了しています。−−−
ご意見、ご感想がありましららこちらの掲示板へお願いします。反響が多ければ続きを急ぎます。