[[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にトライステートバッファを使いたいならこれを使う。
		     );

 基本的に言うことはないす。
 一回波形を追ってみるとこの挙動がわかりやすいかなぁと。

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS