« 2010年3月 | トップページ | 2010年5月 »

2010年4月の4件の記事

2010年4月30日 (金)

FPGAの外付けSRAMアクセス成功

VerilogHDLに親しむ(4/24/2010)
 SRAMをアクセスするテストベンチのステートマシンの擬似コーディングを少しづつ、実際のVerilogHDLのコードに移していく。折角だから7セグLEDにも登場してもらって、SRAMへの蓄積バイト数を表示することにする。

 7セグLEDはあれから、また2つモジュールを増やして6ヶにした。こうしておくと、この7セグ基板はこのあとデジタルクロックに活用できる。VerilogHDLのドライバーも6ヶ用に改修する。コーディングに慣れてきて鼻歌が出る。

A4302870

 UARTは、前のステップのコードをそのまま流用する。モジュールを別ファイルにしてあるので移植は簡単だ。今度は本格的なステートマシンである。HDLの開発にだいぶ慣れては来たが、まだregとwireの区別を完全に理解しているわけではない。トップモジュールで使わない変数は、いちいちあらたに定義しないでモジュール間でスルーできるはずなのだが、自信がない。それでもトップモジュール、top_sramは徐々に形をなして完成に近づいてきた。

 この過程が楽しい。電子工作の醍醐味は、自分で考えたロジックやプログラムが実際に思ったとおりに動いたときである。コーディングしているときはこれで果たして動くのか不安でならないが(プログラムは書いたとおりにしか動かない)、デバッグをやりとげて実際に想定どおりの動きをしたときの喜びはなにものにも換えがたい(だから人のソースはわざと見ないようにしている)。

 プラモデルや、キットを組み立てるのも、それはそれで楽しいが、自分で設計図を引き、材料を揃えて、いちから作り上げた模型飛行機が実際に空を飛んだときの興奮とは比較にならないのと同じである。

また、基板付録のついた雑誌を買ってしまった(4/25/2010)
 FPGAプロジェクトの第二ステップのコーディングがそろそろ完成かというところへ、思わぬ横槍が入った。気がつけば今日はInterFace誌(6月号)の発売日である。今月号は大物の基板の付録がついている。クロック144Mhzの32ビットプロセッサー、ルネサスSH-2A(SH7262)の基板である。

If1006

 どうしようか迷ったが、付録基板企画史上最速のプロセッサーという触れ込みだ。これだけのスペックのCPU基板が¥2000台で手に入る機会はこれを逃せばまずないだろう。破格の値段というのに弱いのが当研究所の所長の特徴である。

 やっぱりこれは買うしかない。近くの書店で手に入れた。使うあてのない基板がまた増えてしまった。去年のデジタルデザインテクノロジー誌(2009年春号)のLatticeのFPGA基板も手に入れたまま、まだ何もいじっていないと言うのに。

 これだけの性能のプロセッサーは、そろそろアマチュアでは簡単に使いこなせないレベルにある。何らかのリアルタイムOSを入れないと恐らく満足に動かないはずだ。基板はともかく、雑誌の記事の内容はもともとあまり期待していなかったが、今度も正直言ってがっかりした。

 あいかわらず、サンプルはLED点滅しかない。もう少しこのCPUを生かせる解説はないものだろうか。TOPPERS/JSPを標準OSと想定しているのなら、このあたりのインストールの解説か、ライブラリを使ったLCDかUARTへの「Hello World」、それが無理でも、全体のシステムの初期化(メモリ、クロック、タイマー、I/O機能)の解説でもあれば、先につながるのだが、LCDコントローラー、USBコントローラーなどペリフェラルの紹介だけでは、読者は期待だけ持たされ、目隠しされて海に放り出されるようなものである。

 このLEDの点滅のプログラムも、見れば6つの初期化プログラム、5つのヘッダーファイルをincludeして始めて動く。このへんを系統だって分かり易く説明するのは確かに大変だが、これではLEDを点滅させた後、殆どの読者は手も足も出ないだろう。

 熟練者なら何をしなければならないかがわかっているから、ソースコードや、Webを頼りに少しづつ環境を整えていけるだろうが、慣れない人には8ビットマイコン程度ならともかく、32ビットの大規模、複雑なソフト環境の中を先に進むことはまず絶対不可能である。

 電子工作はひとつひとつの手順に難しいものがあるわけではない。ただその要素が膨大に多いだけである。こんどの記事で、始めては見たが電子工作は難しいと離れていく人がまた増えるのではないかと心配する。

 それにLEDを点滅させただけで、有り余る機能を持ちながら、そのあと何も使われずに部品箱に放り込まれてしまうプロセッサーが不憫でならない。

 まあ、雑誌の記事にあまり多くを期待しすぎるのかもしれない。なんといってもこのスペックの基板が付録についてくる良い時代に生まれたことを感謝しよう。

ステートマシンは動いたがSRAMがアクセス出来ていない(4/28/2010)
 それはともかく、FPGAプロジェクトである。UARTからの入力をSRAMに蓄積するテストベンチのコーディングが完成した。ステートマシンに慣れてきたので、ステートを2つ追加して、入力の前にDOSプロンプトのような>を出し、入力か出力かがわかるようにする。SRAMのアクセスに今ひとつ自信がないが、UARTのやりとりはだいぶ慣れてきた。

