2013年6月30日日曜日

LatticeECP3用DDR3 SDRAMCの作成 9

前回のつづき、

リードデータのvalid信号はDQSBUFDのDATAVALIDを使わないで別に作ることにした。

rd_ren信号を(DQSBUFDのREADポートに入力する信号)をrpp[2:0]でシフトして生成している。
rd_renはDQSのプリアンブル分も含んだパルス幅になっていて必要な幅よりも広いため、rd_renを1サイクル遅延させたrpp[0]とrd_renとをANDしてrpp[1]に入れ、それをもう1段遅延させている。


DQSDLLB部も修正を行った。DQSDLLBはリード時にDQS信号の位相を90°ズラすためのハードマクロであるが、このモジュールのUDDCNTLN入力を常時 L にしていた。この信号は負論理の信号で、L が入力されると位相量が更新される。(この更新というのはDLLのキャリブレーションに相当する動作と思われる。) ハンドブックにはリード/ライト期間外に L にして更新できると書いてあった。つまり、リード/ライト時は L にしてはいけなかった。そこで、以下のようにした。起動時に自動で1回更新処理を行い、以降はソフトウェア制御により任意のタイミングで更新できるようにした。当然、この時はリード/ライトは発生しない状態にしておく必要はある。


以上の変更&修正を行ったところ、リードでそれらしい値が読めるようになったが、微妙に違う。ただし、今度は10回リードしても値自体の変動は無かったので、おそらくライト側の異常が考えられた。実は、この症状には思いつくところがあった。以下はライトのシミュレーションの波形だが、赤丸部のようにグリッジが発生している。これは以前から気づいてはいたのだがシミュレーションモデルの問題だとばかり思っていた。が、実機でも実際にこの現象が発生しているのかも知れない。


そこで、改めてハンドブックを調べてみたところ、ODDRX2Dに入力するSCLKとDQCLK1との位相関係について制約があることが判った。  SCLKとDQCLK1とは逆位相にする必要があるようだ。


このDQCLK0, 1はどこで生成されるかというと、DQSBUFDで生成される。


DQSBUFDにはSCLKも入力されるし、DQCLK0,1はハードマクロからハードマクロへの信号なのだから、特別はことをしなくても上記の位相関係をDQSBUFDが担保するべきでは?という気もするのだが。。。  そこで、DQSBUFDのシミュレーションモデルのソースを確認したところ以下のようになっていた。


入力であるECLKWB_int1はECLKW (ECLK) を遅延させた信号、RSTBはRST信号で、DQCLK0_int、DQCLK1_intが最終的にDQCLK0、DQCLK1になる。この記述からSCLKはまったく論理に絡んでいないことが判る。しかも、制御できる入力はRSTだけなので、この信号のタイミングを工夫して与えることで、SCLKとDQCLK1との位相関係を満たさなければならない。。。うーむ。
で、結局以下のようにRST信号をSCLKの立ち下がりエッジで叩いてからDQSBUFDに入力するようにした。(dc_ddrio内部でsrstがDQSBUFDのRSTに接続されている。)




ちなみに、DQCLK1とDQCLK0との位相関係について、上記のハンドブックの図ではDQCLK1の1の期間にDQCLK0が1になるようになっているが、おそらくこれは誤植と思われる。DQSBUFDのシミュレーションモデルのソースでは以下のような記述となっており、DQCLK0_intにはDQCLK1_intを反転した信号が入力されている。この記述ではDQCLK1、0は H → Hというような位相関係にはならない。


RSTの修正を行った結果、USB-UART経由での単発のアクセスによる確認ではあるが、正常にリード/ライトできるようになった。次はLFSR等による高密度なアクセスによる確認をする必要がある。が、その前に、500MHz (1Gbps)で動くかどうか確認してみた。各部の動作周波数は以下のようになる。


合成は成功した。


以下のような簡単なプログラムで動作確認してみた。


結果はOK


次に以下のようなプログラムで動作確認してみた。リードバック動作を伴うこととUSB-UARTの通信速度の遅さもあって、このプログラムの実行は一晩を要したが、エラーなく最後まで動作していた。


ということで、1Gbpsでの動作も可能なようだ。。。すばらしい。Lattice すげー
このLatticeECP3 Versa Development Kitは買って正解だったかも知れない、うんうん。

ネットで検索してみてもLatticeのFPGAで××を作った的なページは殆ど見つからない。検索のしかたが悪いのかも知れないが。 開発環境であるDiamondの習得はそれほど難しくないと思う。むしろ簡単な部類に入るんじゃ無いだろうか。タイミングアナライザ等は操作中に突然落ちたりすることがあるが、以前(Lattice XP2で何かを作っていた頃)に比べれば頻度は少ない。それにLinux版特有の症状かも知れないし。デバイスの価格も安そうだし、もっと人気があっても良さそうな気がするが。。。まぁ、DQSBUFDのように癖のあるハードマクロが有ったりはするが、慣れればどうということも無いんじゃなかろうかとも思う。。。今のところは。。。それに、DRAM-PHYはIPExpressで生成して使うだろう普通は。っという気もする。であるなら、やはり、もっと普及してもいいよな。私が知らないだけか?


