2008/12/01(月)[QuartusII][SOPC] DDR SDRAM High Performance Controller

[QuartusII][SOPC] DDR SDRAM High Performance Controller

基本

基本的には,ALTERAから出ているUsers Guide~(External DDR Memory PHY Interface Megafunction User Guide (ALTMEMPHY))file:"altmemphy.pdf"~を参照すれば使い方がわかるはずです.


はまったところ

使用するIPのユーザーズガイドは目を通すべし

DDRcontrollerにおいては,2つの制約ファイルが用意されていました.いろいろと調べる羽目になったけれども,SOPC Builderを純粋に使って幾分には,ユーザーズガイドに沿って作業を進めれば乗り越えられたようです...

具体的には,以下のファイルが生成されます.

<module-name>_phy_ddr_timing.sdc
<module-name>_phy_ddr_pins.tcl
 where <module-name> := SOPC Builder の "module name"に記述した名称

SDCファイルはprojectにTimeingQuestへ渡すように設定が必要です.
tclについては,外部端子設定を行うマクロがついています.v7.2のpicture viewerを元にPin Assignment Editorで設定をしてしまったので,使用感は今のところわかりません.scriptを見る感じでは,module階層をたどって外部ピンまで探し出し,ドライブ設定(SSTL-2),電流設定(8mA~Max.まで機能ごとに設定),OutpuEnableGroup設定を行うようです.結果的にどうすべきかのメモを置いておきます.

  • OutpuEnableGroupの設定~1

以下の信号全てを同一グループとし,I/O Bankの制約に引っかからないように制御する.

mem_dq[0..15], mem_dqs[0..1], mem_dm[0..1]
  • OutpuEnableGroupの設定~2

以下の信号全てを同一グループとし,I/O Bankの制約に引っかからないように制御する.

led[0..3]
  • Current_Strengthを設定する
    • Maximum Current
      mem_dq[0..15], mem_addr[0..] //全部
      
    • 12mA
      mem_cs_n, mem_ras_n, mem_cas_n, mem_cke, mem_we_n, mem_clk, mem_clk_n
      mem_ba[0..1], mem_dm[0..1], mem_dqs[0..1]
      

動作クロックがわからない

SOPC BuilderでControllerを貼り付けるが,Clock domainの設定に留意する点がある.DDR controllerの動作クロックは,configurationで自動的にPLLを使ってクロックを生成させる方法をとると,inputするreferenceクロックとほぼ無関係*1に動作する.
このため,本IPの出力クロックを使わないのであれば,Clock Brdigeを加える必要がある.また,本IPはSlave portしか存在しない.このSlavePortの動作クロックは,以下のシンボルのクロックで駆動される.Master Portも同じくロックで駆動する必要がある*2

<DDRcontroller-Module-Name>_sysclk
 where <DDRcontroller-Module-Name> := "Module Name"の欄に入力した文字列

失敗の具体例

システム要件

CPU clock=100MHz
DDR clock=133MHz/66.5MHz
 CPU-DDR間には Clock Bridgeを設置
  BridgeのSlave(CPU側)は CPU clockを設定
  BridgeのMaster(DDR側)は CPU clockを設定(※ここが誤り)

Timing Analysisの結果,以下のようなcritical warningが出る.