A4302871

 HDLができたので、アドレス18本、データ8本、7セグの制御線14本のピンアサインを慎重に行う。このピンアサインは機種を決めるとちゃんと既に設定したピンや、Vccなど信号線でないピンは設定できないようになっている。始め、入力を受け付けないので開発環境のバグかと少しあせったが、向こうの方が賢かった。この開発環境を少し馬鹿にしていた自分を恥じる。

 ファームができた。いよいよテストである。緊張の瞬間だ。今度のコードは未経験のステートマシン、SRAMのアクセスが入っている。まあ、最初から動くことは余り期待していない。電源を入れ、iMPACTを始動させてプログラムを書き込む。

 おお、UARTの端末にプロンプトの>が出た。キーボードを叩く、文字が出た。良いぞ、このあたりは動いているようだ。おやあ、文字は同じ>のままで増えていくだけだ。SRAMに入れたデータを端末に戻すキー、リターンキーを押す。何も表示されず、カーソルだけが最初に戻った。

 さあ、これからが本番だ。久しぶりの少しまともなプログラムのデバッグに心が躍る。事件の現場に乗り込んだ刑事の心境である。目の前に犯人の残した沢山の証拠がある。この証拠を元に何が原因でこれが起きているかをつきとめ、正しく事件を解決していく。

 まず、現在、起きている状況をなるべく詳しくメモにする。まとまったら、それに対して仮説をたて、ソースコードを検証していく。暴走か、全くの沈黙では仮説の立てようがないが、こんどは結構動いて証拠を残してくれている。

 少し調べただけで、いくつかのミスが見つかり、SRAMのテストベンチは、とりあえずUARTからのデータ入力を受付け、出力はされないがリターンキーで次の入力を受け付けるところまで動いた。7セグには受け付けたバイト数がちゃんと表示され、リターンキーを押すと0に戻る。

 実際の出力がされないのは、バイナリー端末(アクノリッチ)で、入力した最後のデータ(改行)を入力バイト数だけ出力していることがわかった(改行の連続なので普通の端末で

Acktitle_2

はデータがないように見える)。

Ackbin_2

 SRAMにデータが入っていないか、正しくとりだせないかだが、UARTのステートマシンのところはほぼ想定どおりの動きをしていることがわかった。やっぱりSRAMのアクセスがうまくいっていない。この確認は実際にSRAMに所定の信号が入っているか調べるしかない。これ以上の机上デバッグは無理である。オシロをとりだして、実際の動きを確かめることにする。

SRAMの読み書き成功。しかしUARTにゴミが残る(4/29/2010)
 オシロで見た結果は一目瞭然だった。CE(ChipEnable)が一旦、アサート(L)になると、元に戻っていない。CEは今の状況では大きな問題にならないが、WEは書き込みenableになったままなので、いつまでたっても読み込めない。動作しない原因はわかった。でもどうして制御線が元に戻らないのか。SRAMモジュールでは1クロック回した後、CEなどを戻している。

 SRAMアクセスの部分をさらに念入りに調べる。タイミングチャートを描いてみて原因がわかった。FPGAのHDLは、クロックが同じだと、すべてのモジュールが同時に動く。リクエスト/ビジーの連携は、必ずクロックをひとつ遅らせないと正しい結果を受け取れない。そうか、SRAMモジュールにもステートマシンを入れて順序処理にしてやる必要があるのだ。

 単なる繰り返しで処理をしていたSRAMアクセスにも、アイドル->アクセス->ウェイトの3つのステートマシンにして、コーディングしなおす。よーし、これで動くはずだ。胸が高鳴る。さあ、どうだ。ターミナルを立ち上げ、適当な文字を入れてリターンキーを押す。やった。やりました。見事に入れた文字列が戻ってきた。頭の部分が少しおかしいが、あとは正確に表示してくる。いいぞ。

Example2

 最初の1文字だけがおかしいが、あとは完全だ。200バイト以上の日本語テキストをカット&ペーストで入力し、リターンキーを押す。よし、これも出来た。これでSRAMの読み書きが実現した。念のためロジアナを引き出して、制御の様子をとってみた。きれいにリターンキーを押した時の、書き込みと、そのあとの読み出しのCEのパルスが見えた。オシロではCEのパルスがひとつしか見えなかったが、時間的にこれだけ離れているので安いオシロでは観測不能であることが良く分かる。

Sram1

 最初の文字が化ける理由は、SRAMではなくて、UARTの不具合である。SRAMが原因でないことは、リセットボタンを押してプロンプトを出すところから化けるので間違いない。連続して文字を送るときは問題ないが、最初の文字がどうもうまく送信されないようだ。

 このUARTのコードは、雑誌からの借り物である。リクエスト/ビジーの連携が上手く行っていない感じだ。色々、ウエイトを入れたり、判断ロジックを入れたりしたが、どうしても直らない。暫く苦闘したが、解析は当面諦めることにした。FPGAプロジェクトの目的は別のところにある。こればっかり

Sram2

やっているわけにはいかない。いまひとつすっきりしないが、とりあえずの目的は果たした。

 休日のほぼ一日をつかって、SRAMのアクセスが遂に実現した。第二ステップ終了である。ロジアナに見るように、SRAMアクセスとしては超遅い読み書きで、これからどれくらい速度を上げられるか、同時読み書きの検証をどうするか、課題はまだ山積しているが、FPGAプロジェクトは先に進めよう。次は、いよいよ本来のディスプレイのRGBインターフェースの作成である。

| | コメント (3) | トラックバック (0)

2010年4月22日 (木)

外付けSRAMを制御するFPGAのピンが足らない

 FPGAでビデオインターフェースを作るプロジェクトは、シミュレーターのインストールに道草を食ってしまい、第二ステップは、まだ基本的な仕様がかたまっただけである。このステップの目標は、外付けSRAMの制御をマスターすることで、UARTを通してメモリにデータを蓄積し、そのあとリターンキーの入力でそれを吐き出させる機能を開発することにしている。

 本来のFPGAの目的であるビデオインターフェースは、電源を入れれば、ただひたすらVRAM(SRAM)にあるフレームデータをアナログビデオ信号に変換して出力することだけである。複雑なシーケンス制御は想定していない。考えてみれば、UARTなどを使った順序制御の必要はない。

