Cyclone VでACPのアドレス設定を誤った場合の描画結果

FPGA

Opencores.orgで公開した3DCG IPコアをDE0-Nano-SoCに移植したところ、描画結果が正しく表示されないという現象が発生しました。

描画結果の線が欠ける

描画結果の線が欠ける

ZedBoard版の正しい描画

ZedBoard版の正しい描画

ZedBoard版は問題になく表示されているので、AXIなどの基本的な設計部分に問題はないはずなのですが、DE0-Nano-SoC版は、描画結果の線にランダムなノイズが発生します。なお、DE0-Nano-SoCには表示系のインターフェースが搭載されていないため、DVI出力用にCQ出版社の”DE0&DE0-nano用拡張ボード”を利用しています。

システム構成

AXIの接続

Cyclone V内部に実装したシステム構成は次のようになっています。3DCG IPコアはFPGA部分に格納し、プロセッサを内蔵したHPSとはAXIで接続しています。

AXIの接続

AXIの接続

3DCG IPコアがマスタとなるAXI(HPSがスレーブとなるAXI)は、

  • FPGA-to-HPS Bridge
  • FPGA-to-HPS SDRAM Interface

から選択できますが、今回はACP(Accelerator Coherency Port)を利用できるFPGA-to-HPS Bridgeで接続しています。FPGA-to-HPS Bridgeのデータ・バス幅は64ビットの設定です。Cyclone Vは、プログラマブル・ロジックを内蔵したブロックをFPGAと呼んでいるのが少しややこしいです。

フレーム・バッファのフォーマット

3DCG IPコアのフレーム・バッファのフォーマットは、1ピクセル1バイトです。今回のFPGA-to-HPS Bridgeのデータ・バスは64ビット幅なので、AXIシングル・アクセスに8ピクセル分のデータが格納されます。このため、1ピクセルだけ更新する場合には、AXIのライト・ストローブWSTRBを制御して、必要なバイト部分のみ1を設定します。

描画シーケンス

フレームごとに、クリア処理と描画処理のペアを繰り返すことで、CGを描画しています。

  • CPUがDDR3上のフレーム・バッファをクリアする
  • その後、3DCG IPコアがDDR3上のフレーム・バッファにCGを描画する

ACPを利用する場合、CPUとFPGAでDDR3の同一部分をアクセスする場合のアドレスが異なります。通常、CPUがアクセスする同じ場所をFPGAからアクセスする場合、そのアクセス・アドレスに0x80000000のオフセットが必要です。

HPSとFPGAからのDDR3アクセス

HPSとFPGAからのDDR3アクセス

原因解明

まず疑ったこと

描画結果を見てまず疑ったのは、ACP利用時のAXIライト・ストローブ(バイト・イネーブル)の扱いです。描画結果を見ると、ライト・ストローブの処理が正しく行われていないように見えます。今回のAXIのデータ・バス幅は64ビットなので、1アドレスに8ピクセルを格納できます。このため、通常のCG描画でWSTRBがすべて1(=0xff)になるのは、水平な直線を描画する場合に限られます。そして、CGで水平な直線を描画することは、一般的に稀です。つまり、WSTRBがすべて1になることは、ほとんどありません。そこで、設計を変更し、キャッシュ・システムを内蔵しました。キャッシュ・システムを内蔵することで、あるフレーム・バッファのアドレスにライトを行う場合は、まずそのアドレスのデータを一旦読み出し、キャッシュ・システムで必要なバイト部分だけ書き換えた後で、WSTRB=0xffとして書き戻すことにしました。

本来の設計

本来の設計

変更後のAXIライト・アクセス

変更後のAXIライト・アクセス

キャシュ・システムを導入した結果

しかし、描画結果はまったく変わりませんでした。

axii

描画結果は変わらず

つまり、AXIライトのライト・ストローブが原因ではありませんでした。そうなると、ソフトウェアの設定ミスの可能性が大きくなります。ZedBoard用のシステムは正常に描画されているので、DE0-Nano-SoCに依存したソフトウェア部分に何らかの設定ミスがありそうです。

本当の原因を特定

結局、原因はACPアクセスのアドレス・オフセットの設定ミスでした。一カ所だけ、3DCG IPコア側からフレーム・バッファをアクセスする場合のアドレスに、0x80000000のオフセットを付加するのを忘れていました。

  D3D_COL_ADRS  = fb_front ?FRAME_BUFFER_0 : FRAME_BUFFER_1;
#ifdef __DE0_NANO_SOC__
 D3D_COL_ADRS = fb_front ? FRAME_BUFFER_0| 0x80000000 : //ACP Address
                           FRAME_BUFFER_1| 0x80000000;
#else
 D3D_COL_ADRS = fb_front ?FRAME_BUFFER_0 : FRAME_BUFFER_1;
#endif

修正後、正しく描画されることが確認できました。

アドレス修正後の正しい描画結果

アドレス修正後の正しい描画結果

FPGA(FPGA-to-HPS Bridge)からACP以外の領域(通常領域)をアクセスすると、今回のような意図しないデータ(描画結果)が読めるということですね。。

まとめ

原因は、わかってしまえば非常に単純なACPに関するソフトウェアの設定ミスでしたが、キャシュ・システムを追加するなど、原因の特定に時間がかかってしまいました。また、せっかく内蔵したキャッシュ・システムは、外して元に戻しました。今回の3DCG IPコアは、元々フレーム・バッファのリード・モディファイ・ライトは不要なので、キャッシュ・システムを入れるとDDR3のデータ転送量が増え、描画速度が遅くなってしまいました。

タイトルとURLをコピーしました