金曜日, 12月 6, 2013

デモシステム更新(カメラ制御)

しばらく間が空いてしまいましたが、デモシステムを更新します。ダウンロードリンクは前回のデモと同じ(relm_demo.jar)になります。

基本的に前回のデモ内容は全て含まれていますが、回路の変更によりソフトウェアの互換性はありません。今後この新しい回路の仕様に基づいてリファレンスを公開していく予定ですので、その点ご容赦ください。

最も主要な追加デモはCMOSセンサカメラの制御ですが、その他にもSVGA解像度(800×600)への対応やウォームリセット機能が追加されました。また、JTAG通信仕様の変更により、画像の転送が少し速くなっています。

デモ用ソフトウェアは以下になります。

reset.rb
ウォームリセットを実行します。実際にはコア戦争のVampire(またはpit-trapper)のように、メモリ全体をジャンプ命令で埋め尽くして全てのスレッドの捕獲を試みます。もしうまく捕獲できなかった場合にはLEDが点灯したままになりますので、そのときは「Config FPGA」でコールドリセットを実行してください。

vga.rb
SDRAMの内容をVGA(640×480, 60Hz)出力します。外付けの出力回路は前回の記事を参考にしてください。「Send Image File…」または「Send Image URL…」で画像データをSDRAMに書き込むことができます。

svga.rb
SDRAMの内容をSVGA(800×600, 72Hz)出力します。モニタによっては対応してないかもしれません。解像度を切り替える場合は、一旦ウォームリセットを実行してください。

gsensor.rb
加速度センサで画面出力をスクロールします。予めvga.rbかsvga.rbのどちらかを実行しておく必要があります。メモリ上に2048×2048ピクセルの仮想画面があり、その中で表示位置を移動します。ボード上のボタン操作でスクロール方向を反転させることができます。(KEY1: 通常, KEY0: 反転)

led.rb
LEDをランダムに点滅させるプログラムです。DE0-Nano本体のみで実行が可能です。

camera.rb
CMOSセンサカメラの画像をリアルタイムで画面出力します。予めvga.rbかsvga.rbのどちらかを実行しておく必要があります。CMOSセンサのデータはYUV形式で受け取れますので、色変換とディザ表示のために、残る全てのスレッドを消費して強引に高速実行しています。残念ながら、DE0-NanoにはSDRAMが一つしか載ってないので、表示のための読み出しと書き込みが同時にはできません。そのため、昔のVRAMのようにメモリ書き込みの際に表示読み出しをしないので、黒いノイズが入ってしまいます。ボード上のKEY0を押すと、垂直ブランク期間中にのみ書き込みを行うモードとの切り替えを行いますが、ノイズが消える代わりに表示速度が低下します。KEY1は簡易肌色検出モードの切り替えになります。

IMG_3955.jpg

外付けのCMOSセンサは、aitendoのカメラモジュール(OV9655)を利用します。ピンアサインはこのモジュールに合わせてあるので、同じくaitendoのピンヘッダ変換基盤を利用すれば、あとはピンソケットを2つ付けるだけで面倒な配線は全く不要になります。カメラの向きの関係でピンソケットの片方をL型にする必要がありますが、どちらをL型にするかで違った形のカメラ装着が可能です。

IMG_3957.jpgcamera_circuit.png

このデモではカメラ入力を直接画面に表示していますが、例えばこのカメラをロボットの制御に応用する場合、画面表示の代わりに画像認識やモータ制御を行うことになります。画像認識にちょっとした顔検出アルゴリズムを組み込めば、顔の方に寄って来るロボットが作れたりします。こういった多数のセンサやアクチュエータを同時制御するロボティクス応用において、このプロセッサはまさに打って付けであるといえます。

月曜日, 8月 12, 2013

デモシステム公開

レジスタレスマルチプロセッサの実行可能なデモシステムを公開します。

このシステムは、市販のFPGAボードDE0-Nano上に16コアのレジスタレスマルチプロセッサを構築し、ホストPCからのプログラムのダウンロードおよび実行を可能にしたものです。

デモ内容は主に、ボード上のSDRAMを画像メモリとした画面出力と、加速度センサによる画面のスクロールです。レジスタレスマルチプロセッサではキャッシュアクセスによる命令実行タイミングの乱れがないため、厳密なタイミングのデバイス制御をソフトウェアで直接行えるという利点があります。特に、このシステムではその利点を生かして、複雑なSDRAMの制御をほぼソフトウェアのみで行っています。

デモの実行は、DE0-Nanoを接続したホストPC上で実行可能Jarファイル(relm_demo.jar)をダウンロードして実行するだけでOKです。ただし、Java実行環境とUSB-Blasterのドライバがインストールされている必要があります。おそらく、DE0-Nano付属のデモプログラムが動く環境であれば、問題ないと思われます。

できればDE0-Nano本体だけで実行できるデモにしたかったのですが、やはりボード上のLEDのみでは有効なアプリケーションを開発するのが難しいので、抵抗5本だけで出来る簡易VGA出力回路を増設することにしました。あくまでも簡易なので、DE0のVGA出力の様に中間調が出せませんが、それでもLEDに比べればかなりのことが表現出来ると思います。

vga_circuit.pngIMG_3378.JPG

上の回路では基板の空いた部分に圧電サウンダを載せていますが、今回のデモでは特に使用していません。音が不要な方や圧電素子によるFPGAの破壊が心配な方は、省略しても結構です。