S_a4172842

 しかし、プロセッサーとの間はバス接続でなく、シリアルのSPIを考えている。とすると、まだ仕様は考えていないが、SPIから来るビデオデータの頭を知るための何らかの順序制御は必要になる。それにFPGAの勉強としては恰好の題材でもある。少し回り道だが、UARTでの制御にこだわってみることにした。

ステートマシンを理解する(4/15/2010)
 UARTからのデータ入力は、キーボードからの手入力または、端末ソフトでのカットアンドペーストか、ファイル転送すれば、高速でメモリを書くことになる(といってもUART以上の速さにならないが)。FPGAのUARTは幸いなことに完全な全二重である。エコーバックも問題ないはずだ。

 頭の中だけで考えていたステートマシンの詳細設計に入った。メモを沢山書いて頭を捻る。ちょっと勉強しただけでこんなことを言うのもおこがましいが、ステートマシンには汎用性がなく、構造化することが出来ないので少し複雑なことをしようと思うととても面倒なことになることがわかった。

 例えば、同じ処理が出てくるので(UARTの送信など)、普通のプログラミング言語の関数のように処理ブロックを使い回しすることを考えたが、フラグの制御が大変で、かえって構造が複雑になる。階層構造には出来ない。ひとつのalwaysループから外のモジュールを制御するのは、例のリクエスト/ビジーフラグ方式が必要で、処理が複雑になり、しかもどうやっても1クロックづつ遅れる。

 それでも、段々形になっていくと、もっと良い方法がないかと夢中になる。最後の方では仕事の帰りのバスの中で急に思いついて、忘れないよう手帳を取り出してメモをとるくらいまで熱中した。最初、20近くあったステートは、最終的には6つまで減らすことが出来た。

S_a4202843

 要するに、ステートマシンでの1ステートは、プロセッサーの命令ひとつと割り切って汎用性を考えず、泥臭く重ねるしかないようである。FPGA内にわざわざリソースを使ってCPUコアが作られ、使われている理由がわかる気がしてきた。確かに複雑なステートマシンは本人以外のデバッグがとんでもなく難しいものになりそうだ。

 ステートマシンの詳細設計がほぼ出来た。まだ擬似コーディングのレベルだが、何回か検証して動く自信が出てきた。負けず嫌いなので、出来上がってからウェブでみんながどうしているか調べる。よーし、同じようなことをしているようだ。知らないときより記事の理解が早い。やっぱり自分で苦労するのとしないのでは大違いだ。さあ、次はメモリの実装である。

ハンダ付けをしようとしてFPGAのピンが足らないのに気づく(4/18/2010)
 最初に、17本のアドレス線をハンダ付けする。SRAMの固定は迷ったが、直接ベース基板にハンダ付けした。ピンアサインを確かめる。うーむ、分散していて接続線を同じ長さにすることは難しい。クロックは今のところオリジナルの33Mhzで動かすので少々長さが違ってもまだ大丈夫なはずだが心配になってきた。

 計算してみる。光(電気)の速さは、毎秒3×10**8m(10の8乗)、SRAMの最小アクセス10nsは、クロックが100Mhzということで、100×**6ヘルツ。そうか1クロック3mもある。配線長が問題になるのはギガヘルツ以上でこの程度ではまだ全く問題ないようだ。安心した。

S_a4202846

 配線が10本以上になる時は、アートワークをした方が良い。単にピンとピンをつなぐだけだが、ピッチ変換基板は2段に分かれており、前に偉い目にあったことがある(Mega128 のSDカード付き基板 08/09/09)。用心してアートワークから始める。アドレスは17本でデータは16本である。このピンアサインをしていて重大な誤りに気づく。SRAMの制御線のことを全く忘れていた。半田付けする段階で気づくというのも、お粗末な話だが、このあいだアドレスを一本減らして何とか詰め込んだFPGAのピンが2本以上また足らなくなってしまった。

 チップイネーブルとか書き込みイネーブルなどの制御ラインである。SRAMの制御は色々なやり方があって、データシートには3種類を越えるタイミングチャートが出ている。絶対必要なのは、読み書きを区別する書き込みイネーブル(*WE、*は負論理)だけではあるが、それでも1本足らない。

 色々考えたが、ピンをうかせるため、データを8ビットにして、512KBのメモリの半分だけを使うことにする。QVGAの16ビットカラーのフレームサイズは154KBなので、半分の256KBでも大丈夫だし、今のテストフェーズでは、16ビットのデータハンドリングはかえって面倒だ。アドレス線を当初より1本増やす必要があるが、データ線の8本が浮くので残りを制御線にまわせる。前に美しくないと言っていたやりかただが、背に腹は代えられない。

SRAMのピン位置を間違えていた(4/22/2010)
 SRAMとFPGAとの配線はすべて終了した。UEW線は交差させないという当研究所のルールは守れそうにない。電源ライン、データライン、アドレスラインが派手に交叉する。50Mhzを越えると汎用基板では不安定になるというWeb情報もあるが、今さらもう遅い。動かしてみるしかない。まあクロックは33Mhzでも十分余裕があるのでこの程度なら何とか動くだろう。基本的には私は超楽観主義者である。

