Spartan-6LXTの内蔵PCIe EndPointの使い方を理解した
ついに、Spartan-6LXTの内蔵PCIe EndPointの使い方を理解しました。
うーん、なんていうか非常に複雑で面倒です。
内蔵EndPointは、TLPの組み立てや解読を行うために、ユーザが自分でステートマシンや上位の回路(ソフトウェア層)を作らなければなりません。
確かに、CoreGenで内蔵EndPointのラッパを作ると簡単なサンプルデザインが自動で作られます。XILINXのSP605に付属しているサンプルデザインも基本的にはそれです。このサンプルはメモリ空間の読み書きができるので、一見すると良さそうなのですが、実はそのサンプルデザインには、「1DWのデータ転送しかサポートしていない」という制限があります。
これはかなり重大な問題で、ルートコンプレックス(パソコン)は4バイトを超えるメモリ・リード/ライトのリクエストを発行できないのです。つまり、LONGサイズでしかアクセスできませんから、転送速度は上りも下りも1~2MBytes/sec程度になってしまいます。もし、2DW以上のリードリクエストを発行したら、EndPoingは応答を返さないので、タイムアウトしてしまいます。(パソコンが一瞬固まります)
内蔵EndPointを使ったデザインを作るには、やはりCoreGenの自動生成サンプルではなく、一から作り直さなければなりません。
そこで、今まで作ってきた特電PCIe互換コアを使います。特電PCIe互換コアは、DMA転送や割り込みまでサポートしていて、それなりに高機能で、すぐに使えます。この互換コアは独自のデータリンク層や物理層回路をもっています。
一方、内蔵EndPointは、PCI Expressの規格への準拠や信頼性は優れています。(コンプライアンステストに通っているのですから)。そのため。特電PCIe互換コアのデータリンク層以下をSpartan-6LXT内蔵EndPointに置き換えれば、高機能と高信頼性が両立できるはずです。
今日は、内蔵EndPointの使い方を解明するとともに、そういう移植を行っていました。
少し苦労しましたが、できました。
下の図は、2DWのメモリ・リード・リクエストを受け取ったときの挙動です。
「00000002 000016FF FCFF6808」というのがメモリ・リード・リクエストのTLPです。
それに対して
「4A000002 02000008 00001608 F43D85EE 8526871B」というコンプリーションを返しています。
最後の2DWのF43D85EE 8526871Bというのが応答したパケットに含まれるデータです。
このように、2DWのコンプリーションも返せます。
また、ルートコンプレックスからCombied Writeで送られてきた16DWのデータの塊も、問題なく受け入れられています。
このような感じで、長いデータ転送ができるようになったので、FPGA内に64kバイトのメモリを実装し、メモリ空間の読み書きテストを行いました。
エラーなく転送できていることが確かめられ、Writeは約120MBytes、Readは約1.8MBytesという結果が出ました。Readが遅いのはPIOモードであるためです。
あと2~3日じっくり取り組めば、DMAや割り込みまで移植できそうです。
PCI Expressが自由自在に使えるようになるまで、あと少しです。
| 固定リンク
コメント