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の使い方
    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
Last-modified: 2019-08-29 (木) 00:03:48