2013年6月24日月曜日

LatticeECP3用DDR3 SDRAMCの作成 7

実機で試してみた。
System Architectureは以下のようにしている。 Versa BoardはPCIE I/Fも付いているが、いきなりPCIEから制御してもバグでPCが固まったりHDDに障害を与えたりする可能性も考えられるので、最初はPCとはなるべく粗な結合状態で確認したほうがいいだろうと考えた。


で、以下のようなプログラムで0を書いて、それが正しく読めるかを見てみた。


結果は以下の通りで正しく読めていない。リードを10回行っているが、表示される値が微妙に異なっているので少なくともリードに問題があるようだ。


今度は、FFFFFFFFで試してみたが同様に正しく読めなかった。


結果


そこで、以下のようにSDRAMからのリードデータの代わりにカウンタの値を返すようにしてリードしてみた。カウンタのカウントイネーブルであるrd_vldはDQSBUFDのDATAVALID信号だ。


SDRAMは16bit x バースト長8でアクセスしていて、且つ、上記の箇所ではデータ幅は64bitだから、期待通りに動作していればrd_vld (DATAVALID)は2サイクルの期間アサートされる筈だ。したがって、カウンタはリードの度に+2づつ更新される筈である。が、期待に反して以下のような結果になった。以下では1分程度時間をあけて4回プログラムを実行した。


上記結果をみると実行の度に値が増加(しかも大幅に)しているので、どうやらDATAVALIDが1に張り付いているっぽい。このDATAVALIDが1に維持されるという現象はシミュレーションでも確認されていて、それを回避するためにREADストローブのタイミングをあれこれと苦心していた訳だが、実機でも発生してしまっている。ということはシュミレーションモデルの問題では無くて実際にそういう動作をするということなんだろう。なんとも癖のあるモジュールだ。それとも、何か使い方を間違っているんだろうか??

うーん・・・


2013年6月15日土曜日

LatticeECP3用DDR3 SDRAMCの作成 6

Timing Analysis ViewでI/O部の遅延時間を確認した。

CLKのODDR→PAD迄の遅延時間

DQ入力のPAD→IDDR迄の遅延時間

DQSの入力遅延時間も必要なのだが、DQSはDQSBUFD内部ではクロックとして扱われているらしく遅延時間が表示されない。そのため、DQSのPAD→DQSBUFD迄の入力遅延もDQと同じと仮定することにした。

遅延時間のモデルは下図の様なイメージで考えている。シミュレーションで使用しているMicronのDDR3 SDRAMモデルはデバイスの遅延時間も含んで動作しているので、FPGA内部の遅延時間と基板パターンの伝搬時間を追加すれば実際に近いタイミングを作れる筈だ。

0.283は基板パターンの伝搬時間の推定値だ。VersaボードのFPGA - DDR3 SDRAM間は以下の写真のような位置関係になっている。パターンの引き回しは内層で行っている様だ。両者の距離が約3cmだが、パターンは等長配線のためにクネクネ(ミアンダパターンとか言ったっけ?)している筈なので4cmと見積もった。パターンは内層を通っているのでマイクロストリップラインではなくストリップラインの伝搬時間の式 td[ns] = 3.33 x パターン長[m] x sqrt (FR-4基板の誘電率)で計算した。

これらの時間を以下のようにRTLに追記した。以下はDQSの箇所を示しているが、DQ、CLK、ADDR、等全ての信号についてそれぞれの値を追記している。

上記から往復の遅延時間の合計は約4.6nsにもなる。したがって、現状のREADストローブ信号のタイミングでは動作しそうにない。実際シミュレーションしてみると以下のようになった。

そこで、READストローブのアサートタイミングを遅らせるように修正した。

リードはこれでいい感じになった。が、遅延時間を加味したシミュレーションでライトにもtDQSSのタイミングエラーが出てしまった。

ライトの場合DQSとクロックの位相は理想的には同じ、ズレたとしても±0.25tCK以内と規程されている。つまり400MHzで動かす場合はDQSとクロックとのズレは±0.625ns以内でなければならないが、シミュレーションの波形で確認すると約0.7nsとなっていた。

DQS出力の位相はDQSBUFDのDYNDELAY入力の値で調整することが可能で、ハンドブックでは delay = DYNDELAY x 26ps とある。  (ただし、DQSBUFDのシミュレーションモデル内部の記述では delay = DYNDELAY x 27ps + 140ps となっている。  ) そこで、この機能を利用して0.7ns分DQとDQSの位相を遅らせてみたが以下のように異常動作になった。

おそらく遅延量が大き過ぎるんだろう。そこで、DRAMに供給するクロックの位相もズラすことにした。 400MHzは100MHzの源振からPLLで逓倍して生成している。ECP3のPLLのCLKOS出力は逓倍+位相シフトしたクロックを生成できる。ただしシフト量は離散的で粗い。また、あまりシフト量を大きくしすぎると今度はアドレスやRAS, CAS等の信号のタイミングマージンに影響がでてくる可能性がある。  今回はFPGA内部の400MHzとDRAMに出力する400MHzとで-45°の位相差を持つようにした。  つまり、このクロック位相でDQSの位相を粗く設定し、DQSBUFDのDYNDELAYで微調整するという方針で行くことにし、以下のように調整できた。DYNDELAYでの遅延量は約500psになった。

