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設定を行うようです.結果的にどうすべきかのメモを置いておきます.
以下の信号全てを同一グループとし,I/O Bankの制約に引っかからないように制御する.
mem_dq[0..15], mem_dqs[0..1], mem_dm[0..1]
以下の信号全てを同一グループとし,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クロックとほぼ無関係に動作する.
このため,本IPの出力クロックを使わないのであれば,Clock Brdigeを加える必要がある.また,本IPはSlave portしか存在しない.このSlavePortの動作クロックは,以下のシンボルのクロックで駆動される.Master Portも同じくロックで駆動する必要がある.
<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を作り上げることすらできなさそうです.