Kintex-7でDDR3 SD-DIMMを使う
いま受託でやっている仕事で、Kintex-7にDDR3のSO-DIMMをつないで読み書きしようとしています。
ISEとCoreGenの環境でやっているのですが、なかなかうまく動いてくれません。
CoreGenでSODIMMを選択すると、なぜか最後までインプリメントが通らないで、とりあえず単一のDDR3メモリを選択して、SODIMMの8分の1だけ動かそうとしています。
まず最初の設定画面。AXI4を選択しておきます。
AXI4を使わないapp何とかという信号を操作する使い方だと、最高性能が出せるけどポートは1つだし自分でユーザクロックとの同期とかしなければならず、面倒です。
AXI4にするとその辺の面倒なことは全部コアがやってくれます。
次。ここが肝心。
まず、ここで設定する速度はDDR3メモリに行くクロックの速度。ここで800MHzと指定したらDDRのレートはクロックの倍の1600Mb/sになります。とりあえず控えめの500MHzにしました。これならDDRメモリのレートは1Gb/sになるはず。
4:1という設定は重要ですが、このままにしておきます。
その次の設定画面。
データバスの幅はDDR3メモリの幅の8倍だから、これでよい。この画面では特に変更なし。
次の設定画面。ここが超重要!
Input Clock Periodというのは、おそらくコアのsys_clkのクロックのことですが、これをメモリクロックの4分の1にします。4分の1というのは、前の設定で4:1にしたから。
DDRのレートはクロックの倍だから、メモリの速度が1000Mb/sなら、ユーザインタフェースの速度は8分の1になって、データバスは8倍の幅になる、と考えるとつじつまが合います。
この関係をstrictに保たないと、何だかAXIコアが途中で止まってしまうようです。
(AXIコアが途中で止まるという現象で2週間ほど悩みました)
それ以外の設定は特に変更なし。
その次の設定も重要。ClockをNoBufferにしたのは、自分で作ったデザインの中にあるMMCMからクロックを供給するためです。基板上のオシレータからMRCCのピンを通して直接MIGのコアに入れるならば設定は変わってくるでしょう。
IO Power ReductionはOFFにすると、エラーが出て途中で止まる。
XADCを使うと、FPGAの温度を測って、再キャリブレーションとかデータアイの中央に合わせるだとか、そういうことをやってくれるらしい。でも、現在の基板でXADCはVREFPをGNDにつないでしまったのでXADCが使えないので、これはOFFにする。
※XADCをDisableにすると、device_temp_iという信号を自分で与えなければならなくなる。とりあえず2509という数値を12bitで与えることにしている。これは40℃前後を示す値だったはず。
インプリメントするときは、こんな感じ。
inst_axi_ddr : axi_ddr3 port map ( ddr3_dq => ddr3_dq, ddr3_dqs_n => ddr3_dqs_n, ddr3_dqs_p => ddr3_dqs_p, -- Outputs ddr3_addr => ddr3_addr, ddr3_ba => ddr3_ba, ddr3_ras_n => ddr3_ras_n, ddr3_cas_n => ddr3_cas_n, ddr3_we_n => ddr3_we_n, ddr3_cs_n => ddr3_cs_n, ddr3_reset_n => ddr3_reset_n, ddr3_ck_p => ddr3_ck_p, ddr3_ck_n => ddr3_ck_n, ddr3_cke => ddr3_cke, ddr3_dm => ddr3_dm, ddr3_odt => ddr3_odt, -- Inputs -- Single-ended system clock sys_clk_i => clk125m, clk_ref_i => clk200m, ui_clk => ui_clk, ui_clk_sync_rst => ui_clk_sync_rst, mmcm_locked => mmcm_locked, aresetn => aresetn, app_sr_req => app_sr_req, app_sr_active => app_sr_active, app_ref_req => app_ref_req, app_ref_ack => app_ref_ack, app_zq_req => app_zq_req, app_zq_ack => app_zq_ack, -- Slave Interface Write Address Ports s_axi_awid => ddr_axi_awid, s_axi_awaddr => ddr_axi_awaddr, s_axi_awlen => ddr_axi_awlen, s_axi_awsize => ddr_axi_awsize, s_axi_awburst => ddr_axi_awburst, s_axi_awlock => ddr_axi_awlock, s_axi_awcache => ddr_axi_awcache, s_axi_awprot => ddr_axi_awprot, s_axi_awqos => ddr_axi_awqos, s_axi_awvalid => ddr_axi_awvalid, s_axi_awready => ddr_axi_awready, -- Slave Interface Write Data Ports s_axi_wdata => ddr_axi_wdata, s_axi_wstrb => ddr_axi_wstrb, s_axi_wlast => ddr_axi_wlast, s_axi_wvalid => ddr_axi_wvalid, s_axi_wready => ddr_axi_wready, -- Slave Interface Write Response Ports s_axi_bready => ddr_axi_bready, s_axi_bid => ddr_axi_bid, s_axi_bresp => ddr_axi_bresp, s_axi_bvalid => ddr_axi_bvalid, -- Slave Interface Read Address Ports s_axi_arid => ddr_axi_arid, s_axi_araddr => ddr_axi_araddr, s_axi_arlen => ddr_axi_arlen, s_axi_arsize => ddr_axi_arsize, s_axi_arburst => ddr_axi_arburst, s_axi_arlock => ddr_axi_arlock, s_axi_arcache => ddr_axi_arcache, s_axi_arprot => ddr_axi_arprot, s_axi_arqos => ddr_axi_arqos, s_axi_arvalid => ddr_axi_arvalid, s_axi_arready => ddr_axi_arready, -- Slave Interface Read Data Ports s_axi_rready => ddr_axi_rready, s_axi_rid => ddr_axi_rid, s_axi_rdata => ddr_axi_rdata, s_axi_rresp => ddr_axi_rresp, s_axi_rlast => ddr_axi_rlast, s_axi_rvalid => ddr_axi_rvalid, -- System reset - Default polarity of sys_rst pin is Active Low. -- System reset polarity will change based on the option -- selected in GUI. init_calib_complete => init_calib_complete, device_temp_i => conv_std_logic_vector(2509,12), sys_rst => sys_rst_n );
リセットが2つありますよね。sys_rst_nは、コアのリセット。aresetnはAXIのリセットです。
sys_rst_nを解除してからしばらく(16クロックでいいという話があるが、私はms単位待たせている)経ってからaresetnを解除します。
クロックはui_clk。ユーザ側ステートマシンはui_clkで動くようにする。ui_clkの速度は、メモリクロックの4分の1。つまり、↑の設定では125MHzになります。
これで何とかDDR3メモリが動くようになりました。
でも、XORSHIFTを使って作った乱数を読み書きしてみると、たまにリードエラーが発生しています。
よく見ると、バースト的にエラーが発生していて、以下の特徴があります。
- AXIの次のバーストサイクルにはエラーを持ち越していない。直っている。
- リフレッシュと関係がありそう
- XORSHIFTはずれていない。つまり、AXIのRVALIDやWREADY,WVALIDなどの問題ではない
書き込むアドレスが、AXIコアの中で変わってしまっているのかもしれません。
まだまだ道は長そうです。
◆追伸
続きはメーリングリストで流しました
| 固定リンク
コメント