見事に入れた文字列が戻ってきた。頭の部分が少しおかしいが、あとは正確に表示してくる。最初の1文字だけがおかしいが、あとは完全だ。200バイト以上の日本語テキストをカット&ペーストで入力し、リターンキーを押す。これでSRAMの読み書きが実現した。念のためロジアナを引き出して、制御の様子をとってみた。きれいにリターンキーを押した時の、書き込みと、そのあとの読み出しのCEのパルスが見えた。オシロではCEのパルスがひとつしか見えなかったが、時間的にこれだけ離れているので安いオシロでは観測不能であることが良く分かる。最初の文字が化ける理由は、SRAMではなくて、UARTの不具合である。SRAMが原因でないことは、リセットボタンを押してプロンプトを出すところから化けるので間違いない。連続して文字を送るときは問題ないが、最初の文字がどうもうまく送信されないようだ。このUARTのコードは、雑誌からの借り物である。リクエスト/ビジーの連携が上手く行っていない感じだ。ウエイトを入れたり、判断ロジックを入れたりしたが、どうしても直らない。苦闘したが、解析は当面諦めることにした。FPGAプロジェクトの目的は別のところにある。こればっかりやっているわけにはいかない。いまひとつすっきりしないが、とりあえずの目的は果たした。休日のほぼ一日をつかって、SRAMのアクセスが遂に実現した。第二ステップ終了である。ロジアナに見るように、SRAMアクセスとしては超遅い読み書きで、これからどれくらい速度を上げられるか、同時読み書きの検証をどうするか、課題はまだ山積しているが、FPGAプロジェクトは先に進めよう。次は、いよいよ本来のディスプレイのRGBインターフェースの作成である。(木)外付けSRAMを制御するFPGAのピンが足らないFPGAでビデオインターフェースを作るプロジェクトは、シミュレーターのインストールに道草を食ってしまい、第二ステップは、まだ基本的な仕様がかたまっただけである。このステップの目標は、外付けSRAMの制御をマスターすることで、UARTを通してメモリにデータを蓄積し、そのあとリターンキーの入力でそれを吐き出させる機能を開発することにしている。本来のFPGAの目的であるビデオインターフェースは、電源を入れれば、ただひたすらVRAM(SRAM)にあるフレームデータをアナログビデオ信号に変換して出力することだけである。複雑なシーケンス制御は想定していない。考えてみれば、UARTなどを使った順序制御の必要はない。プロセッサーとの間はバス接続でなく、シリアルのSPIを考えている。すると、まだ仕様は考えていないが、SPIから来るビデオデータの頭を知るための何らかの順序制御は必要になる。それにFPGAの勉強としては恰好の題材でもある。回り道だが、UARTでの制御にこだわってみることにした。ステートマシンを理解する(4/15/2010)UARTからのデータ入力は、キーボードからの手入力または、端末ソフトでのカットアンドペーストか、ファイル転送すれば、高速でメモリを書くことになる(といってもUART以上の速さにならないが)。FPGAのUARTは幸いなことに完全な全二重である。エコーバックも問題ないはずだ。頭の中だけで考えていたステートマシンの詳細設計に入った。メモを沢山書いて頭を捻る。勉強しただけでこんなことを言うのもおこがましいが、ステートマシンには汎用性がなく、構造化することが出来ないので少し複雑なことをしようと思うととても面倒なことになることがわかった。同じ処理が出てくるので(UARTの送信など)、普通のプログラミング言語の関数のように処理ブロックを使い回しすることを考えたが、フラグの制御が大変で、かえって構造が複雑になる。階層構造には出来ない。ひとつのalwaysループから外のモジュールを制御するのは、例のリクエスト/ビジーフラグ方式が必要で、処理が複雑になり、しかもどうやっても1クロックづつ遅れる。それでも、段々形になっていくと、もっと良い方法がないかと夢中になる。最後の方では仕事の帰りのバスの中で急に思いついて、忘れないよう手帳を取り出してメモをとるくらいまで熱中した。最初、20近くあったステートは、最終的には6つまで減らすことが出来た。要するに、ステートマシンでの1ステートは、プロセッサーの命令ひとつと割り切って汎用性を考えず、泥臭く重ねるしかないようである。FPGA内にわざわざリソースを使ってCPUコアが作られ、使われている理由がわかる気がしてきた。確かに複雑なステートマシンは本人以外のデバッグがとんでもなく難しいものになりそうだ。ステートマシンの詳細設計がほぼ出来た。擬似コーディングのレベルだが、何回か検証して動く自信が出てきた。負けず嫌いなので、出来上がってからウェブでみんながどうしているか調べる。よーし、同じようなことをしているようだ。知らないときより記事の理解が早い。自分で苦労するのとしないのでは大違いだ。さあ、次はメモリの実装である。ハンダ付けをしようとしてFPGAのピンが足らないのに気づく(4/18/2010)最初に、17本のアドレス線をハンダ付けする。SRAMの固定は迷ったが、直接ベース基板にハンダ付けした。ピンアサインを確かめる。うーむ、分散していて接続線を同じ長さにすることは難しい。クロックは今のところオリジナルの33Mhzで動かすので少々長さが違ってもまだ大丈夫なはずだが心配になってきた。光(電気)の速さは、毎秒3×10**8m(10の8乗)、SRAMの最小アクセス10nsは、クロックが100Mhzということで、100×**6ヘルツ。1クロック3mもある。配線長が問題になるのはギガヘルツ以上でこの程度ではまだ全く問題ないようだ。配線が10本以上になる時は、アートワークをした方が良い。用心してアートワークから始める。アドレスは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でも十分余裕があるのでこの程度なら何とか動くだろう。基本的には私は超楽観主義者である。制御線は、何を採用するか迷った。SRAMのデータシートをもういちど丹念に読み直す。read/writeともいくつもの方法があり、どれにするか迷う。Enable)というのがどうも理解できない。Enable)がL、つまり書き込みのところでは、*OEはX(不定)となっていて何のためにあるピンかよく分からない。Enable)を下げ、*WEを読み込みのときHigh、書き込みのときにLowにする制御でコーディングをすることにする。ハードの準備は全て終わった。あとはVerilogHDLのコーディングを残すだけとなった。実は前から気になっていることがある。それはCY7C1041DのSRAMの第一ピンの位置である。普通、ICチップの1ピンの位置はチップの上に刻印などのマークがあってすぐ分かるようになっているが、写真にあるように、このチップは、ちょっと目にすぐわかる大きめの丸印と、よく見ないと見えない、小さな刻印が対角線上についている。最初、小さい方の刻印を見落としていて、大きい丸印を1ピン側とみて気楽にピッチ変換基板にハンダ付けしたのだが、どうも違うような気がしてきた。このチップはVccとグランドピンがピン列のちょうど中間に2組出ていて、それぞれがたすきがけになっており、逆差しをしても致命的なことにならないようにはなっているが、間違えれば当然全く動かない。データシートの外見図には、型番などの表記はなく、1ピンの小さな丸印の絵が右上の大きめの丸の位置についているだけで、小さな丸の表示はない。外見図の位置からすると、大きな丸が1ピンのマークのようにも見えるが、どうもおかしい。Webにあたってみるが、個別のチップについては全くヒットしない。一般的な話では、丸の刻印が3つもあるICチップの1ピンの見分け方の説明があって、大きい丸印はモールドを流し込む時の射出孔の跡らしく、小さい方が1ピンマークだという。このチップも小さい刻印の方が1ピンのマークのように思えてきた。逆さまにつけてしまったようだ。表面実装ICのとりはずしは、サンハヤトの特殊ハンダ入手以来、そう難しくはなくなったが、それでも一大決心がいる。はずしたけれど、やっぱり元のままで良かったなどという悲劇は避けたいので、さらに調べる。解決は意外なところにころがっていた。当研究所では、パーツは常に予備と確認のため複数買うことにしている。予備のSRAMを取り出して調べてみた。すると裏には大きめの丸印2つと、小さな丸印があり、この小さな丸印の位置が表側の小さな丸印と一致したのである。小さい方が1ピンのマークだ。これで確信を持ってチップを外せる。何回目かのSMD(表面実装チップ)のとりはずしは、順調に行った。大きめ(30W)のハンダごてで、低温ハンダを両側に流し、半田ごてを往復させると、またたくま(3秒くらいか)に、チップが、ずるっと浮いてくる。このハンダがなかったころ、細い銅線を使って苦労してはずしていたことを考えれば、うそのような簡単さだ。\4000以上するが悔しいけれど実に強力である。ハンダ吸い取り線で低温ハンダを念入りにとり、洗浄剤で綺麗にして、もういちどSRAMをハンダ付けする。これでハードの心配はすべて解消した。残るは、コーディングである。(火)外付けSRAMをFPGAにつなぐFPGAビデオインターフェースプロジェクトは、次の第二ステップに進んだ。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倍ルーペで確認する。次は本番の4メガビットSRAMの0.8ミリ44ピン。ハンダが多すぎてピン上部までハンダが表面張力で上がると、ハンダブリッジが中々解消できない。それに片側22ピンもあるとどうしてもハンダが均等に流れず、ハンダがついていないところが出てきたりしてルーペで確認しないと危ない。アイテムラボで大量購入したピンポスト(これは安価で便利)を立てて、SRAMはめでたく汎用基板に実装可能となった。実際にどこにつけるかで迷う。基板にハンダ付けしてしまうと移動できないし、基板そのものの全体レイアウトが決まっていないので場所も確定できない。全体のレイアウトを決めようと、必要なピン数を数えていて愕然となる。雑誌付録基板についているFPGA、Spartan3EのXC3S250Eは一番ピン数の少ないモデルで、I/Oピンは66ヶしかなく、ユーザーが自由に使えるピンは、回路図を見ると51本しか出ていない。SRAMのアクセスや、デジタルRGBのピンを数えていくと全く余裕がない。3を足すと、ありゃりゃあ、54本だ。アドレスは、512Kも使わないので一本減らせるが(QVGA16ビットカラーで154KB)、それでも53、メモリアクセスを8ビット単位にすれば8ピン浮くが操作が面倒だ。アドレスを18本使って8ビット半分だけを使う手もあるが余り美しくない。一度、基板の回路図をしらみつぶしに探す。onlyというピンが4本あり、これが使えそうだ。SPIの受信と同期信号は入力なので、この2つを、このピンにアサインすると、51プラス2で何とか入りそうだ。SRAMのアクセスはあっけないほど簡単だが(4/7/2010)秋月で買った4メガビットSRAM、CY7C1041DV33である。付属資料は1枚ペラの簡単なスペックしかないので、正式なデータシートをWebから落としてアクセス方法を調査する。SRAMのアクセスは気が抜けるくらい簡単な方法でデータが読み書きできることがわかった。所定のアドレスを設定すれば、少し遅れてデータバスにデータが出現し、書き込みは、WriteEnableピンを下げる(負論理なので)だけである。これらのデータが有効になる最小時間がそれぞれ10nsということで、有効になっても何かトリガーがあるわけではなく、長い方には制限がない。回路をどう組むか迷ってしまうくらいだ。VRAMではアクセス以外にもっと大きな問題がある。読み書きをほぼ同時に行わないといけないということである。今度のプロジェクトの当面のゴールは静止画で、動画ではないのでそうシビアではないが、データを読んでいるとき画面が真っ暗になるのはみっともないし、将来の動画を視野に入れれば、ぜひ実現しておきたいところだ。今度のSRAMはデュアルポート(双方向だと独立して動ける)ではないので、同時に読み書きする(プロセッサーからのデータ書き込みとビデオインターフェースへの読み出し)ロジックは自分で作らなければいけない。このあたりになると、入門レベルを超えているのでWebには適当な回路やロジックはころがっていない。自己流でステートマシンっぽいロジックを作っていくが、これでうまく動くのか全然自信がない。本来なら、どこかの既存のライブラリや、ソースコードを使うべきなのだろうが、へそ曲がりの負けず嫌いときているので、意地になって自分で考える。タイミングチャートを作りながら、様々に検討する。それと、同じデータラインで入力と出力を同時に実現する、VerilogHDLのinoutというインターフェースのコーディングが良く分からない。これもWebを先生に色々当たる。このあたりの苦労も面白い。そもそもこの苦労を面白いと思わなければ、こんなことはやっていられないのかもしれない。2日間ほど、あーでもない、こーでもないとやった結果、何とか断片的だが、inoutを実現するVerilogHDLソースコードが見つかった。SRAMではないがinoutポートを双方向で読み書きするモジュールだ。双方向のポイントは、ポートを出力にしないときは、トライステート(1、0、ハイインピーダンス)のハイインピーダンスにするところだろう。;とポートをハイインピーダンスにしておく。すると入力のときは、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の入門ページには沢山シミュレーションの例が紹介されている。装備を余り重くしたくなかったので、今まで横目で見るだけで我慢していたが、そろそろ入れる時期だ。Xilinxを入れることにする。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の説明が見当たらない。あてずっぽうで、やっとクロックを出すところまで行ったが、リセットを出すところでギブアップした。データを動かすforceのコマンドが言うことを聞かない。いやいや、このシミュレーターだけでも知らなければならないことが膨大にある。動いただけでも良しとしよう。順序回路の4桁十進変換が動いた(3/31/2010)FPGAの初の自作プログラムで7セグLEDのカウンターがやっと動き始めた。次のステップはUART機能の組み込みである。UARTは、これまでの雑誌にいくつかサンプルコードがある。これをコピーするだけで簡単に動くはずだ。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ものクロックが入っている。@(クロック)の構文を使えば、割り算の代わりに、引き算を繰り返せばあっという間に計算が出来るはずである。バイナリの入力が変化したのをトリガーにクロックごとに引き算をして、1位の桁が出たところで止めればよい。うむ、うまく行きそうだ。引き算構文の前にフラグを立て、このフラグを1位の桁のところで下ろせば、そのときは望みの10進デジット(BCD)が揃っている。このフラグは、別のalwaysでバイナリー値が変わるたびに上げてやればよい。一種のステートマシンだ。よし、コーディングに入る。良いぞ、組み合わせ回路よりステップ数も少ない。勇んで論理合成に入った。おやあ、エラーが沢山でてくる。drivers.というエラーだ。別の独立したループの間で共通の変数はいじれないようだ。これが出来ないならステートマシンという考え方が成り立たないはずだ。雑誌記事をさらに読み込む。うーむ、なにやら難しいことをしている。それぞれが、リクエストフラグとビジーフラグを持ち、それを見合いながら動いている。こんな割り算のような簡単なロジックにいれるには大げさすぎる。確かに、ハード回路を組む時に、一本のロジック線に別々のところからの信号を一緒にすることは出来ないはずなので理屈はわかる。マイコンプログラムでは苦もなく出来るしかけが、ここでは出来ないというのはどうも納得できない。出来ないとなると何とかしてやろうといういつもの悪い癖が出る。簡便な方法があるはずだ。2日ばかり、暇さえあれば考え、何度かコーディングまで行ったが、やっぱり、同じエラーではねられるか、LEDはカウントアップしてくれない。昨日の深夜、寝る前に入った風呂の中で、突然閃いた。2つのalwaysで変数を共有するからいけないのだ。ひとつのalwaysの中に入れてしまえばそもそも共有を考える必要がない。それに入力が変化したことは、alwaysのセンシティビティリストに入れなくても、常に前の入力を保存しておけばよい。今まで共有しようとして苦労したが、それをせずに済む方法があった。これだ、クロックの度に動くalwaysで、入力を以前、BCDを出した時にセーブした値と比較し、同じならスルー、違えば、1位の桁が出るまでループ、1位の桁がでたところでセーブした値を今出した入力値に変える。うまいぞ、できそうだ。次の日、喜び勇んでコードを作り直す。出来たコードの確認ももどかしく論理合成をかける。良かった、エラーはでない。コンフィギュレーションする。祈る気持ちで、タクトスイッチを押す。