2011年12月30日金曜日

FUNCTION GENERATORの作成 3

鋸波、三角波、矩形波も出力できるようになった。 これらはDDSのphase accumulatorの値や、sin tableへの入力アドレス、符号信号を利用して生成している。


FPGAのBRAMは本質的にDual Port Memoryであり、sin(x) tableのROMもDual Port ROMとして生成している。このDual Portの利点を活かして波形生成機能も2CH持つことにした。 それぞれのCHで生成波形の種別や周波数、初期位相、振幅(減衰量)を個別に設定できる。また、両CHの出力について乗算(DSB変調波形の生成)・加算が出来るようにした。

以下はCH1側にDDS1とDDS2の乗算結果を、CH2にDDS2の出力そのままを出している。



以下はDDS2で三角波、DDS1で正弦波を発生させ、両者を加算した波形をCH1に出している。


ここまでの機能のDDS部とUART I/FでSpartan3E 250E用にRTLを構築して合成したところ合成できた。


まだDAC I/F部は入っていないがここまでの機能であればSpartan3E 250Eに実装出来そうだ。

2011年12月25日日曜日

FUNCTION GENERATORの作成 2

一応、DDS部のRTL作成が終わり、シミュレーションで動作確認をしている。
以下はdds_coreをテストベンチに4つインスタンスして、1.0Hz(基本波), 1.001Hz, 1.01Hz, 1.1Hzを生成させてみている。 phase_accumulatorの小数部は12bitなので、基本波の1/1000程度の周波数までは生成できる。ただし、前回のブログに書いた通り小数の場合は誤差はあり、1mHzは実際は0.9765625mHzになる。 (上記の周波数はDACのサンプリングレートを1usecとした場合で表している。 最終的には変わるかもしれない。元々1Hzから10MHz程度の周波数を生成可能にしたいと考えていたので、1usecでは10MHzが生成できないため。 現状、1usecとしているのは開発に使用するSpartan3A StarterKitのDACのサンプリングレートが1usec位になるためだ。)

動作モードとしては単一周波数をずっと出し続けるモードの他にSweepモードも持たせようと考えている。Sweepの種別は周波数が倍々で増加するoctave モード、10倍づつ増加するdecade モード、そして設定されて増分づつ増加するstep linear モードの3種だ。

step linear mode


octave mode

2011年12月17日土曜日

FUNCTION GENERATORの作成 1

ファンクションジェネレータはケースに入れて末永く使える物にしたいと思っており、その為にはFPGAも評価ボードではなく専用の物が欲しくなる。が、あんまりお金もかけられないのでFPGA部についてはSDR-SDRAMC作成で使用したSpartan3EのボードかLattice XP2のボードを利用しようと考えている。 でも、それにインプリするのはまだ先の話だ。 Spartan3A StarterKitはDACも搭載されているので、これを使って開発を行う。 それで今は正弦波発生部(DDS)の検討を行っている。正弦波はsin(n)のテーブルをROMに持っておき、ROMのアドレスを0から順次与えてROMのリードデータをDACに出力する。

正弦波テーブルはROMなのでnは角度値そのものではなくテーブルの要素番号になる。つまり、1周期をN分割してテーブルに持つ訳であり、1アドレスは2π/Nの角度に相当する。ROMにアドレスnを入れて出力を得るということはsin(n・2π/N)の値を得ていることになり、nを0からN-1まで1づつ増加させて得られる正弦波を基本波とすると、nをm倍の速度で増加させれば(n += m)、m倍の周波数の波形が得られることになる。でもこれだと基本波の整数倍の周波数しか得られない。1.2倍とか2.5倍等小数倍の周波数を発生させたい場合は何らかの補間処理が必要になる。この補間方法として直線補間または4点のラグランジェ補間を考えていた。

