2014年2月25日火曜日

DDR2 SDRAMCの情報

このところ、どういう訳かDDR2 SDRAMコントローラの記事のページビューが多い。
DDR2 SDRAMコントローラを作るのが流行っているんだろうか?

現在時刻のページビュー

日単位のページビュー

週単位のページビュー

月単位のページビュー


閲覧者の内訳はこんな感じ





このブログの稚拙な文章では知りたい情報は得られないかもしれないので、役に立ちそうな情報源を書いておく。

・ DDR2 SDRAMのシミュレーションモデル
 VerilogのシミュレーションモデルがMicronのサイトから入手できる。
 DDR2 SDRAMの使い方や、仕様がよく判らない場合は、シミュレーションして動かしてみるのも一つの手だと思う。 大抵のDRAMはJEDEC規格に準拠している筈なので、実際に使うデバイスがMicron製でなくても仕様的には互換製があると思う。

    http://www.micron.com/products/dram/ddr2-sdram#fullPart

・ JEDEC規格書
 DDR2 SDRAMのJEDEC規格番号はJESD79-2* で、最新版はJESD79-2Fのようだ。
    http://www.jedec.org/standards-documents/docs/jesd-79-2e
    上記リンクアドレスは末尾が2eになっているが、リンク先のページでは2Fと表示されている。

・ Spartan-6のIODELAYやODDR等のハードマクロ
 User Guide UG381 に詳細仕様が記載されている。
    また、Xilinxの開発環境(ISE)をインストールしてある場合、インストール先のディレクトリ配下に各マクロのシミュレーション用モデルもインストールされている筈である。私はLinux版をインストールしており、私の環境では ****/ISE_DS/ISE/verilog/src/unisims/ にverilog版のシュミレーションモデルがインストールされている。  UG381の文書だけでは動きが理解しづらい場合は、このモデルを単体シミュレーションしてみたり、エディタで開いてソースを眺めてみるのも良いと思う。

・ その他
 以前、ELPIDAが「DDR2 SDRAMの使い方」というタイトルのユーザーズマニュアルを出していた。今でもネットで検索すれば見つかるかも知れない。

こんなところかな。

2014年2月23日日曜日

SDRAMCのMachXO2への実装 2

前回、150MHzでSDRAMのクロック系でタイミングエラーが1つ出ていた。
この構成ではクロックと他の信号とのスキューを同程度にしたくて、IOBのODDRXEというDDRレジスタを介してクロック出力していたのだが、このやり方を止めてPLLの出力を直接ピンに出すようにしたところ、タイミングエラーは出なくなった。スキュー調整はPLLの位相設定で行う。

そこで、クロックの上限を探って見たところ、160MHzまではエラー無しで合成できた。

が、しかし、このデザイン(160MHz)をFPGAにロードして動作させてみると、FAILする。
よくよく考えてみれば、実装しているSDRAMのタイミングパラメータは-7 (143MHz)品なので、160MHzはスペックオーバーである。そこで、クロックを140MHzにしてみたところ動作した。また、改めて150MHzを試したところこれも動作した。SDRAMに供給するクロック(下図のCLKOS)の位相は270°にしている。

150MHzは143MHzに対して+4.9%の値なので、動作マージンの範囲なのかも知れない。

動作している様子を動画撮影して、100MHz時と比べてみた。
手前が100MHz動作、奥が150MHz動作である。
video

ということで、150MHzまでは動作した。  すばらしい!  → MachXO2


2014年2月19日水曜日

SDRAMCのMachXO2への実装

以前このブログでSDR -SDRAMコントローラIPを作り、Spartan3E、Cyclone 3 (DE0)、 Lattice XP2に実装してみた。今回はそのコントローラをMachXO2に実装した。  このブログではメモリコントローラを作成することが多い気がするが、別にメモリコントローラが好きで好きでたまらないという訳でもないし、この分野の専門家でも無く、大容量の記憶領域を得ようとするとどうしてもFPGA外付けのメモリが必要になってしまうのでしょうがない。今回、MachXO2に実装しようとしているのも、目的はMachXO2 Breakout Boardを使ってロジアナもどき(なんちゃってロジアナ)を作りたいからだ。  GPIB IPの動作確認をしている時にバスの全信号を観測したいことが多々あったので、next themeとしてなんちゃってロジアナの作成をやってみることにした。

