いま受託でやっている仕事で、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コアの中で変わってしまっているのかもしれません。
まだまだ道は長そうです。
◆追伸
続きはメーリングリストで流しました
最近のコメント