ラグランジェ補間は上記のような演算を行う。割り算があるが分母の各項は何れも既知なので定数化できる。また、乗算等の演算量も多い。 以下はN=360でnを0.1刻みにした時の直線補間とラグランジェ補間の比較だ。 何bitのDACを使うかは未定だがとりあえず16bitDACを使うという想定で、正弦波の最大振幅は32767にしている。波形は両者差が無いように見える。

以下は理想値に対する誤差だ。

これを見ると直線補間の方は最大1.3 digit程度の誤差が発生するのに対してラグランジェ補間の方はほぼ0となっている。ところが、上記の計算では振幅の量子化(小数点以下の切り捨て)をしていなかった。量子化した場合は以下のようになった。

これをみると、ラグランジェ補間の方も最大1digitの誤差があり、直線補間と大差なさそうなので直線補間で行くことにした。 次に1周期の分割数Nは幾つがいいか?  小さいと直線補間での誤差が大きくなり、大きいとテーブルサイズが大きくなってしまう。 Nを上図の10倍の3600とし、DACのサンプリング周期を1usとした場合、目標仕様の下限周波数1Hzを作るためにはnは1us x 3600 = 0.0036刻みにしなければならない。 駆動周波数にもよるとは思うが(たぶん)float adderはlatencyが1以上かかるので、phase accumulator部は固定小数演算にしたい。その場合、固定小数の小数部が何ビットあれば0.0036を十分に近似できるだろうか? 整数部は分割数N、つまり3600が表現できる必要があるので12bit必要で、phase accumulatorが32bitの場合小数部は32-12=20bit、この20bitで0.0036を近似すると0.003599・・ (99.977[%])と%オーダーの誤差になる。 FPGAに入力される源振(水晶発振器)の周波数精度はppmオーダーなので、%オーダーではちょっと残念だ。 せめて整数Hz(1Hzの整数倍)は精度よく出したい。 そこで分割数Nは1000000(20bit)、小数部を12bitにしようと思う。 この場合、テーブルサイズがめちゃめちゃデカくなってしまう。正弦波は相似形な波形なので1/4象限のデータのみをテーブルにして他はそれを写像して作り出すことはできる。そうするとテーブルサイズは1/4の250000になる。振幅の最大値を32767にするのでデータのbit幅は15bit、したがってそのままでは250000 x 15 = 3750000、 3.5Mbitの容量のROMが必要になってしまうが、以下の方法で圧縮できるはずだ。 250000を例えば4要素毎の区間に分割し区間内では先頭のみ15bitデータ、他は前方の要素との差分とする。

sin関数は0の部分が最も変化率が大きいが、今検討している分割数の場合その部分の変化率(差分)は1以下なので差分は1bitで表すことができる。ということは4要素の場合15bit x 4 = 60bitが18bitと1/3に圧縮できる。要素数を増やせばさらに圧縮率は高くできる。また、この方式は直線補間をする上でも都合がいい。 直線補間は以下のような演算になるが、Δy10は差分値がそのまま使える。 Δx10は要素nとn+1の差なので1、(x-x0)はphase accumulatorの小数部になる。したがって、差分値が1か0かでy0に小数部を加算する・しないを行えば良い筈だが、テーブルのデータが既に15bitに量子化されていてかつ出力するDACも16bitだとすれば、小数部をそのまま加算する意味は無いので、実際は小数部を四捨五入して加算するようにする。

テーブル1要素のデータ構成、即ち、何要素でグルーピングするのがいいかについて検討する。
上記では4要素の図を示したが、実際は直線補間のためにもう1要素(例えばP0~P3とP4)必要になる。要素数に対する圧縮率とROM容量を計算すると以下のようになった。

要素数30位から飽和している感じで、要素数32の場合ROM容量はおよそ370Kbitだ。冒頭に書いたようにターゲットFPGAはSpartan3E(XC3S250E)またはLatticeのXP2(XP2-5)であり、これらのBlockRAMの容量は250Eが216K、XP2-5が166K、・・・・・うぅぅ、はいらねーーー、くそー もうひと工夫必要だ。
テーブルに書くデータをCプログラムを書いて生成してみた。右側8桁が差分情報だ。

