FPGAの部屋

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

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。ご利用ください。 http://marsee101.web.fc2.com/index.html

カテゴリ: Virtex4のお勉強

先週、今週はパソコンのリプレース、プロバイダの乗換えなど、いろいろイベントがあってなかなか進まなかったが、DDR2 SDRAMコントローラ関連のOSERDESとISERDESの問題にはまっている。
どうも最後でPlace & Routeで配線できないと言われてエラーになってしまう。
こんな感じ。

ERROR:Route:472 - 
   This design is unrouteable.
   To evaluate the problem please use fpga_editor.
Routing Conflict 1: 
    Net:GLOBAL_LOGIC0 on pin SR on location OLOGIC_X0Y111 
    Net:SYS_RST_IBUF_1 on pin SR on location ILOGIC_X0Y111 
    Conflict detected on wire: PINFEED(-63835,80448)

Routing Conflict 2: 
    Net:GLOBAL_LOGIC0 on pin SR on location OLOGIC_X0Y113 
    Net:SYS_RST_IBUF_1 on pin SR on location ILOGIC_X0Y113 
    Conflict detected on wire: PINFEED(-63835,84320)


どうやらSR(リセット)ピンがOSERDESとISERDESで違っているのがだめなのか?
DQS付近の入出力用ソースはこの辺。

    // Instantiate DQS DDR registers
    generate
    genvar n;
        for (n=DDR2_DQS_DM_WIDTH-1; n>=0; n=n-1) begin: WRDATA_DQS
            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(dqs_oq[n]),
                .SHIFTOUT1(),
                .SHIFTOUT2(),
                .TQ(dqs_tq[n]),
                .CLK(clk),
                .CLKDIV(clk100MHz),
                .D1(dqs_oserdes_d_1d[n*4]),
                .D2(dqs_oserdes_d_1d[n*4+1]),
                .D3(dqs_oserdes_d_1d[n*4+2]),
                .D4(dqs_oserdes_d_1d[n*4+3]),
                .D5(),
                .D6(),
                .OCE(1'b1),
                .REV(1'b0),
                .SHIFTIN1(1'b0),
                .SHIFTIN2(1'b0),
                // .SR(dqs_reset_3d[n]),
                .SR(1'b0),
                .T1(dqs_oserdes_t_1d[n*4]),
                .T2(dqs_oserdes_t_1d[n*4+1]),
                .T3(dqs_oserdes_t_1d[n*4+2]),
                .T4(dqs_oserdes_t_1d[n*4+3]),
                .TCE(1'b1)
            );
            
             ISERDES #(
                .BITSLIP_ENABLE("TRUE"),
                .DATA_RATE("DDR"),
                .DATA_WIDTH(4),
                .INTERFACE_TYPE("NETWORKING"),
                .IOBDELAY("IFD"),
                .IOBDELAY_TYPE("FIXED"),
                .IOBDELAY_VALUE(32),
                .NUM_CE(1),
                .SERDES_MODE("MASTER")
            ) DQS_DDR2_IN (
                 .O(ddr2_dqsin_out[n]),
                 .Q1(), 
                 .Q2(), 
                 .Q3(), 
                 .Q4(), 
                 .Q5(), 
                 .Q6(), 
                 .SHIFTOUT1(), 
                 .SHIFTOUT2(),
                 .BITSLIP(1'b0),
                 .CE1(1'b1), 
                 .CE2(1'b1),
                 .CLK(1'b0),
                 .CLKDIV(1'b0),
                 .D(ddr2_dqsin[n]),
                 .DLYCE(1'b0),
                 .DLYINC(1'b0),
                 .DLYRST(1'b0),
                 .OCLK(1'b0), 
                 .REV(1'b0),  
                 .SHIFTIN1(1'b0), 
                 .SHIFTIN2(1'b0),
                 .SR(reset)
              );
             
             BUFIO DQS_DDR2_IN_BUFIO (
                .I(ddr2_dqsin_out[n]),
                .O(ddr2_dqsin_bufio[n])
            );
            
            IOBUF DDD2_DQS_BUF (
                .O(ddr2_dqsin[n]),
                .IO(ddr2_dqs[n]),
                .I(dqs_oq[n]),
                .T(dqs_tq[n])
            );
        end
    endgenerate


.SR(1'b0) と .SR(reset) の違いがある。これをどちらも .SR(reset) にしてみた。
そうするとやはり、このコンフリクトはなくなったが、まだ後、18個のコンフリクトを解消する必要がある。

次は、下のコンフリクト。

Routing Conflict 1: 
    Net:ddr2_sdram_cont_inst/clk90 on pin CLK on location OLOGIC_X0Y97 
    Net:clk on pin OCLK on location ILOGIC_X0Y97 
    Conflict detected on wire: BOUNCEIN(-63349,57088)


これはDQのclk90 と clk がコンフリクトしているようだ。DQのISERDESのOCLK と CLKDIV は clkネットがつながっていて、OSERDESのCLKには clk270 がつながっていた。どうやら、これらのピンは同じクロックがつながっている必要がありようだ。
事実、XAPP721 ISERDES と OSERDES を使用した高性能DDR2 SDRAM インターフェイスを見ても、ISERDESのOCLK と CLKDIV、OSERDESのCLKには同じ CLKfast_90 がつながっている。やはり、配線がこれしかないのだろう。
これで、Place & Route は通ったが、タイミング制約が満足していない。クロックを変更してしまったので、タイミングダイアグラムをもう一度考察する必要が出てきてしまったし。。。

今日の教訓、OSERDES, ISERDESの決まりごと
1.OSERDESとISERDESのSRには同じリセット信号をつなぐ。
2.ISERDESのOCLK と CLKDIV、OSERDESのCLKには同じクロックを入力する。


注:コンフリクトの方がclk90 なのに、なぜclk270 の話になるのかというと、グローバルバッファを削減するためにclk270 は ~clk90として定義してあるからです。
assign clk270 = ~clk90;

DDR2 SDRAMコントローラを作っていると、DQなどの入出力ピンの入力をISERDESにして、出力をODDRにすると、どうもPlace & Route でルートできないといわれてエラーになってしまう。
Virtex4のIOブロックの詳細回路図がないのかと思って探したのだが、良くわからなかった。そこでISERDESにはOSERDESを使っておけば問題ないだろうということで、OSERDESを使うことにした。でもOSERDESも内部構造がなぞである。Virtex4 FPGAユーザーズガイド(英語版)ににも載っていないし。。。
でもありました。Xilinx社のアプリケーションノート、XAPP721 ISERDES と OSERDES を使用した高性能DDR2 SDRAM インターフェイスにOSREDESの内部回路が載っていた。説明が少なくてなぞの端子があるが、大体このアプリケーションノートを見るとわかった。でも、もっともっとユーザーズマニュアルに詳しく書いて欲しいと思った。
下にXilinx社のアプリケーションノート、XAPP721 ISERDES と OSERDES を使用した高性能DDR2 SDRAM インターフェイスの3ページより転載します。
cfc34852.png


OSERDESをDDRモードにすると、最低4ビット入力となって、CLKDIVはCLK入力の1/2にする必要がある。そうなると、CLKDIVは100MHz、CLKは200MHzとなる。今までは、DDR2 SDRAMコントローラは200MHzで動作していたのだが、OSERDESを使う出力だけは100MHzでデータをロードする必要が出てきた。(ISERDESは200MHzで使うことができた)
最初からすべてのDDR2への出力にOSERDESを使うことを前提に100MHzで設計していたら良いのだろうが、200MHzで動く資産があるので、これを使うには、100MHzで動作するOSERDESとの同期を取る必要がある。200MHzで発行するWriteコマンドを100MHzのクロックエッジに同期させる必要が出てきたので、同期信号を作成した。この同期信号に同期してWriteを発行すれば、100MHzに対してのタイミングが確定されるので、OSERDESでDQとDQSを出力することが出来るようになる。

私はDCMを使用する際に、IPではなくDCMプリミティブを使用している。DDR2 SDRAMコントローラもSpratan3EのDDR SDRAMコントローラをベースに作り直しているので、DCMプリミティブもそのまま使用していた。
今回、インプリメント時にDDR2 SDRAMコントローラ用のDCMのDLL_FREQUENCY_MODEがLOWだとだめだとDRCが言ってきたので、HIGHに変更した。その後、シミュレーションをしていなかったのだが、スイッチや7セグLEDを上につけてシミュレーションを行ったところ、動作しなかった。
なんだなんだと思って、詳細に見てみたところCLK90が出ていなかった。そういえばVirtex2ではDLL_FREQUENCY_MODEがHIGHだとCLK90とCLK270はでなかった。
Virtex4ではDCMが変更になっているので、DCMプリミティブも変更になっているはずだと思って、ユーザーズマニュアルを見てみた。そうすると、DCM_BASE, DCM_PS, DCM_ADVの3つのプリミティブを使うようだった。(Virtex-4 ユーザーガイド UG070(v1.4)2005年9月12日の56ページから転載)
7df7658a.png


これを使わないとVirtex4用のDCMは使えないようだ。ちなみにDCM_ADVのVerilog HDLソースコードを読んでみたらDLL_FREQUENCY_MODEがHIGHでもCLK90とCLK270は出力されるようだった。
やはり、CoregenでDCMのIPを使ったほうが安全だと思った。ちょっとやってみたが、DCM_ADVが出てきた。
fa1f6b77.png


ついでなので、ISERDESのNETWORKINGモードのbitslipモードをテストしてみる。”ISERDESのお勉強の続きのその後2”から、わざとDDRのデータをずらして、bitslipを使用してビットの位置を合わせてみた。
テストベンチだけ変えたので、テストベンチはこれ。

`default_nettype none
`timescale 1ps/1ps
module serial_parallel_converter_tb;
    reg Din = 1'b0;
    reg clk_in = 1'b0;
    reg rst = 1'b1; // reset
     reg bitslip = 1'b1; // bitslip mode
    reg enable = 1'b0;
    wire [9:0] recv_data;
    wire [9:0] q_out;
    
    wire [9:0] para10bits;
    wire outbit;
    integer i;
    
    parameter PERIOD = 5000; // 5ns, 200MHz
    parameter real DUTY_CYCLE = 0.5;
    parameter OFFSET = 0;

    initial    // Clock process for clk
    begin
        #OFFSET;
        forever
        begin
            clk_in = 1'b0;
            #(PERIOD-(PERIOD*DUTY_CYCLE)) clk_in = 1'b1;
            #(PERIOD*DUTY_CYCLE);
        end
    end
    
    serial_parallel_converter UUT (
        .Din(Din),
        .clk_in(clk_in),
        .rst(rst),
        .bitslip(bitslip),
        .enable(enable),
        .recv_data(recv_data),
        .q_out(q_out)
    );
    
    initial begin // 10bitを出力
        #100000;    // GSRリセットを待つ
        #(PERIOD);
        rst = 1'b0;
        #(PERIOD);
        enable = 1'b1;
        
        @(posedge UUT.clkdiv); // clkdivの立ち上がりまでWait
         #(PERIOD); // 1clk_inの半分の時間を進める
        #(PERIOD/4);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        #100000
        $stop;
    end
    
    task Out10bits;
        input [9:0] para10bits;
        integer i;
        begin
            for (i=0; i<10; i=i+1)
                Out1bit(para10bits[9-i]);
        end
    endtask
    
    task Out1bit;
        input outbit;
        begin
            Din = outbit;
            #(PERIOD/2);
        end
    endtask
    
    initial begin // データがあってから7つ数えてbitslipを0に。
    // 10'b01_0100_1010の1つ前の立ち上がりでbitslipを0にする必要がある
        @(posedge UUT.clkdiv);
        while (recv_data != 10'b01_0100_1010) 
            @(posedge UUT.clkdiv);
    
        for (i=0; i<10; i=i+1) begin
            @(posedge UUT.clkdiv);
            if (i==7) begin
                #1000;
                bitslip = 1'b0;
            end
        end
    end
    
endmodule
`default_nettype wire


これをシミュレーションするとこうなる。
d97e1ccd.png


rstが上がる前から、bitslipはずーと1で、最初に14ah(10_0100_1010)になってからclkdivの立ち上がりごとにiをカウントしていって7になったときに、bitslipを0にして、ビットの入れ替えをやめる。こうすれば14ah(10_0100_1010)をキープできる。
ネットワークのデータは最初のパターンがわかっていれば、こうしてビットの位置の同期を取ればよいのだろうと思う。

ISERDESのお勉強の続きで1:10のDDRのISERDESをインプリメントしてみたが、今度はシミュレーションをしてみた。ISERDESの1:8のSDRのタイミングチャートがユーザーズマニュアルにあったが、このタイミングチャートだとすると、今やっている1:10のDDRのタイミングと合わない気がするが、とりあえずBitslipを使ってみたので、記録しておく。
どうやら、DDRはCEが1になったclkdivの立ち上がりと同時のclk_inや次のclk_inの立下りからではなく、次のclk_inの立ち上がりからシリアルーパラレル変換するようだ。タイミングを調整して、このタイミングにあわせる。
この前のISERDESのVerilogファイルはこのように変更した。

`default_nettype none
`timescale 1ps/1ps
module serial_parallel_converter (
    Din,
    clk_in,                       
    rst,
    bitslip,
    enable,
    recv_data,
    q_out
);
    input  Din;
    input  clk_in;
    input  rst;
    input bitslip;
    input enable;
    output [9:0] recv_data;
    output [9:0] q_out;
    wire    Din;
    wire    clk_in;
    wire    rst;
    wire    bitslip;
    wire    enable;
    wire    [9:0] recv_data;
    wire    [9:0] q_out;
    wire   iserdes_clkout;
    wire   iobclk;
    wire   clkdiv;
    wire   shiftdata1;
    wire   shiftdata2;
    wire [9:0] data_internal;
    reg    [9:0] data;
    
    // Instantiate ISERDES for forwarded clock
     ISERDES fwd_clk (
         .O(iserdes_clkout),
         .Q1(), 
         .Q2(), 
         .Q3(), 
         .Q4(), 
         .Q5(), 
         .Q6(), 
         .SHIFTOUT1(), 
         .SHIFTOUT2(),
         .BITSLIP(1'b0),
         .CE1(1'b1), 
         .CE2(1'b1),
         .CLK(iobclk),
         .CLKDIV(clkdiv),
         .D(clk_in),
         .DLYCE(1'b0),
         .DLYINC(1'b0),
         .DLYRST(1'b0),
         .OCLK(1'b0), 
         .REV(1'b0),  
         .SHIFTIN1(1'b0), 
         .SHIFTIN2(1'b0),
         .SR(rst)
      );
    defparam fwd_clk.BITSLIP_ENABLE  =  "TRUE"; 
    defparam fwd_clk.DATA_RATE =  "DDR";
    defparam fwd_clk.DATA_WIDTH =  4;   
    defparam fwd_clk.INTERFACE_TYPE =  "NETWORKING"; 
    defparam fwd_clk.IOBDELAY =  "NONE"; 
    defparam fwd_clk.IOBDELAY_TYPE =  "DEFAULT"; 
    defparam fwd_clk.IOBDELAY_VALUE = 0; 
    defparam fwd_clk.NUM_CE = 1; 
    defparam fwd_clk.SERDES_MODE =  "MASTER"; 
    
    // Instantiate Master ISERDES for data channel
    // 1:10 Deserialization Factor
    ISERDES data_chan_master (
        .O(), 
        .Q1(data_internal[0]),
        .Q2(data_internal[1]),
        .Q3(data_internal[2]), 
        .Q4(data_internal[3]),
        .Q5(data_internal[4]),
        .Q6(data_internal[5]),
        .SHIFTOUT1(shiftdata1),
        .SHIFTOUT2(shiftdata2),
        .BITSLIP(bitslip),
        .CE1(enable), 
        .CE2(1'b1),
        .CLK(iobclk),
        .CLKDIV(clkdiv),
        .D(Din), 
        .DLYCE(1'b0),
        .DLYINC(1'b0),
        .DLYRST(1'b0),
        .OCLK(1'b0), 
        .REV(1'b0),
        .SHIFTIN1(1'b0), 
        .SHIFTIN2(1'b0),
        .SR(rst)
    );
    defparam data_chan_master.BITSLIP_ENABLE =  "TRUE"; 
    defparam data_chan_master.DATA_RATE =  "DDR";
    defparam data_chan_master.DATA_WIDTH =  10;   
    defparam data_chan_master.INTERFACE_TYPE =  "NETWORKING";         
    defparam data_chan_master.IOBDELAY =  "NONE";                 
    defparam data_chan_master.IOBDELAY_TYPE =  "DEFAULT";         
    defparam data_chan_master.IOBDELAY_VALUE =  0;                
    defparam data_chan_master.NUM_CE =  1;                        
    defparam data_chan_master.SERDES_MODE =  "MASTER"; 
    //
    // Instantiate Slave ISERDES for data channel
    // 1:10 Deserialization Factor

    ISERDES data_chan_slave (
        .O(), 
        .Q1(), 
        .Q2(), 
        .Q3(data_internal[6]),
        .Q4(data_internal[7]),
        .Q5(data_internal[8]),
        .Q6(data_internal[9]),
        .SHIFTOUT1(), 
        .SHIFTOUT2(),
        .BITSLIP(bitslip),
        .CE1(enable), 
        .CE2(1'b1),
        .CLK(iobclk),
        .CLKDIV(clkdiv),
        .D(1'b0), 
        .DLYCE(1'b0),
        .DLYINC(1'b0),
        .DLYRST(1'b0),
        .OCLK(1'b0), 
        .REV(1'b0),
        .SHIFTIN1(shiftdata1), 
        .SHIFTIN2(shiftdata2),
        .SR(rst)
    );
    defparam data_chan_slave.BITSLIP_ENABLE =  "TRUE"; 
    defparam data_chan_slave.DATA_RATE =  "DDR";
    defparam data_chan_slave.DATA_WIDTH =  10;   
    defparam data_chan_slave.INIT_Q1  =  1'b0;   
    defparam data_chan_slave.INIT_Q2  =  1'b0;   
    defparam data_chan_slave.INIT_Q3  =  1'b0;        
    defparam data_chan_slave.INIT_Q4  =  1'b0;   
    defparam data_chan_slave.INTERFACE_TYPE  =  "NETWORKING";         
    defparam data_chan_slave.IOBDELAY  =  "NONE";                 
    defparam data_chan_slave.IOBDELAY_TYPE  =  "DEFAULT";         
    defparam data_chan_slave.IOBDELAY_VALUE  =  0;                
    defparam data_chan_slave.NUM_CE  =  1;                        
    defparam data_chan_slave.SERDES_MODE  =  "SLAVE";             
    defparam data_chan_slave.SRVAL_Q1  =  1'b0;                   
    defparam data_chan_slave.SRVAL_Q2  =  1'b0;                   
    defparam data_chan_slave.SRVAL_Q3  =  1'b0;                   
    defparam data_chan_slave.SRVAL_Q4  =  1'b0;
    //
    BUFIO bufio1 (
        .O(iobclk),
         .I(iserdes_clkout)
                 );
    // To get a 1:10 deserialization factor in DDR mode, 
    // set the clock divide factor to "5"
    BUFR bufr1 (
        .O(clkdiv),
        .CE(1'b1),
        .CLR(1'b0),
        .I(iobclk)
    );
    defparam bufr1.BUFR_DIVIDE  =  "5";
    
    always @(posedge rst, posedge clkdiv) begin

        if (rst)
            data <= 0;
        else
            data <= data_internal;
    end
    assign q_out = data;
    assign recv_data = data_internal;
endmodule
    


次にテストベンチ。

`default_nettype none
`timescale 1ps/1ps
module serial_parallel_converter_tb;
    reg Din = 1'b0;
    reg clk_in = 1'b0;
    reg rst = 1'b1; // reset
//     reg bitslip = 1'b1; // bitslip mode
    reg enable = 1'b0;
    wire [9:0] recv_data;
    wire [9:0] q_out;
    
    wire [9:0] para10bits;
    wire outbit;
    integer j;
    
    parameter PERIOD = 5000; // 5ns, 200MHz
    parameter real DUTY_CYCLE = 0.5;
    parameter OFFSET = 0;

    initial    // Clock process for clk
    begin
        #OFFSET;
        forever
        begin
            clk_in = 1'b0;
            #(PERIOD-(PERIOD*DUTY_CYCLE)) clk_in = 1'b1;
            #(PERIOD*DUTY_CYCLE);
        end
    end
    
    serial_parallel_converter UUT (
        .Din(Din),
        .clk_in(clk_in),
        .rst(rst),
        .bitslip(1'b0),
        .enable(enable),
        .recv_data(recv_data),
        .q_out(q_out)
    );
    
    initial begin // 10bitを出力
        #100000;    // GSRリセットを待つ
        #(PERIOD);
        rst = 1'b0;
        #(PERIOD);
        enable = 1'b1;
        
        @(posedge UUT.clkdiv); // clkdivの立ち上がりまでWait
        #(PERIOD/2); // 1clk_inの半分の時間を進める
        #(PERIOD/4);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b01_0100_1010);
        Out10bits(10'b10_0101_1011);
        #100000
        $stop;
    end
    
    task Out10bits;
        input [9:0] para10bits;
        integer i;
        begin
            for (i=0; i<10; i=i+1)
                Out1bit(para10bits[9-i]);
        end
    endtask
    
    task Out1bit;
        input outbit;
        begin
            Din = outbit;
            #(PERIOD/2);
        end
    endtask
    
//     always @* begin // q_outが10'b01_0100_1010の1つ前の10'b10_1001_0100になったらbitslipを0にする
//         if (recv_data == 10'b10_1001_0100)
//             bitslip = 1'b0;
//     end
    
    
endmodule
`default_nettype wire


最終的にbitslipは使用しなかったが、クロックと送ってきたビット列が合わずにワード同期が取れない場合は、bitslipを最初1にして、ビット列を移動することができる。そのときに、送ったデータと同一になったらbitslipを0にしてビット列の移動を止めれよいが、ISERDESのQ出力は1段多くラッチされているので、1つ手前でbitslip信号を0にしないと行き過ぎてしまう。
シミュレーションすると下のようになる。
1903c6fc.png


rstが0になって、enable(CE1)がclkdivの前でアサートされたクロックエッジの次のclk_inの立ち上がりエッジからデータ(Din)をサンプルするようだ。
サンプルされたデータはclkdivでラッチされて、次のclkdivの立ち上がりで出力([9:0]data_internal)されるようだ。
これでNETWORKINGモードでは、うまく行ったようだ。ずーと同じタイミングでデータ転送されればこれでOKだと思う。もしビット列が間違っていても、あらかじめ参照パターンがわかっていれば、bitslipを使って必要なだけビット列を入れ換えれば良い。
だが、DDRの受信の場合は、必ずしもそのタイミングに合うというわけではないので、bitslipでビット列を入れ替えるのは難しい。さらにclkdivは、clk_in(DQS)が途中で止まってしまうので、DQSから分周して作るのは難しいと思う。そこで、グローバルクロックから入れたらどうだろうと思っている。
さらに、DDR2-SDRAMコントローラのアプリケーションノートはMEMORYモードで使用しているので、検証してみたい。

↑このページのトップヘ