S_a4202847

 制御線は、何を採用するか迷った。SRAMのデータシートをもういちど丹念に読み直す。read/writeともいくつもの方法があり、どれにするか迷う。*OE(Output Enable)というのがどうも理解できない。Highのままでも書き込みができるようなのだが、真理値表では*WE(Write Enable)がL、つまり書き込みのところでは、*OEはX(不定)となっていて何のためにあるピンかよく分からない。

 結局、ピンは余っているが、一番オーソドックスな方法に見えるアクセスの度に、*CE(Chip Enable)を下げ、*WEを読み込みのときHigh、書き込みのときにLowにする制御でコーディングをすることにする。

 ハードの準備は全て終わった。あとはVerilogHDLのコーディングを残すだけとなった。しかし、実は前から気になっていることがある。それはCY7C1041DのSRAMの第一ピンの位置である。普通、ICチップの1ピンの位置はチップの上に刻印などのマークがあってすぐ分かるようになっているが、写真にあるように、このチップは、ちょっと目にすぐわかる大きめの丸印と、よく見ないと見えない、小さな刻印が対角線上についている。

S_a4222867

 最初、小さい方の刻印を見落としていて、大きい丸印を1ピン側とみて気楽にピッチ変換基板にハンダ付けしたのだが、どうも違うような気がしてきた。このチップはVccとグランドピンがピン列のちょうど中間に2組出ていて、それぞれがたすきがけになっており、逆差しをしても致命的なことにならないようにはなっているが、間違えれば当然全く動かない。

 データシートの外見図には、型番などの表記はなく、1ピンの小さな丸印の絵が右上の大きめの丸の位置についているだけで、小さな丸の表示はない。外見図の位置からすると、大きな丸が1ピンのマークのようにも見えるが、どうもおかしい。

 Webにあたってみるが、個別のチップについては全くヒットしない。しかし一般的な話では、丸の刻印が3つもあるICチップの1ピンの見分け方の説明があって、大きい丸印はモールドを流し込む時の射出孔の跡らしく、小さい方が1ピンマークだという。どうも、このチップも小さい刻印の方が1ピンのマークのように思えてきた。

 逆さまにつけてしまったようだ。表面実装ICのとりはずしは、サンハヤトの特殊ハンダ入手以来、そう難しくはなくなったが、それでも一大決心がいる。はずしたけれど、やっぱり元のままで良かったなどという悲劇は避けたいので、さらに調べる。

 解決は意外なところにころがっていた。当研究所では、パーツは常に予備と確認のため複数買うことにしている。予備のSRAMを取り出して調べてみた。すると裏には大きめの丸印2つと、小さな丸印があり、この小さな丸印の位置が表側の小さな丸印と一致したのである。うん、間違いない。小さい方が1ピンのマークだ。いやあ、良かった。これで確信を持ってチップを外せる。

 何回目かのSMD(表面実装チップ)のとりはずしは、順調に行った。少し大きめ(30W)のハンダごてで、低温ハンダを両側に流し、半田ごてを往復させると、またたくま(3秒くらいか)に、チップが、ずるっと浮いてくる。このハンダがなかったころ、細い銅線を使って苦労してはずしていたことを考えれば、うそのような簡単さだ。\4000以上するが悔しいけれど実に強力である。

 ハンダ吸い取り線で低温ハンダを念入りにとり、洗浄剤で綺麗にして、もういちどSRAMをハンダ付けする。よしうまくついた。これでハードの心配はすべて解消した。いよいよ残るは、コーディングである。

| | コメント (4) | トラックバック (0)

2010年4月13日 (火)

外付けSRAMをFPGAにつなぐ

 FPGAビデオインターフェースプロジェクトは、次の第二ステップに進んだ。外付けSRAMをVRAM(Video RAM、ビデオバッファー)にする工程である。昔々、ワンチップコンピューターといえばZ80、8080だった時代、RAMをCPUにつけようと色々準備しながら結局挫折したことを思い出す。そう、あのころのマイコンは自分のメモリですらすべて外付けで回路を組まないと動いてくれなかった。良い時代になったものである。

 感慨にふけりながら作業を進める。偉そうなことを言ってはいるがメモリの実装は当研究所では始めての経験である。経験者にとっては何を今さらというところだろうが、近頃、電子工作をマイコンで始めた人にとっては知らないことが多いのではないだろうか。なるべく基本的なところも省略せず書いていくことにする。

0.5ミリピッチと、0.8ミリピッチの表面実装ICハンダ付け(4/5/2010)
 雨の中、久しぶりに秋葉原に寄り、秋月電子で在庫が復活した4メガビット高速SRAM、CY7C1041DV33(\500)と、ロームの8ビットビデオDAC、BU3616K(\300)を入手した。アイテムラボからは、それぞれ変換基板が届いている。

 どちらも0.8ミリピッチなのでハンダ付けはそう難しくない。ついでなので一緒に買ったあった0.5ミリピッチの変換基板のハンダ付けを腕試しに最初に挑戦してみた。これは以前の雑誌付録のARM基板、LPC2388のイーサネットインターフェースのためにDigiKeyで買ったあったPHY層トランシーバーのDP83483である。0.5ミリピッチのQFP48だ。

 小ピッチの表面実装部品のハンダ付けは最初はとても出来ないと敬遠していたが、慣れてしまえばそう難しいものではない。拡大鏡は必須だが、要は、うっかりすると出来るハンダブリッジは気にしないことである。それとハンダはなるべく少ない方が良い。基板のパッドは必ず薄くハンダメッキをしておき、ブリッジしたら、フラックスを塗ってハンダ吸い取り線を使えば解消する。余り綺麗とはいえないが0.5ミリでも問題なくつけられた。20倍ルーペで確認する。