ここで差分データからuniqなデータ数を数えてみたら734個だった。

そこで差分データのuniqなパターンに固有番号を付与してテーブルにはその番号を書くようにすれば、32bitのデータが(734個なので)10bitになる。したがってROM容量は(15bit+10bit) x 7813 word = 195.325KbitになるのでXC3S250Eにはギリギリ入りそうな感じだ。伸張処理では番号をビットデータに戻すためのテーブルが必要になるがこれは分散RAMで作るしか無いだろう。分散RAMは38Kbitあり、必要な容量は734x32bit = 23.488Kbitなので入るんじゃなかろうか?  厳しいかなー??? ・・・待てよ! MicroBoardを使う手があるぞ。あれならSpartan6 LX9でEBRは576Kbit, 分散RAMは90Kbitなので余裕のよっちゃんだ。おー、250EでダメだったらMicroBoardにしよっと。

2011年12月12日月曜日

next theme

毎回、毎回、同じようなのばっかりやってても進歩がないので、次のテーマはアナログっぽいのをやることにした。 具体的にはファンクションジェネレータを作ろうと思う。 以前から実験用に1台欲しかった。秋月などで完成品を売ってるが結構な値段するので、なかなか手が出ないし、頑張れば自作できそうな気もする。あくまでも自分で使うだけなのでそれなりに機能すれば良い。 今現在のざっくりとした構想としては、正弦波、矩形波、三角波等の他、任意波形の出力。 正弦波はDDSで生成する。任意波形はDRAMに波形データを書いておいてそれを再生する方式にする。周波数範囲としては1Hz ~ 10MHz位は欲しいなぁ~。 正弦波と他波形の加算・乗算などもできるとうれしいかも。 アナログは殆ど素人なので、最終的にどんなものが出来るかわからんがやってみよう。

2011年12月11日日曜日

2011年12月1日木曜日

(LP)DDR-SDRAMCの作成 3

内蔵CPUによるMemory R/Wは32bit単位でSingle Accessなので負荷としては軽い。 そこでいつものようにDRAMに画像データを置いてVGA I/Fに表示させた。これだとReadだけではあるがBurst Readが繰り返し発生する。 VGA I/FはSpartan3A Starter KitやDE0のように抵抗ラダー式にした。


画像サイズはXGA (1024x768)にした。 表示素材はNASAのImage Galleryから入手した。


表示のチラつきやノイズ等もなく綺麗に表示されている。

元々このSDRAMCではDRAMをSelfRefresh Modeにすることも出来るようにしていたが、もう少し進めてSelfRefresh時にDRAMへの供給Clockを止めたり、またSDRAMC停止時にはDeepPowerDown Modeにするようにした。 以下はSimulationで確認している様子。


SelfRefreshに入るところ


SelfRefreshから抜けるところ


停止(Deep Power Down)に入るところ


一応安定に動作できているので、いつも通りRTL一式を以下で公開した。
http://www.hi-ho.ne.jp/bravo-fpga/

2011年11月28日月曜日

(LP)DDR-SDRAMCの作成 2

何点か修正箇所はあったものの、合成の方はわりとすんなりとMetし実機での動作確認も上手くいったのだが、一つ大きな勘違いをしていた。それは、FPGAのSpeed Gradeを最速の3にしてしまっていたことだ。 MicroBoardに実装されているのは2なのでこれではいけない。(とは言え、実機では動作しているのだが。。偶々かも知れない。) そこで、Speed Gradeの設定を2にして合成し直してからが大変だった。なかなかMetしてくれない。 RTLのあちこちを修正し、ISEのDesign Goals and StrategiesをTiming Performanceにし且つMap PropertiesのStarting Placer Cost Tableの値を3にして漸くMetした。


Memory R/W TestのProgramを走らせていてPassする度にLEDを点滅させているだけなので面白みにかけるが、以下は動作している様子だ。


