はじめに
このページでは、ソース同期データ入力 (source-synchronous data inputs) について説明します。この手法は、データ入力が、外部部品がこれらの入力と並行して生成するクロックに同期している、というものです。
この方法は、外部部品がそういう動作をするから、という単純な理由で使われることがよくあります。もう 1 つの良い理由は、データの供給元が FPGA から物理的に遠く離れていることです。FPGA と相手側の間にケーブルとコネクタがある場合もあります。例えば、ピクセルデータを送るデジタルカメラなどです。
ソース同期クロック (source-synchronous clock) には、常に動作しているとは限らない、という潜在的な難点があります。クロック信号は、接触不良の物理的接続や過度のノイズの影響を受けることもあります。また、クロックの周期が安定していないことや、ジッタ (jitter) が過度に大きいこともあり得ます。これは、データ(したがってクロックも)の供給元がマイクロプロセッサの I/O ペリフェラルである場合によく起こります。
なお、クロックとデータの関係全般については、別ページで説明しています。
不安定なクロックへの対処
ソース同期入力でもっとも重要な指針は、外部から来るクロックを FPGA 内部の論理要素に直接接続すべきではない、ということです。むしろ、FPGA 内部で使うクロックは、FPGA 内の PLL が生成するクリーンなクロックであるべきです。
外部クロックを FPGA 内部のロジックに直接接続すると、不可解な問題が発生する可能性があります。不良なクロックは、クロックの問題には見えない予期しない動作を引き起こします。過度のジッタ (jitter) やグリッチは、設計の信頼性のある動作を保証するタイミング要件に違反する可能性があります。その結果、Verilog コードに照らせばあり得ない状況を含め、実質的に何でも起こり得ます。したがって、問題を FPGA 設計のバグだと誤解しがちです。
クロックの問題は、クロックサイクルが失われるだけで、その結果いくつかのデータ要素が欠落するだけ、と(誤って)考えるのは自然なことです。不良なクロックが他の問題を引き起こしている場合、その問題を解決しようとする試みは、ロジック設計の中で特に関係しそうな部分に集中しがちです。これにより、多くの時間を無駄にする可能性があります。
外部クロックをロジックファブリックが直接使ってもよい唯一の状況は、そのクロックが安定かつクリーンであることが保証されている場合です。FPGA が動作を開始した時点でこのクロックが安定していない場合は、この問題への対処が必要です。クロックが不安定な間は、このクロックに依存するロジックにリセットをかけなければなりません。
考えられる戦略
外部クロックに同期する方法としては、主に 4 つの戦略があります。以下では、これらの戦略を順不同で説明します。
戦略 #1: 01 信号サンプリング
この戦略は、ソース同期入力に対して最も堅牢な方法です。外部クロックが誤動作している場合、01 信号サンプリング (01-signal sampling) は他のどの方法よりも明確な利点を持ちます。ただし、この方法が有効なのは、データソースのクロック周波数が比較的低い場合に限られます。
この方法については、専用ページで別途説明しています。
戦略 #2: PLL を使用する
この戦略では、外部クロックを FPGA 上の PLL の入力に接続します。PLL の出力クロックが論理要素に使われます。PLL がロックしていない間は、これらの論理要素にリセット信号が加えられます。この方法により、論理要素が安定したクロックに依存することが保証されます。PLL の出力クロックが安定しないときは、リセットによって論理要素が無効化されるからです。
また PLL を使うと、外部クロックを直接接続する場合と比べて、タイミング制約 (timing constraints) を達成しやすくなります。PLL がクロックピンと FPGA 内部クロックの間の遅延を補正するからです。
ただし、外部クロックの不完全さが PLL の出力に過度のジッタ (jitter) を引き起こす可能性があることに注意してください。PLL が生成するクロックが異常にノイジーであっても、PLL のロック検出器は PLL が正常に動作していると示し続けることがあります。この状況に対する簡単な解決策はありません。1 つの可能性は、PLL の出力に依存するロジックの タイミング制約を変更することです。例えば、タイミング制約におけるクロックのジッタを、PLL では(ロックが外れるため)おそらく超えないであろう値に増やすことができます。
この戦略には、システム同期クロック (system synchronous clock)との類似点があります。どちらのシナリオでも外部クロックが PLL に接続され、この PLL の出力が FPGA 内部で使われます。したがって、タイミング制約も システム同期クロックの場合と同じように書きます。
なお、PLL は通常、その出力クロックを システム同期クロックにとって最適な形で外部クロックに合わせます。ソース同期クロック (source synchronous clock) にとっての最適な位置合わせは、少し異なるかもしれません。どちらの場合でも、クロックは完全には一致しません。むしろ、クロックエッジの間には意図的なわずかな時間差があります。この時間差により、I/O レジスタのタイミング要件を満たしやすくなります。一部の PLL は、ソース同期クロックに対して最適な性能になるようクロックを位置合わせするように設定できます。
この戦略は、ここに挙げた他の戦略と比べると、実装が最も簡単です。比較的高いクロック周波数に適しています。しかし、I/O の限界に近い周波数では、この戦略はおそらく機能しないでしょう。
戦略 #3: 位相シフト
この戦略は、データレートが FPGA がサポートできる最大値に近い場合に、通常選ばれます。
このようなデータレートでは、タイミング要件を保証する通常の方法は機能しません。タイミング制約 (timing constraints) を達成することは不可能になるでしょう。しかし、データ信号の信頼できるサンプリング (sampling) は依然として可能です。
タイミング制約の問題は、タイミング要件を計算によって保証しようとするところにあります。そのような計算には、FPGA の製造ばらつきなど、いくつかの不確かなパラメータが含まれます。これらのパラメータを考慮すると、計算は信頼できるサンプリングを保証するタイミング解を導き出しません。データレートが非常に高い場合、これらの不確実性に費やすタイミング余裕はありません。
しかし、特定の FPGA チップにとって、これらのパラメータは一定です。したがって、解決策は、FPGA が動作している間に正しいタイミングを探索することです。実際には、FPGA 内部のステートマシン (state machine) が、データクロックとサンプリング時点の間の遅延を調整する、ということを意味します。つまり、計算に頼るのではなく、適応的なメカニズムを使って最適なタイミングを見つけるのです。このメカニズムは 位相シフト (phase shifting) と呼ばれます。
この戦略は、DDR SDRAM メモリからのデータ信号でよく使われます。この用途では、常に可能な限り高いデータレートを達成することが目標です。したがって、I/O ポートの性能は限界まで引き出されます。そのため、データ入力が確実にサンプリングされることを保証する唯一の方法が位相シフトになります。DDR メモリの初期化が終わったら、特別なデータ列がメモリに書き込まれます(メモリへのデータ信号は ソース同期出力なので、タイミングに困難はありません)。その後 FPGA は DDR メモリ内の同じ領域を繰り返し読み出します。ステートマシンがサンプリングの遅延を徐々に変えながら、最適なタイミングを見つけます。期待される入力データは、以前に書き込んだものと同じデータ列なので既知です。したがって、ステートマシンはデータがどの程度信頼できるかを容易に評価でき、最適な遅延を見つけることができます。
このメカニズムの興味深い特徴は、DDR チップが供給するデータクロックを無視できることです。DDR メモリは FPGA が生成するクロックに同期します。このクロックは、DDR メモリが受け取る ソース同期出力の一部です。したがって、ソース同期入力のデータクロックは、FPGA が生成するクロックと正確に同じ周波数であることが保証されます。そのため、位相シフトのメカニズムは、データと一緒に届くクロックの代わりに内部クロックに頼ることができます。これら 2 つのクロックの間に未知の遅延があっても問題ありません。ステートマシンはその遅延に関係なく最適なタイミングを見つけるからです。
実際、DDR メモリでは、このメカニズムは通常このように実装されます。DDR メモリにはソース同期クロック(データストローブ (data strobe) と呼ばれます)がありますが、位相シフトメカニズムの通常の実装ではこの信号を無視します。その論拠は、データ信号がストローブに位置合わせされていることよりも、確実に届くことのほうが重要だからです。
したがって、位相シフトを使えば、データクロックが不要になります。内部クロックの周波数がデータレートと正確に同じであることが保証されていれば、その内部クロックを代わりに頼ることができます。
この戦略におけるタイミング制約の目的は、通常の IOB レジスタの場合と同じです。
戦略 #4: クロックを直接使う
この戦略は、一見すると最も単純です。外部クロックを FPGA 内部のフリップフロップに直接接続します。例えば次のようにします。
module top (
input data_clk,
input [7:0] data
);
reg [7:0] data_samp;
always @(posedge data_clk)
begin
data_samp <= data;
[ ... ]
end
上で述べたように、この戦略は通常良い考えではありません。主な理由は、@data_clk にグリッチが発生すると、このクロックに依存するすべてのロジックが予測不能になるからです。
外部クロックがクリーンで安定していることが保証されていれば、このように使うことも合理的であり得ます。しかし、それが保証されていても、クロックピンとフリップフロップの間の遅延のために、タイミング要件を達成するのが難しい場合があります。一部の FPGA には、この遅延を減らすための専用クロックリソースがあります。その場合、専用のクロック入力ピンを使い、I/O ポートを FPGA 上の特定の領域に制限することが必要になるかもしれません。
クロックを直接使う場合、タイミング制約は システム同期クロックと同じように書きます。
この戦略に代わる単純な方法は、上で提案したように PLL を使うことです。データクロックが安定しない場合は、01 信号サンプリング (01-signal sampling) を検討すべきです。
まとめ
01 信号サンプリングがこのページの最初に挙げられ、この戦略が別ページで説明されているのは偶然ではありません。この方法は、データレートがこの方法が対応可能な範囲を超えていない場合に、もっとも推奨される方法だからです。
他の戦略を検討する場合は、データクロックの安定性に注意を払うことが重要です。クロックが許容される動作(つまりクロック周期と最大ジッタ (jitter))から逸脱すると、関連するロジックが恒久的かつ回復不能な誤動作を起こす可能性があります。ロジックを通常の動作に戻すことができるのはリセットだけです。
PLL を使って信頼できるクロックを生成すれば、状況は大幅に改善されます。PLL の出力は、そのロック検出器がそう示している限り信頼できます。そうでない場合、このロジックにリセットを適用すべきです。