合成も成功してビットストリームの生成の成功したので次は実機での確認だ。


さーて、動くか???


2013年6月10日月曜日

LatticeECP3用DDR3 SDRAMCの作成 5

単純なリード/ライト、少し複雑なリード/ライトの他、CLやCWLを振っての動作が論理シミュレーションで確認できたので合成に着手している。  システムアーキテクチャはとりあえず以下のようにした。

IDDRX2DやODDRX2D等のハードマクロは以下のようなdirective (synthesis  foo)を記述する必要があった。

このdirectiveでハードマクロの属性を指定するようだ。合成後にPhysical viewerでハードマクロを見てみると以下のように表示された。

StrategyはTiming Strategyで行っている。

合成制約は以下のようにした。。。クロック周波数の設定と幾つかの非同期パスのBLOCK (dont_touch)設定程度だ。 因みに、今回はPLLを使っているのでクロック周波数の情報はPLLのネットリストからも取得できるらしく、下記のように明示しなくても自動で設定が挿入される。 が、明示しないと不安なので明示している。

で、合成は成功した。以下はPhysical Viewerで全体を表示した様子。

これを見るとかなりのリソースを喰っているように見えるが、Device utilization summaryをみると、SLICEの使用率は9%と少ない。

タイミングも一応metしている。

上記結果のfmaxの値を見ると、500MHz (1Gbps)まではいけるかも??
それは後々確認することにして、今はリードタイミングについて確認をしなければ。


2013年6月6日木曜日

MachXO2 7000HE Breakout Board

久しぶりにFPGA評価ボードを購入した。
購入したのはMachXO2 7000HE Breakout Boardで、秋月電子で¥3,000だった。



データシートによると、7000HEはXilinxのSpartan3E 250Eとリソース規模的には近いようだ。
どの位のデザインが入るか見るために、以前 Lattice XP2用に作成したデザインをMachXO2用に修正して合成してみた。 システムアーキテクチャは以下の通りで、自作の32bit CPUとSDR-SDRAMC、カメラ(TCM8230MD) I/F、 VGA I/F、 タイマー(PWM)、 割込みコントローラ等から成る。


合成結果


SLICEのusageは78%だった。

MachXO2の良いところは、オンチップユーザフラッシュメモリがある点かなと個人的には思う。
例えば、A/DやD/Aを制御するデザインの場合、補正演算用のパラメータ等をフラッシュに持たせることができる。
そのうち、何か作ってあそぼっと。

2013年6月3日月曜日

LatticeECP3用DDR3 SDRAMCの作成 4

リードアクセスのバグはDQSBUFDのREADストローブのタイミングが原因だった。
ここは何か引っかかりそうだなと思っていたら、やはりそうなってしまった。

以下はバグありの場合の波形で、READストローブのLのタイミングがDQSの前半しか重なっていない。そのため、DATAVALIDがSCLKの1サイクル期間しか1になっていない。
リードは8バーストで行っているので2サイクル期間1になるのが期待する動作だ。


以下は修正後の波形だ。


DQSIはDDR3 SDRAMからドライブされる外部入力信号なので、DDR3 SDRAMの出力遅延やFPGAの入力バッファの伝搬遅延時間が重なり、FPGA内部クロックに対して遅れる。これに対して、READはFPGA内部信号なのでDQSI程は遅延しないが、この両者のタイミングが重なっていないとDATAVALIDが正しく生成されない。その上、READストローブはSCLK駆動信号なのでタイミング調整をしたとしてもその粒度は粗くなる。ということで、やはり、このREAD信号の部分は少々厄介だと感じているがどうか?? 一度合成しSTA(タイミング解析)をして実遅延を調べ、それを加味した状態でシミュレーションしたほうがいいかも知れないな。


2013年6月2日日曜日

LatticeECP3用DDR3 SDRAMCの作成 3

SDRAMC コア部を組み上げてシミュレーションを開始した。 SDRAMCの内部構成はこれまでのLPDDR SDRAMCやSpartan6用のDDR2 SDRAMCと同様だ。


単純な接続ミス等を修正してようやくベクタが流せる状態になったので、簡単なベクタを実行してみた。シミュレーションはMicronのDDR3 SDRAMモデルを接続して行っているが、エラーメッセージ等はでていない。


以下が上記ベクタ実行時の波形

リードアクセスにバグがあるようだ。。。う~ん、今日のところは時間切れだ。


TE0720 No.4 (BNN-PYNQを動かしてみる 2)

TE0720でBNN-PYNQを動かすことが出来た。 以下は前回に続いてBNN-PYNQが動くまでの記録。 gdb (GNU debugger)で例外が出る原因を調べてみた。 例外が発生しているのはシェアードライブラリ(python_hw-cnv-pynq.so)の中であ...