FC2カウンター FPGAの部屋 DQSをクロックとしてDQをリードするDDR2 SDRAMコントローラのOSERDES使用法
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

DQSをクロックとしてDQをリードするDDR2 SDRAMコントローラのOSERDES使用法

(2008/07/29 間違いを修正しました)

DQSをクロックとしてDQをリードするDDR2 SDRAMコントローラのOSEDES使用法を書いておこうと思う。
大体できてきたOSERDESを使用したDQとDQS, DQSNを見てみる。
OSERDES_DDR2_1_080726.png
上の図では3回WRITEコマンドが発行されている。1クロック置きにddr2_rasb='1', ddr2_casb='0', ddr2_web='0' の時がWRITEコマンドだ。
黒いカーソルで発行されたWRITEコマンドの最初のWRITEするデータが赤のコマンドのところになる。本当はddr2_dqs は赤のカーソルの前1クロック分0になって、赤のカーソルのところで1になるはずだが、半クロック分の0が2つあるように見える。これは0と0の間に 0 ps のZが挟まっている。デルタ遅延でZになっているのだろか?
とりあえず実用的には問題ないものと思われる。

ところで、以前のタイミングチャートとの違いに気がついている方もいらっしゃると思うのだが、今回のタイミングチャートは以前のよりも1/4クロック前にずれている。
マイクロン社DDR2 SDRAM (HT47H) データシートの88ページにある。Figure 56 : WRITE Burst を下に引用する。
OSERDES_DDR2_2_080726.png
上図でWLはWrite Latency でWriteコマンドを発行してから DDR2 SDRAMにデータが書き込まれるまでの時間を表している。 WL = AL (Posted CAS Additive Latency) + CL (CAS Latency) - 1 = 0 + 3 -1 = 2 クロック。
tDQSS は DQS rising edge to CK rising edge で MIN = –0.25 × tCK, MAX = +0.25 × tCK だ。つまりWrite時のDQSの立ち上がりエッジがWLの–0.25 × tCK から +0.25 × tCK の間にあれば良いことになる。
上図ではそのタイミングのうちのNOM、MIN、MAX (MIN~MAX) のタイミングを紹介している。今までのDDRやDDR2 SDRAMコントローラではデータをCLK位相0度で出したかったので、MAXのタイミングを使用していた。今回はtDQSSをNOMにすることにした。理由は特にないのだが、NOMの方がtDQSSのタイミングの真ん中なのでちょうど良いのかな?と思ったのだ。それでこの機会に修正した。

DQの部分のOSERDES, ISERDESのところのVerilogコードを下に示す。

    // ddr2_dqのIOBをプリミティブでインスタンシエーション
    generate
    genvar i;
        for (i=DDR2_DATA_WIDTH-1; i>=0; i=i-1) begin: WRDATA_INOUT
            OSERDES # (
                .DATA_RATE_OQ("DDR"),
                .DATA_RATE_TQ("DDR"),
                .DATA_WIDTH(4),
                .INIT_OQ(1'b0),
                .INIT_TQ(1'b1),
                .SERDES_MODE("MASTER"),
                .SRVAL_OQ(1'b0),
                .SRVAL_TQ(1'b1),
                .TRISTATE_WIDTH(4)
            ) WRDATA_DDR2_OUT (
                .OQ(ddr2_out[i]),
                .SHIFTOUT1(),
                .SHIFTOUT2(),
                .TQ(out_tri[i]),
                .CLK(clk270),
                .CLKDIV(~clk100MHz),
                .D1(wrdata_3d[i]),
                .D2(wrdata_3d[i+16]),
                .D3(wrdata_2d[i]),
                .D4(wrdata_2d[i+16]),
                .D5(),
                .D6(),
                .OCE(1'b1),
                .REV(1'b0),
                .SHIFTIN1(1'b0),
                .SHIFTIN2(1'b0),
                .SR(reset),
                .T1(dq_oserdes_t_2d[i*4]),
                .T2(dq_oserdes_t_2d[i*4+1]),
                .T3(dq_oserdes_t_2d[i*4+2]),
                .T4(dq_oserdes_t_2d[i*4+3]),
                .TCE(1'b1)
            );
                        
             ISERDES #(
                .BITSLIP_ENABLE("FALSE"),
                .DATA_RATE("DDR"),
                .DATA_WIDTH(4),
                .INTERFACE_TYPE("MEMORY"),
                .IOBDELAY("IFD"),
                .IOBDELAY_TYPE("FIXED"),
                .IOBDELAY_VALUE(0),
                .NUM_CE(1),
                .SERDES_MODE("MASTER")
            ) DDR2_DQ_INPUT (
                 .O(),
                 .Q1(dq_fall_1d[i]), 
                 .Q2(dq_rise_1d[i]), 
                 .Q3(), 
                 .Q4(), 
                 .Q5(), 
                 .Q6(), 
                 .SHIFTOUT1(), 
                 .SHIFTOUT2(),
                 .BITSLIP(1'b0),
                 .CE1(1'b1), 
                 .CE2(1'b1),
                 .CLK(ddr2_dqsin_bufio[i/8]),
                 .CLKDIV(clk270),
                 .D(ddr2_dq_in[i]),
                 .DLYCE(1'b0),
                 .DLYINC(1'b0),
                 .DLYRST(1'b0),
                 .OCLK(clk270), 
                 .REV(1'b0),  
                 .SHIFTIN1(1'b0), 
                 .SHIFTIN2(1'b0),
                 .SR(reset)
              );
             
            IOBUF DDD2_DQ_BUF (
                .O(ddr2_dq_in[i]),
                .IO(ddr2_dq[i]),
                .I(ddr2_out[i]),
                .T(out_tri[i])
            );
        end
    endgenerate


OSERDESのCLKにはclk270 (クロックの位相が270度の200MHzクロック)、CLKDIVには~clk100MHz (100MHzクロックの反転)が入っている。D1からD4には4つデータを用意する必要があるため、D1には3クロック分遅れたデータの下16ビット(1個のOSERDESは1ビットなので、generateで16ビット分生成されている)、D2には3クロック分遅れたデータの上16ビット、D3には2クロック分遅れたデータの下16ビット、D4には2クロック分遅れたデータの上16ビットが入っている。
これのタイミングチャートを下に示す。
OSERDES_DDR2_3_080726.png
黒カーソル位置で100MHzクロック (clk100MHz) の立下りでwrdata_3dとwrdata_2d がサンプルされる。そのサンプルされたデータは、赤カーソル位置のclk270の立ち上がりでD1のデータから順に出力された (out_tri 信号)。

後はMASKの実装が残っているので、それをテストしたら、ISERDESのタイミングの調整に移る。

(2008/07/29追加)
Xilinx社のアプリケーションノートXAPP721J、”ISERDES とOSERDESを使用した高性能DDR2 SDRAMインターフェイスのデー タキャプチャ”の3ページの図3を引用する。
OSERDES_DDR2_4_080726.png
私の回路では図3のCLKDIVに~clk100MHzが、CLKにclk270 が入っている。そうするとCLKDIVでサンプルしたデータは次のclk270 でDQに出力されるはずなので、あっていると思う。
  1. 2008年07月27日 06:52 |
  2. DDR SDRAMコントローラ
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/844-5a5253a2
この記事にトラックバックする(FC2ブログユーザー)