Breakout BoardへのSDR-SDRAMの実装は以前と同様のやり方で行った。
ちなみに、このBreakout BoardはCommunication Boxに組み込んだ物とは別の個体である。
Breakout Boardは予備の意味もあって3枚程所有している。

使用したSDRAMはISSIの128Mb(16MB) SDRAMでデータ幅は16bitである。
この基板のJ3, J5コネクタの信号は差動信号も考慮した配線になっている。

今回作るのはロジアナで想定している測定対象はGP-IBバス等の不平衡信号ではあるのだが、このJ3,J5の信号を信号入力用ポートとして使えば、色々と想定外の使い方の可能性も出てくる。このため、SDRAM用の信号はJ3,J5とは反対側のJ2,J4の端子を使用している。

RTLの方は以前作成したSDRAMCに若干の変更を加えている。
・ DDR2-SDRAMC等ではシミュレーションのために入出力バッファにSTA(静的タイミング解析)で得た伝搬遅延時間を加えているのだが、以前作成したSDRAMCではそれを行っていなかったので今回から加えることにした。  信号端をバッファモジュールに切り出した。

例えば、入出力バッファ(iobuf)は以下の様に記述している。

上位モジュール ... データ系

上位モジュール ... アドレス、コマンド系

iobufのソースをみて判る通り、モジュール内の遅延時間パラメータの値は0.0としている。SDRAMCはFPGAのハードマクロを使用していないので、各社のFPGAにも容易に実装できる。実際、以前のSDRAMC IP作成時にはXilinx Spartan3E、Altera Cyclone 3、 Lattice XP2に実装して動かした。なので、このモジュール内で特定の遅延時間を書いてしまうと、デバイスや実装が変わる度にその値を書き換えることになってしまい旨くない。そこで、モジュール内の値は0.0とし、テストベンチ側でdefparam文で実際の値を設定するようにした。

これ以外の変更点として、SDRAMの容量を64Mbから512Mbまで対応するようにした。


このSDRAMCを2種類のアーキテクチャで実装してみた。

1つ目

合成は成功、タイミングもMetした。

zumi32にメモリ R/Wチェックプログラムをロードして48時間程走らせてみたが問題なかった。

2つ目は、LFSRによるメモリR/Wモジュールの構成で、DDR3 SDRAMCの時に作ったやつの32bitバス版を作成した。

こちらも合成も成功した。


動作している様子
video

PC側のプログラムからFPGA内部のpass カウンタとfail カウンタの値をポーリングして表示している。FAIL_Cの値はゼロなのでエラーは検出されていない。
video

このアーキテクチャでSDRAMの駆動周波数を150MHzにして合成してみたところ、1つだけタイミングエラーとなった。

DRAM_CLK端子の最小パルス幅が9.614nsの為、これを越える周波数は設定できないようである。

無理やりコンフィグデータを生成し、FPGAにプログラムして動かしてみたところ結果は以下の様になった。

まったく駄目という訳ではなく、暫く動いてからFAILする。

ということで、このデバイスでSDRAMを動かす場合は100MHz当たりが上限と考えたほうが良さそうである。少なくとも、私のデザインでは。

2014年2月2日日曜日

Communication Box 25 (GPIB IPの作成 14)

今回は、サービスリクエスト、シリアルポールと割込み等の確認をおこなった。

・パラレルポール
パラレルポールであるが、現有GPIB I/F付き装置の資料を参照したところ、何れの装置も非サポートとあるため現状実機確認不可である。それほど積極的に使う機能では無いのかも知れない。

・シリアルポール
テクトロのオシロはアプリケーションメニュー機能というのがあって、画面にユーザ独自のメニューを表示して操作者がボタンで一つ項目を選択すると、GP-IBのサービスリクエストでイベントを通知させられる。 この機能を利用してサービスリクエスト、シリアルポール、割込みの動作確認をすることにしたのだが、シリアルポールで想定外の事象に遭遇した。またもや、私のGP-IB規格の解釈に誤りがあるのかも知れない。
 シリアルポールの手順は、コントローラがバスをコマンドモードにしてSPEコマンドをバスに送信し、次にTA_nメッセージでポーリングする対象をトーカーに指定する。それからバスのモードをデータモードにすると、指定されたデバイスはステータスバイトをバスに送信する。複数のデバイスをポーリングする場合はTA_n指定、ステータスバイト受信の処理を必要数繰り返し、最後にバスをコマンドモードにしてSPDコマンドを送出してシリアルポールを終了する。(バスに通知する。)