A4122834

 次は本番の4メガビットSRAMの0.8ミリ44ピン。これが結構難儀した。ハンダが多すぎてピン上部までハンダが表面張力で上がると、ハンダブリッジが中々解消できない。それに片側22ピンもあるとどうしてもハンダが均等に流れず、ハンダがついていないところが出てきたりしてルーペで確認しないと危ない。

 アイテムラボで大量購入したピンポスト(これは安価で便利)を立てて、SRAMはめでたく汎用基板に実装可能となった。しかし実際にどこにつけるかで迷う。基板にハンダ付けしてしまうと移動できないし、基板そのものの全体レイアウトが決まっていないので場所も確定できない。

 全体のレイアウトを決めようと、必要なピン数を数えていて愕然となる。雑誌付録基板についているFPGA、Spartan3EのXC3S250Eは一番ピン数の少ないモデルで、I/Oピンは66ヶしかなく、ユーザーが自由に使えるピンは、回路図を見ると51本しか出ていない。SRAMのアクセスや、デジタルRGBのピンを数えていくと全く余裕がない。

 SRAMは、アドレス18本(512KBを2バイト単位でアクセス)、データ16本で34、ビデオは、RGB 5×3の15とV,H同期信号2で17、これにSPI 3を足すと、ありゃりゃあ、54本だ。3本も足らない。

 アドレスは、512Kも使わないので一本減らせるが(QVGA16ビットカラーで154KB)、それでも53、メモリアクセスを8ビット単位にすれば8ピン浮くが操作が面倒だ。アドレスを18本使って8ビット半分だけを使う手もあるが余り美しくない。あれこれ悩む。

 もう一度、基板の回路図をしらみつぶしに探す。するとinput onlyというピンが4本あり、これが使えそうだ。SPIの受信と同期信号は入力なので、この2つを、このピンにアサインすると、51プラス2で何とか入りそうだ。ほっと胸をなでおろす。

SRAMのアクセスはあっけないほど簡単だが(4/7/2010)
 秋月で買った4メガビットSRAM、CY7C1041DV33である。付属資料は1枚ペラの簡単なスペックしかないので、正式なデータシートをWebから落としてアクセス方法を調査する。

Ws000001

SRAMのアクセスは気が抜けるくらい簡単な方法でデータが読み書きできることがわかった。

 所定のアドレスを設定すれば、少し遅れてデータバスにデータが出現し、書き込みは、WriteEnableピンを下げる(負論理なので)だけである。これらのデータが有効になる最小時間がそれぞれ10nsということで、有効になっても何かトリガーがあるわけではなく、長い方には制限がない。かえって回路をどう組むか迷ってしまうくらいだ。

 ただ、VRAMではアクセス以外にもっと大きな問題がある。読み書きをほぼ同時に行わないといけないということである。今度のプロジェクトの当面のゴールは静止画で、動画ではないのでそうシビアではないが、データを読んでいるとき画面が真っ暗になるのはみっともないし、将来の動画を視野に入れれば、ぜひ実現しておきたいところだ。

Ws000000

 しかし、今度のSRAMはデュアルポート(双方向だと独立して動ける)ではないので、同時に読み書きする(プロセッサーからのデータ書き込みとビデオインターフェースへの読み出し)ロジックは自分で作らなければいけない。

 このあたりになると、入門レベルを超えているのでWebには適当な回路やロジックはころがっていない。自己流でステートマシンっぽいロジックを作っていくが、これでうまく動くのか全然自信がない。本来なら、どこかの既存のライブラリや、ソースコードを使うべきなのだろうが、へそ曲がりの負けず嫌いときているので、意地になって自分で考える。

 タイミングチャートを作りながら、様々に検討する。それと、同じデータラインで入力と出力を同時に実現する、VerilogHDLのinoutというインターフェースのコーディングが良く分からない。これもWebを先生に色々当たる。まあこのあたりの苦労も面白い。そもそもこの苦労を面白いと思わなければ、こんなことはやっていられないのかもしれない。

 2日間ほど、あーでもない、こーでもないとやった結果、何とか断片的だが、inoutを実現するVerilogHDLソースコードが見つかった。SRAMではないがinoutポートを双方向で読み書きするモジュールだ。

 双方向のポイントは、ポートを出力にしないときは、トライステート(1、0、ハイインピーダンス)のハイインピーダンスにするところだろう。inoutにしたポートをBUSSとすると、データ書き込みでないときは、assign文で、

 assign BUSS =(データ書き込みのとき)?書き込みたいデータ : Hiz ;

とポートをハイインピーダンスにしておく。こうすると入力のときは、BUSSにあらわれたデータを読むことができる(入力ポートになる)。

 クロックは今のところ30ns(33Mhz)なのでアドレスを決めれば次のクロックサイクルでデータ移動できる。何といっても10nsの高速だ。待ち時間(レイテンシーは1ということ)を入れる必要はない。送受信の調停(アービトレーション)は、送信を優先して(画面送出)、受信(プロセッサーからの更新データ)を待たせる。

 ということでまだコーディングまで行かないが、ロジックレベルでは見通しがついた。何とかなりそうである。残るは、これを検証するテストベンチを作ることである。そろそろ全体のデータの流れを考えながら機能の開発をしていかないと効率が悪い。 

 SPIインターフェースはプロセッサー側がマスター(送信)でFPGAはスレーブ(受信)なので、FPGAのSRAM書き込みにあわせてデータを貰うことはできない。大した大きさにはならないがFIFO(バッファー)をつける必要があるだろう。

