[[ASAP Top]] XGMIIはPMCのチップとのインタフェースを担うインタフェース。 これを使うにはDCMとODDR,ISERDES, OSERDESを活用する必要がある。 ここにはそのヒントを書き残す。 参考ページをまず2つ。 [1] http://www.google.co.jp/url?sa=t&source=web&ct=res&cd=3&ved=0CBEQFjAC&url=http%3A%2F%2Fjapan.xilinx.com%2Fxapp%2Fj_xapp606.pdf&ei=6cUxS8_wLpLq7APq7rWQBg&usg=AFQjCNG0oavN6ZSWHghA4oSCV8EjnZNGUg&sig2=vjTjBv9jmxhgG0HcUOfiyA [2] http://www.google.co.jp/url?sa=t&source=web&ct=res&cd=1&ved=0CAcQFjAA&url=http%3A%2F%2Fwww.xilinx.com%2Fsupport%2Fdocumentation%2Fuser_guides%2Fug070.pdf&ei=eRAyS4D0No_s7AO32KCFBg&usg=AFQjCNFv3i5aW4HYOwg531GIoBBNwwaxsQ&sig2=4kkrOyAwTuSoZl_Pvo3wNA ([2]はI/Oパッドの仕組みとして 322と353ページも必見です) 出力の場合、送信クロックのエッジにデータが乗っている状態を作りたいので、 あらかじめDCMでシステムクロックに対して位相を90度ずらしておくとよい。 -DCMの使い方 1. Core generator で生成する。 生成した.vファイルはそのまま合成にかけられるため、便利。 2. 自分でプリミティブを宣言して使う。 -ODDRの使い方 [2]の356ページ。 クロックの出力に使う。 156Mの信号を90度ずらして、ODDRのクロックに突っ込むとよい。 具体的には次の感じにする。 ODDR #( .DDR_CLK_EDGE("SAME_EDGE"), .INIT(1'd0), // FFの初期値 .SRTYPE("SYNC") // リセットの入力手法、SYNCの方が高い性能が出る ) oddrPrimitive ( .Q( hoge0), // 出力信号 .C( hoge1), // 入力クロック .CE( hoge2), // イネーブル信号 .D1(1'b1), //1! .D2(1'b0), // 0! .R( reset ), // Active High のリセット .S( 1'b0)); // set signal , 基本的には 0 推奨 この出力の方法はプリミティブ名の違いはあれど、他のデバイスでも通用するので覚えておくと便利す。 厳密にはこの後に hoge0 をOBUFプリミティブ(247ページ)に通して出力するのがよい。(けど近年のISEはそこまでしなくても良くなった) -SERDESの使い方 -SERDESの使い方~ Virtex4以降SERDES( Serializer Deserializer)がサポートされたため、 データの送信が以前に比べ楽になっている。 (以前はpararelのデータをいちいちODDR/IDDRを使ってシリアル変換してやる必要があった)~ まずはOSERDESの使い方について書く。 --OSERDES [2]の380ページ以降参照 以下のようにプリミティブを使う。 OSERDES # ( .DATA_RATE_OQ("DDR"), // double clock edge .DATA_RATE_TQ("DDR"), // double clock edge .DATA_WIDTH(4), // データ幅を4に .INIT_OQ(1'd0), // 初期値 .INIT_TQ(1'd0), // TQの初期値 .SERDES_MODE("MASTER"), // もし単一OSERDESでよければこれで .SRVAL_OQ(1'd0), // 謎です。初期値は0らしいが… .SRVAL_TQ(1'd0), // 同じく謎。 .TRISTATE_WIDTH(4) // トライステートバッファへの入力の幅 ) oserdesTest ( .CLK(CLK), // bit 幅4 なら CLK_DIVの2倍の速度でないとダメ .CLKDIV(CLK_DIV), // 基本クロック .D1(dataIn[0]), .D2(dataIn[1]), .D3(dataIn[2]), .D4(dataIn[3]), .D5(1'b0), .D6(1'b0), .OCE(1'b1), // クロックイネーブルずっと動くのが嫌なら制御 .REV(1'b0), // 謎。使わない? .SHIFTIN1(1'b0), // SLAVEモードも合わせて使うなら必要。 .SHIFTIN2(1'b0), // 同上 .SR( ~RST_), // Active High の非同期リセット .TCE(1'b1), // トライステートバッファのイネーブルシグナル .T1(1'b0), .T2(1'b0), .T3(1'b0), .T4(1'b0), .OQ(dataOut), // もし databit が4なら 1CLK_DIV+1CLKで出力 .SHIFTOUT1(), // SLAVEモードも合わせて使うなら必要。 .SHIFTOUT2(), // 同上 .TQ() // もしOBUFにトライステートバッファを使いたいならこれを使う。 ); 基本的に言うことはないす。 一回波形を追ってみるとこの挙動がわかりやすいかなぁと。