Info: Path #1: Setup slack is -3.478 (VIOLATED)
  Info: ===================================================================
  Info: From Node    : Nios2_NoDDR:Nios2_NoDDR_inst|Nios2_NoDDR_clock_1:the_Nios2_NoDDR_clock_1|Nios2_NoDDR_clock_1_slave_FSM:slave_FSM|slave_write_request
  Info: To Node      : Nios2_NoDDR:Nios2_NoDDR_inst|Nios2_NoDDR_clock_1:the_Nios2_NoDDR_clock_1|unxslave_write_requestxx3
  Info: Launch Clock : Nios2_NoDDR_inst|the_pll0|the_pll|altpll_component|auto_generated|pll1|clk[0]
  Info: Latch Clock  : Nios2_NoDDR_inst|the_ddrsdram|ddrsdram_controller_phy_inst|alt_mem_phy_inst|ddrsdram_phy_alt_mem_phy_inst|clk|pll|altpll_component|auto_generated|pll1|clk[1]
  Info: 
  Info: Data Arrival Path:
  Info: 
  Info: Total (ns)  Incr (ns)     Type  Element
  Info: ==========  ========= ==  ====  ===================================
  Info:     30.000     30.000           launch edge time
  Info:     32.932      2.932  R        clock network delay
  Info:     33.037      0.105     uTco  Nios2_NoDDR:Nios2_NoDDR_inst|Nios2_NoDDR_clock_1:the_Nios2_NoDDR_clock_1|Nios2_NoDDR_clock_1_slave_FSM:slave_FSM|slave_write_request
  Info:     33.037      0.000 FF  CELL  Nios2_NoDDR_inst|the_Nios2_NoDDR_clock_1|slave_FSM|slave_write_request|q
  Info:     33.192      0.155 FF    IC  Nios2_NoDDR_inst|the_Nios2_NoDDR_clock_1|unxslave_write_requestxx3~feeder|datad
  Info:     33.255      0.063 FF  CELL  Nios2_NoDDR_inst|the_Nios2_NoDDR_clock_1|unxslave_write_requestxx3~feeder|combout
  Info:     33.255      0.000 FF    IC  Nios2_NoDDR_inst|the_Nios2_NoDDR_clock_1|unxslave_write_requestxx3|d
  Info:     33.305      0.050 FF  CELL  Nios2_NoDDR:Nios2_NoDDR_inst|Nios2_NoDDR_clock_1:the_Nios2_NoDDR_clock_1|unxslave_write_requestxx3
  Info: 
  Info: Data Required Path:
  Info: 
  Info: Total (ns)  Incr (ns)     Type  Element
  Info: ==========  ========= ==  ====  ===================================
  Info:     30.064     30.064           latch edge time
  Info:     29.960     -0.104  R        clock network delay
  Info:     29.820     -0.140           clock uncertainty
  Info:     29.827      0.007     uTsu  Nios2_NoDDR:Nios2_NoDDR_inst|Nios2_NoDDR_clock_1:the_Nios2_NoDDR_clock_1|unxslave_write_requestxx3
  Info: 
  Info: Data Arrival Time  :    33.305
  Info: Data Required Time :    29.827
  Info: Slack              :    -3.478 (VIOLATED)
  Info: ===================================================================

Launch ClockがCPU clock,Latch clockがDDR controller IPが生成したPLLクロックである.Launch/Latchが逆のケースもあり,そもそも異なるclock domainの信号が交錯している段階で異常.特にCELL名から,WRITE要求信号がViolationしているので,ありえない.
FIFOによるclock分離部分のfalse_path設定やmulticycle_path設定忘れなどではないところに注意.無視してよいものと悪いものの判断ができるようになる必要がある.そのためには同期系回路はどのクロックで駆動されているのかを把握し,clock domain境界はどこにあり,そこはどうやって回避しているのかを把握しておくこと.
位相保障をしつつクロックを整数倍にしていれば,setup/hold条件を満足させることもできるだろう.本システムの場合,100MHzと133MHz(またはその半分)で駆動しているため,必ずエラーとなる.


ポート属性の認識誤り

port attribute に留意する.
特に外部portへの接続時に,inout属性を指定する必要のある端子がある.

.mem_clk_n_to_and_from_the_ddrsdram  (),
.mem_clk_to_and_from_the_ddrsdram    (),
.mem_dq_to_and_from_the_ddrsdram     (),
.mem_dqs_to_and_from_the_ddrsdram    (),

CLKが双方向にする必要というのが理解しきれていないが,cycloneとして必要という認識.
PLLにfeebackしているのかpair clockとして位相を合わせるのに使っているのか,documentを追いかけ切れていない.

DQはデータ信号なので双方向,DQSについては,データ送出側がドライブすることになるので,双方向である必要がある.
DDRになってから,driveするデバイスが入れ替わるようになったようなので,SDRAMだけの知識だけで挑んだのでミスった.

なお,DRAM系の情報としては,ELPIDAが公開している製品情報から教材となるPDFを得られる.和文documentが充実していて非常にありがたい.


失敗の具体例

dqsのポート設定を誤ってoutportとして接続したとき,Synthesisまで通ってしまった.
その後のTimingQuestによるtiming analysisで,TimeQuestがassertionでこけた.(QuartusII v8.1, WEB edition)
本件,属性違いに気づかずALTERA my supportにてSRを出してしまったが,Work Aroundとして"inout"にしてくださいといわれて気づいた.

HDLの仕様上,ポート接続時の属性チェックはなされない模様ですね.Tri-stateを考えると,出力同士が衝突してもおかしくないし,記述自体もinoutでぶら下げたりしてますからね...
そんなわけで,moduleを使うにはmoduleの動作概要の理解とinput/output/inout属性の確認,今回のように外部デバイスと接点がある場合も,その信号の意味等を理解しておくほうが無難です.
SOPC Builderはあくまでもサポートツールであり,その下にあるフレームを理解しなくては,自力でprojectを作り上げることすらできなさそうです.

*1 : 入力クロックにロックするが,位相差はできてしまう.

*2 : 同一クロックを用いない場合は,setup/hold条件を満たすようなクロックを生成する必要があるだろう.