本格的なステートマシンの設計とシミュレーターの導入(4/12/2010)

 ステートマシンの設計に入る。今度のテストベンチは、少し本格的なステートマシンになりそうだ。色々資料をあたる。うむ、これはマルチタスクの設計と同じだ。沢山の自律して動くサブモジュール(マルチタスク)を相手に、メインモジュールがリクエストフラグを出して、スタートさせ、サブモジュールからの作業終了フラグ(ビジーフラグ)を待って、同期させながら次の処理へ進む。前に勉強したリクエスト/ビジーフラグで動く方式とはこのことだったのだ。

 興に乗ってUARTモニターのしかけを考え出していると際限がなくなってきた。どうせなら汎用的な仕様にして、後のFPGAの開発にも応用しようと欲張ったものだから、話がどんどんふくらんでなかなか仕様がまとまらない。SRAMの同時アクセスを検証するルーチンをUARTを使って端末にデータを表示しながら作ろうと、あれこれ考えたが複雑になりすぎて手に負えない(画面をスクロールせずに同一行で激しく表示させ、キー入力で変更する機能など)。

 2日ほど考えて諦める。こういうときは基本に戻るのが一番だ。やりたいことを決めて、そこへ資源を集中しないと発散してしまう。こればっかりやっているわけにはいかない。

結局、第二ステップで実現しようという仕様は次のようなものとなった。

・UARTから入力を受け付け、SRAMにデータを溜めると同時にエコーバックする。

・リターンキーをトリガーに、溜めてあったデータを最初から、UARTに最後まで出力する。

・このままでは同時アクセスの検証ができないので、7セグLEDに入力文字を常時表示させ、UARTの入力文字に応じて、表示が変わるようにする。高速は望めないが、少なくとも双方向アクセスの検証にはなる。

 あれこれ道草していたが、やっとのことで第二ステップの作業工程が出来た。UARTを使ってもっとFPGAを自由に操作したいが、それは先の楽しみに取っておこう。しかし、高速同時アクセスの検証は上記機能だけでは安心できない。何かで確認しておかないとあとで構成が複雑になった時に心配である。

 そこで、思いついたのが、シミュレーションである。FPGAの入門ページには沢山シミュレーションの例が紹介されている。装備を余り重くしたくなかったので、今まで横目で見るだけで我慢していたが、そろそろ入れる時期だ。

 Webの情報を元に、無償版のModelsim Xilinxを入れることにする。久しぶりにログオンしたXilinxのサイトからModelSim Xilinx Edition IIIという無償版を案内されるままダウンロードした。超弩級のISEなどに較べれば、こいつは200MBばかりの小さなファイルだ。ライセンスキーをメール経由で入手して無事立ち上げに成功した。            

早速、これまでの7セグの練習プログラムを試してみる。道案内は例によって先人のWebを参考にさせてもらった。
http://homepage3.nifty.com/alpha-1/computer/ModelSimXEIII6_J.html
 ここはインストールまでの手順を丁寧に紹介してくれている。おすすめ。
http://souyuu.net/article.php?story=20100320140542168
 ダイジェスト版で一覧するのには良い
http://homepage1.nifty.com/x6/tool/modelsim.htm
 旧バージョンだがここは操作法が詳しい。

 画面が出た。シミュレーションを開始する。おやあ、全く動きがない。それはそうだ。クロックもリセットも入っていない。さきほどのWebの案内は、インストールまでは懇切丁寧だが、肝腎の使い方について殆ど説明がない。正式の英語マニュアルも落としたが、コマンドベースの説明だけでGUIの説明が見当たらない。

Modelsim

 あてずっぽうで、やっとクロックを出すところまで行ったが、リセットを出すところでギブアップした。データを動かすforceのコマンドが言うことを聞かない。いやいや、このシミュレーターだけでも知らなければならないことが膨大にある。まあ、動いただけでも良しとしよう。先はまだ長い。

| | コメント (0) | トラックバック (0)

2010年4月 3日 (土)

FPGAのUARTで7セグLEDを動かすことに成功

順序回路の4桁十進変換が動いた(3/31/2010)
 FPGAの初の自作プログラムで7セグLEDのカウンターがやっと動き始めた。次のステップはUART機能の組み込みである。UARTは、これまでの雑誌にいくつかサンプルコードがある。これをコピーするだけで簡単に動くはずだ。

A4032785

 UARTの目的は、コーディングの練習以外にもある。これを通してモニターのようなものをFPGAで動かし、デバッグツールにできないかということである。いわゆるステートマシンにしてUARTからの入力を受付け、指示された(内部変数の表示、メモリダンプ)処理を行い、次の外付けメモリ(SRAM)接続ステップのデバッグに使いたい。しかし、雑誌のソースコードを丸写ししているだけでは経験値を上げられない。

 ということもあって、今動いている7セグLEDのカウンターをもう少し拡張することにした。このカウンターは、16ビットのバイナリ入力を7セグLED4桁に十進表示する機能だったが、バイナリーから10進数(BCD)への変換が思ったように動かず、ウェブで、2桁の10進表示の組み合わせ回路を見つけて、それを3桁に拡張して何とか動かした。しかし4桁あるLEDのひとつは0の定数のままで、まだ全部動いていない。このままでは気分が悪い。

 この変換は最初、割り算が2の倍数でしか出来ないというのでwhileを使って引き算を繰り返すロジックにしたら、ISEが暴走するという騒ぎを起こしたいわくつきのロジックである。このときはわけもわからず組み合わせ回路にwhileを入れたが、あとから考えると恐ろしいことをしていたということがわかる。

 その後、沢山ある雑誌の特集記事を精読し(デジタルデザインテクノロジのHDL超入門の号はソフト屋には眼から鱗で面白い)、HDLが大分、分かり始めた。みかけはソフトウエアに見えるが、あくまでもフリップフロップやセレクターなどの論理回路を組み立てるための道具なのだ。これを常に頭に入れておかないと、さっきのようなことが起きる。

 それはとにかく、4桁の十進表示である。考えてみたら33Mhzものクロックが入っている。always @(クロック)の構文を使えば、割り算の代わりに、引き算を繰り返せばあっという間に計算が出来るはずである。バイナリの入力が変化したのをトリガーにクロックごとに引き算をして、1位の桁が出たところで止めればよい。

 うむ、うまく行きそうだ。引き算構文の前にフラグを立て、このフラグを1位の桁のところで下ろせば、そのときは望みの10進デジット(BCD)が揃っている。このフラグは、別のalwaysでバイナリー値が変わるたびに上げてやればよい。一種のステートマシンだ。

 よし、コーディングに入る。良いぞ、組み合わせ回路よりステップ数も少ない。勇んで論理合成に入った。おやあ、エラーが沢山でてくる。いくつかのケアレスミスを直して、最後まで残ったのが、フラグの変数を複数のソースがドライブしているという

