2019年10月20日日曜日

IOEのFast Input/Output Registerを活用しよう

MAX10 FPGAの評価ボード(EK-10M50F484)を用いて、HDMI信号を出力する際に数日間嵌まったので忘れないようにここに書いておく。

■嵌まった内容
FPGAボード上に搭載されているHDMIトランスミッタPHY(アナデバADV7513。以下PHYと呼ぶ)から、Full-HD 60fpsの信号を出力している際に、稀に同期信号が外れて映像が乱れる or 映らなくなる現象が発生した。FPGA内部のビデオ信号/同期信号以外のモジュールを修正した場合や、ドライヤーでFPGAパッケージ温度を上昇させることでも現象が発生することもあり、非常に悩まされた。
発生当初、タイミング系のトラブルだろうな・・・?とは予想していたが、Fmax値は満足しており、タイミング制約の書き方が誤っているのではないだろうか??と疑いを掛けて何度もSDCファイルを書き換えては再合成を繰り返していた。
SDCファイルを何度か書き換えて試行錯誤していると、一時期安定動作することもあったが、周辺回路を追加していくことで映像が乱れる現象が再発し、ますますワケガワカラナイ状態だった・・・。

■PHY < = > FPGA間の信号観測(失敗)
映像が乱れる原因として、PHYのタイミング制約を満たしていないのでは・・・?という疑問が湧いてきた。
気になったので、オシロスコープで信号を見てみることにした。
以下の画像が測定した波形だ。
オシロでPHY信号を測定(CH1:CLK / CH2:Video Data)

う~む・・・分からん。
オシロの水平軸は目一杯拡大しているが、5ns/divが限界。また、このオシロのアナログ帯域は100MHz、サンプリング速度は500MS/s(2ch時)である。観測したい信号のクロック周波数はFull-HD 60fpsのピクセルクロック ≒ 150MHzなので、帯域/サンプリング速度ともに不足している。また、PHY信号線にプローブを接続すると、プローブの入力容量により信号が劣化し、全く映像が出なくなってしまった。
手持ちの測定器による評価は無理だと分かった。。😨

参考までに使用したプローブのスペックを以下に示す。RIGOLのRP2200というパッシブプローブだ。
RP2200のスペック

x10で使用したときの帯域は150MHz、上昇時間2.3ns、入力容量は標準で17pFだ。
プローブを接続することで映像が出なくなった原因は、プローブの入力容量による信号レベルの低下や歪が考えられる。17pFの容量は、150MHz信号に対して約62Ωのインピーダンスとなり、ドライブする側(FPGA)の負担となる。

■Quartus Timing Analyzerでの解析
オシロスコープによるタイミング測定が失敗に終わったので、Quartus Primeに付属のTiming Analyzerを使用してPHYの駆動タイミングを検証してみた。
Quartus上のTools => Timing Analyzer => Custom Reports => Report Path...
で対象の信号を選択する。

Report Pathボタンを押すと内部レジスタからポートまでの遅延時間が解析される。
内部レジスタからポートまでの遅延時間解析結果

ここで解析された時間をブロック図に書き込んだのが以下の図になる。
FPGAとPHYの接続と遅延時間の関係

PHYのビデオデータセットアップタイム(min)は1.8ns、ホールドタイム(min)は1.3nsとなっている。FPGAからPHYまでの配線は、目視によるボード確認でミアンダ配線となっており等長と予想される。PWB上のCLKとデータの伝搬遅延がほぼ同じになれば、CLKを基準としてデータをサンプリングするPHYにとっては配線長を考慮する必要が無くなる。そうなると、CLKの遅延時間4.584nsに対して最も近いDE(Data Enable)の遅延時間5.407nsの両者でホールドタイムが満たせていないことになる。
 セットアップタイムは 6.666 - (5.407 - 4.584) = 5.843ns (min 1.8ns OK)
 ホールドタイムは 5.407 - 4.584 = 0.823ns (min 1.3ns NG)
と計算できる。
セットアップタイム/ホールドタイムの計算