Memory Readの為のCalibrationは無しで動作できている。
LPDDR(Mobile DDR)はDLLを内蔵していないため、tACの振れ幅がものすごく大きい。
普通のDDRの場合は±700ps位の値だ。

JEDECの規格書から引用


これに対してLPDDRの場合は2.0ns~5.0nsもある。

JEDECの規格書から引用


MicronのDatasheetから引用




このtACはClockに対するDQの出力遅延で2.0ns~5.0nsもの振れ幅がある。 勿論動的にjitter的にこの範囲で揺れ動く訳ではないのだろうが、こんだけ幅があるということは、DQをFPGAのIDDRで取り込む場合に、Clockの立上りから取り込みが始まる場合と、立ち下がりからになる場合があるということだ。 以下はMicronのMobile DDR Simulation Modelを使って本SDRAMCをSimulationした波形だ。下がtACが5.0nsの場合で上は2.0nsの場合だ。



波形下部のw_dinはIOBUFの出力、w_din2はIDDR2の出力部だ。 IOBUFとIDDR2間にIODELAY2を置いてこの遅延量を調整(Calibration)しようにも、最大では1Bit期間(2.5ns)以上も遅延させることになり無理が有る。 そこで、本SDRAMCではDQSの値からDataの順序を判定するようにしている。 DQSはH→Lの順に振れるのでHがどのClock Edge側で取り込まれているかで判定をしている。 勿論、DQ、DQSのEdgeがIDDR2のSetup/Holdに引っかかる場合も有り得るので、IODELAY2による遅延調整もできるようにしているが、これはあくまでもSetup/Hold違反の為の調整であって、取り込みEdgeの調整用ではないということだ。

結局PHY_DP部は以下のようになった。

Write系


258行目のfor calibrationはIODELAY2自体のCalibrationの為のState Machineだ。IODELAY2は最初に(あるいは適宜)入力信号(Bit信号)の1期間を教える必要がある。本SDRAMCでは起動時に自動でCalibrationを実行する。また、任意のTimingでSoftwareからこのState Machineを起動することもできる。


以下はCalibrationの様子。Bit期間を教えればいいので、FPGAからDQとDQSを出力しこれをIDDR側にU Ternさせて調整をさせている。


DQSはmclk、DQはこれに270°位相遅れのmclk_270で駆動している関係で、どちらかを遅らせて位相を合わせる必要があるが、現状はDQSの位相を遅らせている。具体的にはDQS側のIODELAY2のIDELAY_TYPE値をVARIABLE_FROM_HALF_MAXにしている。Calibartion完了後、IODELAY2にRSTを印加するとこの遅延値に設定される。


Read系

2011年11月20日日曜日

(LP)DDR-SDRAMCの作成

AvnetのSpartan6 FPGA LX9 MicroBoardはLPDDR-SDRAMが実装されていて、これをTargetにして(LP)DDR-SDRAMCの作成に挑戦している。 (LP)の意味はLPDDRの特徴である省電力機能(部分的SelfRefresh等)の利用を特に意識していないためである。 で、一応RTLは出来た。自作のSDRAMCとしてはDDR2-SDRAMCとSDR-SDRAMCがあるが、今回はSDR-SDRAMCのRTLを元にDDR用に発展させる形にした。下図がブロック図である。


SDRAMは200MHz、FPGA内部(MPIF側)は100MHzで動作させる。 MPIF側のBus幅は64bitにした。MPIFのI/F仕様はbit幅が広がった点を除いてこれまでと同様だ。


PHY_CP部は以下のようにした。


最下部のassignで#3.29の遅延を付けているがこれはSimulation用に付けており、実回路での遅延を目的としているものでは無い。
PHY_DP部のWrite側は以下のようにした。


今回はSpartan6をTarget Deviceとしているが、別種FPGAへの移植も一応念頭においてRTLを作成した。具体的にはDDRの部分はDeviceによって細部が変わる可能性があるためdc_ddrio, dc_ddroというmoduleにした。
そのdc_ddrioであるが、現状以下のようになっている。

(出力系)