デジタルオシロに対してシリアルポールを行ったところ、以下のようになった。

右端の白い領域がオシロがステータスバイトを出力している部分で、写真の通り複数バイトが連続して出力されている。朝日新聞社編の「プロトコルハンドブック」によれば、このステータスバイトは標準的には1バイト長であるが、多バイト長でもよく最終バイトにはEOIが付加されるとある。

現状のIPはこの記述を参考にして複数バイトにも対応するよう作ってある。
上記で出力されるバイト列は有限長なのか見てみたのだが、何バイト受信しても途切れることが無く、また値はすべて同一であった。 ACタイミング的な問題を疑ってもみたのだが、以下のようにハンドシェイクに問題があるとは思えない。もしあれば通常のハンドシェイクも問題が出る筈だ。

そこで、HPのオシロではどうか見てみたところ同じ動作だった。




GP-620というGP-IBアダプタの場合は1バイト長であった。


GP-620の資料によると、この装置はNIのGP-IBコントローラを使っているようである。もしかすると、両オシロはコントローラが違うのかも知れない。即ち、この動作はコントローラ依存なのかも知れない。オシロの蓋を開けて内部を確認すればハッキリするがそこまではしたくない。
岡村廸夫氏の「標準ディジタル・バス(IEEE-488)とその応用」ではステータスバイトについて以下の様に書かれている。

ということで、この動作は規格上もあり得るものなのかも知れない。 ただ、そうなると一つの疑問が出てくる。 トーカー指定を切り替えるにも、また、シリアルポールを終了するためにも、コントローラはバスのモードをコマンドモードに変更して行う必要がある。しかし、ステータスバイト送出側がその完了を通知しない以上、どのタイミングでそれを行うべきかの判断が難しい。。。気がする。
何も考えずにATN信号を操作すると、ハンドシェイクのど真ん中でそれが行われる可能性もある。そのような場合でも問題なくモードが変わり通信が行われていくか・・・? そうなると、コントローラ側が意図的にハンドシェイクへの応答を止めて停止期間を作り、そのタイミングでモードを変える等の動作が必要になると思われる。 本IPの受信FIFOの深度は32段なので、その分の転送は止めようが無いが、FIFOからの読み出しを行わなければFIFOがFULLになった時点でハンドシェイクを停止させることは可能だ。そこで、このやり方で停止期間を作ってバスのモードを変更することにした。これはソフトウェアでの処理になる。 何とも泥臭い処理である。
また、念のためハンドシェイク停止時はNRFDがLとなるよう、gpib_lsn.vの変更も行った。


上記の処置をして動作確認を続けた。
ソフトウェアは以下の通り。 main()でメニューやサービスリクエストで上げるイベントの種別を設定後割込みを許可し無限ループに入る。  サービスリクエストが発生・即ち、SREQがLになると割込みが発生し、hw_interrupt()が実行される。

シリアルポール処理部

ここに示したプログラムはあくまでも動作確認のためのものなので、余計なprintfがあったり、関数の戻り値に実用性が無かったりする。

オシロの画面
 
メニューの右側のボタンを押下するとイベントが発生する。

プログラムの出力


一応、サービスリクエスト、シリアルポール、割込みも全ての要因ではないが確認は取れた。
後は測定器を制御したり測定値を吸い上げたりといったソフトウェアを作成していくことになるが、これは追々やっていくことにする。 ということで、これでGP-IB IPとCommunication Box作成のプロジェクトは終えようと思う。

今回のプロジェクトでは必要な部・機材関係を格安で入手出来る等、幾つもの幸運なことがあった。
LatticeのMachXO2を初めて使ってみたが使いやすい良いデバイスだと感じた。と言っても性能限界まで使っている訳ではないが。。。 もっと色々なものを作ってみたいと思わせてくれるデバイスではある。

RTL置き場 (http://www.hi-ho.ne.jp/bravo-fpga/)のsnapshotは最新版に更新した。



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

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