Xst:528 - Multi-source in Unit <seg7andUART> on signal <FLAG>; this signal is connected to multiple drivers.

というエラーだ。

 ウェブを漁る。どうも別の独立したループの間で共通の変数はいじれないようだ。おかしい。これが出来ないならステートマシンという考え方が成り立たないはずだ。雑誌記事をさらに読み込む。うーむ、なにやら難しいことをしている。それぞれが、リクエストフラグとビジーフラグを持ち、それを見合いながら動いている。結構複雑だ。こんな割り算のような簡単なロジックにいれるには大げさすぎる。

 確かに、ハード回路を組む時に、一本のロジック線に別々のところからの信号を一緒にすることは出来ないはずなので理屈はわかる。しかし、マイコンプログラムでは苦もなく出来るしかけが、ここでは出来ないというのはどうも納得できない。

 出来ないとなると何とかしてやろうといういつもの悪い癖が出る。もっと簡便な方法があるはずだ。相当しつこい性格である。2日ばかり、暇さえあれば考え、何度かコーディングまで行ったが、やっぱり、同じエラーではねられるか、LEDはカウントアップしてくれない。

 昨日の深夜、寝る前に入った風呂の中で、突然閃いた。2つのalwaysで変数を共有するからいけないのだ。ひとつのalwaysの中に入れてしまえばそもそも共有を考える必要がない。それに入力が変化したことは、alwaysのセンシティビティリストに入れなくても、常に前の入力を保存しておけばよい。今まで共有しようとして苦労したが、それをせずに済む方法があった。

 これだ、クロックの度に動くalwaysで、入力を以前、BCDを出した時にセーブした値と比較し、同じならスルー、違えば、1位の桁が出るまでループ、1位の桁がでたところでセーブした値を今出した入力値に変える。うまいぞ、できそうだ。

 次の日、喜び勇んでコードを作り直す。出来たコードの確認ももどかしく論理合成をかける。良かった、エラーはでない。コンフィギュレーションする。LEDがついた。祈る気持ちで、タクトスイッチを押す。おおお、1が出た。2になった。順調に増えていく。さあ、桁上がりするか。いけないa(この7セグは16進表示ができる)が表示されて桁上がりしない。

 ははは、これは比較をA>10でやっているからだ。これをA>9に変える。よーし、順調に10の桁も増えていく。良いぞ。無性に嬉しい。久しぶりの快感だ。自分の考えたロジックの通りFPGAが動いてくれている。達成感で胸がふくらむ。何度も書くが、実に安上がりな娯楽だ。人間というのはこんなささいなことでも無上の喜びを得ることが出来るのだ。

 喜んだ勢いで、4桁に拡張(検証のため千回押すのは大変だった)したり、前のロジックとのリソース使用量の比較もしてみた。組み合わせ回路で999まで出せるコードは、スライスを150使っている(フリップフロップ72、ルックアップテーブル280)のに対して、順序回路にした改良型は、スライスが107(フリップフロップ118、ルックアップテーブル111)と30%も消費リソースが少なくなった。いやあ、鼻が高い。天井に届きそうだ。あんまり嬉しくてVerilogHDLのソースコードを公開してしまう(あくまでも習作です。間違いがあっても責任取れませんのでよろしく)。

//
// 16ビットバイナリを4桁の10進表示に換えるサブモジュール
//
module bin2d1000(pRST, pCLK, CTR, d4, d3, d2, d1);
input pRST;           // RESET
input pCLK;           // System Clock
input [15:0] CTR;     // source 16bit Binary
output [3:0] d4;      // BCD 1000
output [3:0] d3;      //     100
output [3:0] d2;      //     10
output [3:0] d1;      //     1

reg[15:0] WK,SAVE;   // work regs
reg FLAG;            // start/stop flag
reg[3:0] dg4,dg3,dg2,dg1;  // each order counters

always @(posedge pCLK or negedge pRST ) begin  //count loop
  if(!pRST) begin            // initialize variables
    SAVE <= 0; FLAG <= 0;
    dg4 <= 0; dg3 <= 0; dg2 <= 0; dg1 <= 0;
  end else
  if(CTR != SAVE) begin     // begin loop when CTR changes
   if(FLAG == 0) begin      // setup regs at the beginning
     WK <= CTR;
     dg4 <= 0;
     dg3 <= 0;
     dg2 <= 0;
     dg1 <= 0;
     FLAG <= 1'b1;           // do it only once.
   end
  else begin
   if(WK > 999) begin      // over 1000? then subtract 1000
   WK <= WK - 1000;
   dg4 <= dg4 + 1'b1;     // count up 1000 order
  end
  else
   if(WK > 99) begin      // over 100? then subtract 100
     WK <= WK - 100;
     dg3 <= dg3 + 1'b1;
   end   
   else   
    if(WK > 9) begin      // over 10? then subtract 10
      WK <= WK - 10;
      dg2 <= dg2 + 1'b1;
    end         
    else begin
      dg1 <= WK;
      FLAG <= 0;       //stop iteration
      SAVE <= CTR;     //save CTR for next request
    end
   end   // FLAG else if
  end   // SAVE if