Spartan6では出力信号をODDRから出す場合、OEN信号もODDR出力でなければならないようだ。(Spartan3Aの場合はそういう制約はなかった。) また、Clockも共通になる。

(入力系)


IOBUFからIDELAYを通ってIDDR2に行く。
本DDR-SDRAMCではDQSではなく、DQの位相を制御する。
このIDDR2の出力を受けるPHY_DPのRead系は以下のようになっている。


Clock生成はDCMではなくPLLを使う。


PLLでmclk(200MHz)、mclk_270 (mclkの270°遅れ位相)、vclk (25MHz)を生成している。 bclk(100MHz)は、PLLの外でmclkを分周して作成している。これはClock載せ替えのGearBoxでbclkのValid Timing信号(bc_vldで、これ自体はmclk同期)が必要で当然bclkとH/Lの関係が確定している必要があるためこのようにしている。

以下はWriteのSimulation波形だ。


Writeの場合DQSとDQ,DMは90°の位相差が必要だが、このCONTROLLERではDQ,DMの位相をずらしている。(つまり、DQSはCK_Pと同位相)

以下はReadのSimulation波形だ。



MPIF側のCommand受信からRead Data出力迄のLatencyはBankが閉じている場合(Bank Activeが発生する)は13、開いている場合(Bank Activeは発生しない)は11になる。

合成でTimingはMetした。


さてさて、後は実機に流して動作確認になるが、上手く動くか?
IDELAYのCalibrationが必要になると思うがこれからかな?

2011年11月15日火曜日

ガニメデの優しい巨人

創元SF文庫のジェイムズ・P・ホーガンの「星を継ぐもの」シリーズにはまっていて、今は「ガニメデの優しい巨人」を読んでいる。 これのp217の記述 「ハードウェアの構成自体がプログラム可能であって ~   言うなれば、ソフト・ハードウェアだな。」ってまるでFPGAだね。。。この作品は本当に面白い!!

この作品のCopyright情報によれば、「INHERIT THE STARS」(星を継ぐもの)は1977 in USA、「THE GENTLE GIANTS OF GANYMEDE」(ガニメデの優しい巨人)は1978 in USAとなっている。一方、Wikipediaによると、「プログラム可能なロジックアレイ、論理ゲート、論理ブロックといった基本概念は1985年、David W. Page と LuVerne R. Peterson の取得した特許に既に見られる」そうだが、これの出典である特許(http://www.google.com/patents?id=BB4vAAAAEBAJ&dq=4508977)によるとFilling date(申請?)が1981年、特許内で引用している他の特許でもっとも古いのが1971年のものになっている。作者ジェイムズ・P・ホーガンの作品中の上記記述は彼の独創によるものなのか、それとも作品とほぼ同時期に発明されていたPLA (Program Logic Array)の概念について既に知っていたんだろうか・・・ どうでもいいっちゃどうでもいいことなんだけど、ちょっと興味があるな。

2011年11月13日日曜日

Spartan6 FPGA LX9 MicroBoard

AvnetのSpartan6 FPGA LX9 MicroBoardを入手した。

このBoardはLPDDR-SDRAMを実装しており、DDR CONTROLLERを作ってみたいと考え入手したのだった。また、PMODというUser I/O用のConnectorも有るので、例えばDVI出力もできるかも知れないと期待してのことだった。。が残念なことにPMODはFPGAのBank1の端子が使われている。 DS162によるとBank1は差動系のI/Fは殆ど使えないようだ。遊び心がないなぁー Avnetって。 それにU60_xlx_s9_lx9_fpga_microboard-ug022811.pdfというUser Guideによると、PMODはBank0になってるんだけどな。。。



でも、DDR CONTROLLERの作成はできると思うので挑戦してみよう。

自作CPUで遊ぶ 22

今使用しているモータードライバはDM556Dというものだが、このドライバはMicro Stepが 800 [pulse/rev] 〜 40000 [pulse/rev]の範囲で設定できる。 Mi...