OpenCoresに登録したwf3dをZedBoardとDE0-Nano-SoCに移植しました。wf3dの外部インターフェースはデフォルトでWISHBONEバスなのですが、ZedBoardやDE0-Nano-SoCに搭載されているFPGAでは、インターコネクトとしてAXIが使用されています。このため、非常に簡単なAXIのブリッジモジュールを仮作成してwf3dを組込みました。しかし、実機で動作確認を行うと、どうも様子が変です。
所々、ポリゴンが正常に処理されていません。しかし、フリーズはしません。基本的な設計に問題があるとすると、すぐにフリーズしてしまうはずなのですが。Verilogシミュレーションでは問題ないので、シミュレーション・モデルでは省略している実機の振る舞いに原因がありそうです。
AXIの4KBルール
ロジック・アナライザでデバックを行うと、頂点データについて、期待通りの値がAXIからリードできていないことがわかりました。ここで、4KBルールをまだ実装していなかったことを思い出しました。AXIの仕様書には、次のような記載があります。
A burst must not cross a 4KB address boundary.
ルール自体は非常にシンプルです。別の言い方をすれば、「AXIのバースト中に、バーストの最初と最後のアドレスのビット[31:12]が変化してはいけない」ということです。
このルールは、AXIのアクセスが、ある前提を満たしていれば気にする必要がありません。例えば、 DMAを行うモジュールについて、
- DMAの先頭アドレスは、必ず4KBの境界になっている
- バーストは、先頭アドレスからリニアにアクセスする。また、バースト長は、偶数のバースト長(例えば16)で固定
このような前提がある場合、AXIのバーストが4KBのアドレス境界をまたぐことはありません。
例えば、キャッシュを内蔵したIPコアの場合、通常はキャッシュ・ライン単位でバーストを行うので、このような前提が成り立ちます。また、LCDコントローラなども、一般的にはこのような前提が成り立ちます。
wf3dの頂点リードのバースト長は3
しかし、wf3dはこのような設計上の前提が当てはまりません。wf3dの頂点データのリードは少し変則的です。
- AXIのデータ・バス幅は64ビット
- リード時のバースト長は2で固定。ただし、連続する2つのバーストは最後のアドレスがオーバーラップする
AXIのバースト長は2で固定なのですが、場合によっては4KBの境界をまたいでしまいます。
wf3dがこのような変則的なアクセスを行うのは、処理パフォーマンスよりも小回路規模を優先したためです。
AXIブリッジの修正
原因がわかれば、AXIブリッジの修正は簡単です。AXIのアクセスを4KB境界で分割するだけです。具体的には、
- AXIブリッジは、アクセスが発生すると、その開始アドレスとバースト長からバーストの終了アドレスを計算する
- 開始アドレスと終了アドレスのビット[31:12]を比較する(実際にはビット[12]だけ)
- 比較結果が一致であれば、そのままAXIをアクセスする
- 比較結果が不一致であれば、そのAXIアクセスを4KB境界で2分割する
修正前後の動作比較
まず修正前の動作です。
AXIブリッジの修正で、正常な動作を確認できました。
まとめ
4KBルールをうっかり忘れているとデバッグが大変。