end    // always begin

assign d4 = dg4;  // put each BCD
assign d3 = dg3;
assign d2 = dg2;
assign d1 = dg1;
endmodule         // end of module

UARTのコードを入れる。なかなか言うことを聞かない(4/2/2010)

A4032790

 練習課題の次のテーマのUARTである。仕様は、端末からのキーボード入力をエコーバックして端末に戻し、リターンキーを押すと、7セグLEDがカウントアップするというものである。余裕があれば、UARTから送られてきたASCIIコードを7セグLEDに16進表示させたい。

 UARTのソースコードは、色々な雑誌にサンプルとして載っている。VerilogHDLでは、デザインウェーブマガジン誌2008年10月号のものが、わかりやすかったので、このソースを拝借することにする。これ以外では、インターフェース誌2009年9月号、デジタルデザインテクノロジ2号にも出ている。

 別ファイルを起こし、サブモジュールとして作っていく。大した量ではないのでWebからダウンロードしないで手入力で入れてしまう。サブモジュールの練習をしてあったおかげで、接続も慣れてきて、UARTを入れたプログラムの上位レベルの論理合成はNoErrorとなった。下位(実際の結線のチェック)レベルの論理合成では山ほど警告メッセージが出るが、Webによれば無視して良い警告メッセージのようなので(Xst:1285 設定したピンの初期値が不定と言ったWarningなど)、そのままコンフィギュレーションまで進む。

 さあ、ファームが出来た。ハードウエアの準備をする。TTL-UARTは、例によって秋月のUSB-UARTモジュールを活用する。ブレッドボードに載せてジャンパーで接続する。そろそろ新しいブレッドボードを増やさなければならない。これまでのPCMプレーヤーのテストベンチの横を間借りする。

 わくわくしながら、ターミナルソフトを立ち上げ、テストを開始した。祈る気持ちでPCのターミナルのキーボードを打つ。エコーバックはない。リターンキーでカウントアップもしない。しかし、LEDを見ると、おお、何やら16進表示が出ている。受信はちゃんと動いているようだ。1を入れて31、jをいれて6A、素晴らしい。問題なくASCIIコードが出ている。皮肉なことに、つけたしで入れた機能が最初に動いた。

 タクトスイッチを押す。あれえ、いけない。とんでもない数字が表示され、押していると数字がくるくると動きっぱなしになる。何故だろう。最初、クロックでalwaysをまわしていたのを、UARTを入れる際、キー入力の立ち上がりでalwaysをまわすようにした。

   always @( posedge キー入力 or  posedge  UART入力)begin

というステートメントだ。この条件だと、always節内の処理は、キー入力が一回されたときのみ、動くはずなのだが、実際には、キーを押している間中、廻りっぱなしである。わけがわからない。何か大きな勘違いをしているのかもしれない。

 UARTの方は送信が動いていない。ターミナルに文字が戻ってこない。ソースを調べて送信リクエストのビットを上げていないことがわかり、このビットを上げると、今度は立て続けに同じコードを送り続けて止めるタイミングがわからない。やれやれ難しいものである。同時に色々なモジュールが一斉に動いているものを制御するのは大変だ。この日はこれで時間切れ。

UARTが無事動いた(4/3/2010)

A4032791

 久しぶりに電子工作に熱中している。マイコンをやっていますと言うと、何とか電子工作として理解してもらえるが、FPGAとなるともう誰も知っている人がいない。理解されない孤独な道を突き進んでいるという疎外感と、自分の趣味も遂に現代の電子技術の最先端まで来たか(まあ、まだ、ほんの入り口ですが)という誇らしい気持ちが入り混じって、このところ気分が安定しない。

 ともかく、この3日間はFPGAのコーディングに没頭していた。そして、遂にUARTと7セグLEDを使った練習プログラムは、所期の機能を実現した。キーボードを叩けば、そのまま文字が端末に表示され、リターンキーを押せば、カウンターが1つづつ増えていく。人から頂いたソースなので前ほどではないが、それでも嬉しい。

 スイッチを押すタイミングでしか動かないはずのalwaysの解析はあきらめて、クロックを使った前の方式に戻したら、スイッチは何事もなく確実に1つづつカウントするようになった。やれやれ。前のコードの解析はまたあとでやろう。

 UARTの送信が出来ない原因は、ここに書くのも恥ずかしい、変数の定義漏れだった。サブモジュールとの接続は慣れたとはいえ、wireとregの使い分けが難しい。それに親(top)モジュールで使わない変数は、親で定義しないでもつながるときがある。警告メッセージにはでていたのだろうが、他のメッセージの中で見落としたようだ。トップモジュールで、受信側と送信側をそれぞれ、wireで定義し、assignで接続したら、送信データは無事、ターミナルに戻ってきた。

Fpga_uart

 UARTがつながった。キーボードの入力文字が端末に表示されるだけで、何かディバイスが急に身近に感じられるというのも不思議なものだ。これでFPGAの開発は一段と楽になる。秋月電子のホームページを久しぶりに覗いたら、あの高速SRAMの在庫が戻っていた。アイテムラボにはこのSRAM用の変換基板を発注してある。次の第二ステップの準備は進んでいる。いよいよ次の難関、外付けメモリの接続が待っている。

| | コメント (2) | トラックバック (0)

« 2010年3月 | トップページ | 2010年5月 »