relm_demo.jarを実行すると、JRuby環境が未ロードの場合にはインターネットからダウンロードを開始します。ダウンロードしたjruby-complete.jarがrelm_demo.jarと同じフォルダに保存されますので、次回からはダウンロードが不要になります。

jrubyloader.png

JRubyがダウンロード済みになると、デモシステムが起動します。

relm_demo.png

まず、ホストPCにDE0-Nanoを接続した上で、「Config FPGA」を押してマルチプロセッサ回路のコンフィギュレーションを実行します。コンフィギュレーション直後は16のスレッドのうち1つでプログラムローダを実行し、他のスレッドは停止状態となります。プログラムローダはホストPCからJTAG経由で送られてきたデータを基にメインメモリおよびSDRAMの書き換えを行います。これにより、再コンフィギュレーションすることなく、ソフトウェアの書き換えと起動が可能になります。

コンフィギュレーション完了後、デモプログラムの実行を行います。まずDE0-Nano本体のみで実行可能なデモとして、「led.rb」のタブを選択します。エディタにRubyのプログラムが表示されるので、「Run Program」を押して実行すると、DE0-Nano本体のLEDが点滅を始めます。デモプログラムはこのようにRubyのコードとして記述され、デモ環境で実行するとプログラムが転送されて、FPGA上で実行されるようになります。

ただし、現状ではRubyを利用したアセンブリ言語的なドメイン特化言語を構成しているので、比較的低レベルのプログラム記述でソフトウェアを構築することになります。残念ながら、RubyのコードがそのままFPGA上で実行できるわけではありません。

VGA出力回路を接続すると、より高度なデモが実行できます。「Config FPGA」でコンフィギュレーション終了後、「vga.rb」を選択して「Run Program」で実行します。VGA回路出力を適当なモニタに接続すると、通常はSDRAM初期状態のランダムパターンが映し出されます。下の写真では、左側がホストPCのモニタ、右側がFPGAのVGA出力になります。

IMG_3379.JPG

この状態で、「Send Image URL…」を押してWikipediaの富士山の記事に使われている画像のURL(http://upload.wikimedia.org/wikipedia/ja/3/3e/MtFuji_FujiCity.jpg)を入力します。(Ctrl+VでURL文字列の貼り付けが可能)

転送にしばらく時間が掛かりますが、VGA出力に富士山の画像が映し出されます。VGA出力が中間調を出せないため、画像は独自アルゴリズムによる誤差拡散ディザ表示となります。インターネット接続環境でない場合、「Send Image File…」でローカルファイルの画像を転送することも可能です。

IMG_3380.JPG

画像が表示されている状態で、「gsensor.rb」を選択して「Run Program」で実行すると、DE0-Nano本体の傾きに応じて画像全体がスクロールするようになります。

IMG_3381.JPG

この状態で別の画像を転送することが可能ですが、転送の最中でもDE0-Nano本体を動かすと画像のスクロールが実行されます。これは、加速度センサによる画面のスクロールの処理と、プログラムローダによる画像データのSDRAMへの書き込みが、別々のスレッドで並列実行していることを示しています。実際にはこの時点で、以下の4つのスレッドが実行していることになります。

  1. プログラムローダ
  2. VGA出力(vga.rb)
  3. 加速度センサ値読み取り(gsensor.rb)
  4. 加速度センサ値による画面スクロール(gsensor.rb)

これに加えて、LED点滅デモ(led.rb)を起動しても全く問題なく動作します。プロセッサ数の16個までのスレッドを同時に実行することが可能ですが、現状では個別のスレッドをホストPCから停止する機能はありません。ただし、「Config FPGA」を実行することで、プログラムローダのみの初期状態に戻すことができます。

エディタ上でプログラムを変更することで、ユーザ独自のプログラムを実行することができます。例えばled.rbの「_wait 1000000」の数値を変更して「Run Program」を実行すると、点滅速度を変えることができます。「New」を押すと空の「*Scratch*」タブが現れるので、最初からプログラムを書くことも可能です。ただし、変更内容を保存する機能はないため、本格的な開発をしたい場合にはEclipseでJarファイルをインポートするのがよろしいかと思います。

「Create mif files…」を押すと、関連するファイル(jtag.rb, asm.rb, de0nano.rb, mif.rb)を参照用に開いた上で、「Create mif files?」に「はい(Y)」と答えると論理合成時に必要となる初期メモリデータファイルを作成します。この初期メモリデータには、プログラムローダのコードが書き込まれます。実行プログラム記述については今後解説をしていく予定ですが、asm.rbおよびde0nano.rbの内容を解読することで理解することも一応可能です。

「Render VHDL」はプログラム実行には直接関係ありませんが、論理合成用のVHDLコードを出力することができます。このVHDLコードは実際にはRubyプログラムにより自動生成されますので、これらのRubyプログラムのコードも参照用にタブ表示されます。これも内容を解読することで、理論的には全ての技術内容を知ることが可能です。ちなみにVHDLコード出力をうっかり「Run Program」しても大丈夫なように、最初の行におまじないが入っています。

Javaのソースコードも含め、全ての技術的内容はJarファイル内に含まれていますが、全く解説なしに独自開発を進めるのは難しいと思われます。今後、このツールをベースに解説を進めていく予定です。