SDCファイルを何度か書き換えて試行錯誤していると稀に上手く動いていたのは、たまたま出力レジスタとポート間の遅延時間がこれらセットアップ/ホールドタイムの制約を満たす位置に配置されたためと想定される。CLKはFFを介さずに出力ポートへ接続されるため、何度かコンパイルを行っても同じ遅延時間(4.584ns)となっていた。

FPGAに回路を追加したり、SDCファイルを少し変えただけで信号遅延時間がコロコロ変わるのは非常に扱いづらい。そこで、本題のIOEに内蔵されたレジスタが活躍する。これはFPGAの各I/Oピンの直近に固定配置されたレジスタで、出力用/入力用/OutputEnable制御用の3つがある。今回はOutput Registerを使用する。
MAX10 IOEの構造図

IOEのOutput Registerの使い方はとっても簡単だ。
・・・とその前に、Output Registerを使用するためには、最終段のFFからFPGAの出力ポートの間に組み合わせ回路を入れてはならないという制約事項がある。上のブロック図からも明白なように、Output Registerから出力ポートまでに組み合わせ回路を入れられる構造を持たないからだ。また、この制約のおかげで遅延時間が最小かつ固定にできているとも言える。
今回、PHYへの信号はすべてFF出しとなっているため、この制約をクリアする。
PHY制御信号生成部のRTL Viewer抜粋

まず、プロジェクトの解析と論理合成フェーズまでを完了しておく。
次にQuartusツールバーのAssignments => Assignments Editorを起動する。
Toの<<new>>を選択し、Node FinderからOutput Registerを使用したいポート名を入れて検索する。
Node Finderで対象の信号を追加

信号を右側のNodes Foundに追加したあと、OKを押すと以下のようにAssignments Editorに追加される。
Assignments Editorに追加された様子

次に、黄色くなっているAssignment Nameに”Fast Output Register"を選択し、Valueを"on"にする。一行設定できれば、複数の行を選択してCtrl + C, Ctrl + Vで一括で設定できる。設定が完了すると、Status欄にチェックマークがつく。
Status欄にチェックが付けばOKだ

ここまでできたら、フルコンパイルを実行して、制約内容を配置配線に反映させる。
以上でIOEのOutput Registerを使用する設定は完了だ。
なお、今回は出力ポートを指定したが、RTLのレジスタ名を指定して制約を掛けることもできる。

コンパイルが完了したら、再びTiming Analyzerを起動して、遅延時間を確認してみよう。OutputRegisterに割り当てられたことで、CLKを除く各信号の遅延時間が2.345~2.386nsに収まっている。出力ポートまでの遅延時間が短くなっていることに加えて、信号間のばらつきが小さくなっていることにも注目したい。(From:6.662 - 5.407 = 1.255ns、To:2.386 - 2.345 = 0.041ns)
内部レジスタからポートまでの遅延時間解析結果(Output Register使用後)

FPGAから出力されるバス信号の出力遅延が揃うことで、タイミングマージンを確保しやすくなり、等長配線の効果も発揮される。

ここで再びPHYのタイミング制約を満たしているか確認してみよう。
クロックのほうがデータよりも遅延時間が長くなったため、以下のように算出できる。
 セットアップタイムは 4.584 - 2.386 = 2.198ns (min 1.8ns OK)
 ホールドタイムは 6.666 - 2.198 = 4.468ns (min 1.3ns OK)
今度はホールドタイムのほうがマージンが大きい結果となった。
セットアップタイム/ホールドタイムの計算

これで、PHYのタイミング制約を満たすことができた。実際の評価ボードでも、安定した映像出力を確認できた。

更にマージンを確保するためには、位相差を微調整した2出力のPLLクロックにて、CLK信号とデータ信号を生成する方法が考えられる。今回は使用しなかったが、今後タイミング関連で嵌ったときには試してみたい。

それでは楽しいFPGAライフを!

■参考資料
https://www.intel.co.jp/content/dam/altera-www/global/ja_JP/pdfs/literature/hb/max-10/ug_m10_gpio_j.pdf
https://timetoexplore.net/blog/video-timings-vga-720p-1080p
https://www.analog.com/jp/products/adv7513.html


0 件のコメント:

コメントを投稿