aster_ismの工作室

FPGAとかマイコンとか

FPGAで動画にキュアパインを重ねる

これはプリキュアAdvent Calender 2015の19日目の記事です。

フレッシュプリキュアのブルーレイボックスを楽しみにしながらキュアパインと戯れる日々を過ごしているaster_ismです。
はやく、ぶっきーに会いたいです。

さて、昨年のプリキュアAdvent CalenderでもFPGAを使ってよくわからないFPGAでプリキュアの名前をランダムに表示する - 雨のち曇り時々晴れ@aster_ismを作りましが、やっぱり文字だけじゃなくて可愛いキュアパインが表示される方がいい!
ということで、今年はXilinxのVideo IPを流れている映像にプリキュアを合成する専用回路IPをつくることにしました。
簡単にいうと応援アプリみたいな映像が作れるの専用回路です。
注意)FPGAなのでソフトウェアではありません。ハードウェアです。

まず、XilinxのVideo IPは基本的にAXI4-Streamというプロトコルで転送されています。基本的な動作波形は下のようになっています。

tvalidとtreadyが共にHighの時にデータが有効で、フレームの開始1ピクセル目ではtuserがHighとなり、各ラインの最終ピクセルtlastがHighとなります。とても簡単なプロトコルですね。
つまり、

  • tuserとtvalidとtreadyがHighの時に水平方向カウンタと垂直方向カウンタをリセット
  • tvalidとtreadyがHighの時に水平方向カウンタをインクリメント
  • tlastとtvalidとtreadyがHighの時に水平方向カウンタをリセットして、垂直方向カウンタをインクリメント

という制御を行えば、映像のピクセル位置とその画素が取得できます。

あとはそれぞれのカウンタの値がキュアパイン画像の表示領域である場合にキュアパイン画像のピクセルデータに置き換えをします。
ただ、そのまま画像を置き換えると単純に矩形領域となるので、キュアパイン画像の背景部分も表示されてしまいます。なので、キュアパインの画像データに透過ピクセル(透明)であるとの情報1ビットを付加します。実際のデータは画像生成が楽なのでキリがよい値にしてRGB各4bitと透過ピクセル情報1bitに更に予約領域3bit付加して16bitで1ピクセルの情報とします。
なお、RGB各色が4bitなのは、BASYS3のVGAが4bitな為です。

さて、ディスプレイ出力をVGA(640x480)としたので、キュアパイン画像のデータをとりあえず150x300で作成します。よってピクセル数は45000になります。今回は面倒くさいので、FPGA内部のBlock RAMに画像データをすべて入れます。BASYS3のFPGAはArtix-7なので、この画像だけでBlock RAMを約半分消費してしまいます。他のメンバも表示できるようにするにはFlashか外部メモリに入れてロードする必要がありますが、今回はキュアパインだけ表示できればいいので良しとします。

あとは、カウンタの値を見ながらBlock RAMのデータを順番に読み出しながら、透過ピクセルでなければ来たデータを上書きします。
ただし、Block RAMからの読み出しに1cycle時間が掛かるので、届いたデータを数段バッファリングして上書きするピクセル位置を調整しています(詳しくはソースコード参照)。


これをシミュレーションすると次のような波形が得られます。上の信号が元の画像ピクセルデータ、下の信号がプリキュア合成IPを通った後のデータ。overlay信号がHighはそのピクセルが置き換え対象であることを示しています。途中のデータがキュアパイン?(かどうかはわからないけど別の値)に置き換わっているのが確認できます。透過ビットがあるため必ずしもoverlayがHighでも値が変わってないのがわかります。


作ったaxi4s_precureをIPパッケージとして、Vivado上のブロックデザインでインスタンス化します。他の映像出力に必要な回路と合わせて、最終的にこのような回路となりました。
基本構成は、過去に行ったBASYS3でディスプレイ出力 - aster_ismの工作室キュアパイン合成回路を挟んだだけです。

さて、実際に動かした結果ですがカラーバー映像にキュアパイン正しくが合成されて出力されているのが確認できます。
RGB各4ビットなので若干色が微妙ですが、許容できる範囲です。
また、途中説明をしませんでしが、回路への入力(xpos,ypos)を変えることでリアルタイムに位置を変更することもできます。
(xpos,ypos)は4bitで1増加するとxposは40px、yposは30px移動するようにして、dipスイッチに繋いでいます。
2枚目のイメージはスイッチを動かしてキュアパインを右下に少しずらした。


本当は、応援アプリみたいにカメラからの画像にリアルタイムに重畳しようとおもったけど、カメラ映像取り込み回路を作るのが面倒だったので映像はXilinxのテストパターンジェネレータのカラーバーとなってしまいました。
一応、axi4s_precureにつながっているBRAMをデュアルポートにして、FlashとかSDカードからデータを読み込むようにすると、全プリキュアを表示するようにもできるかと思います。
時間があれば改良して全プリキュア選択+カメラ映像の取り込みでオレオレ応援アプリ的な合成回路を作りたいと思います。


(TODO:ソースコードはバグ修正後githubにあげる)

Vivadoを使ったFlashメモリへの書き込み

開発環境はVivadoにほぼ移行したのに,未だにFlashへの書き込みはiMPACT(LabToolだけインストール)を使っているのが嫌になったので,すべてVivado上から行うための方法について調べた(覚え書).

参考としたのは,UG908 Vivado Design Suite ユーザーガイド プログラムおよびデバッグ *1

続きを読む

Vivado SimulatorによるDPI-Cシミュレーション

UG900 Vivado Logic Simulation*1 のAppendix E: Direct Programming Interface (DPI) in Vivado Simulatorを参考にC言語で書いたCSVファイルの読込み関数をAXI4 Lite のマスタIPで呼び出して,このCSVに従ってマスタが動作するようにします.

続きを読む

FlashAir使った非同期転送テスト

FlashAirがGPIOとして使えるらしいという話は聞いていたが,まったく弄ってなかったので先週のFPGAエクストリーム・コンピューティング第6回に外れた悲しさからブラウザ上からBASYS3の7セグに文字を表示するサンプルを作ってみることにした.

続きを読む

Xilinx Vivadoで上手にバージョン管理する方法

以前よりVivadoプロジェクトをバージョン管理したいと考えていた訳ですが、なかなか自分の開発フローに馴染まず諦めていました。

こんな感じで、バージョン管理をしたいというのはみんな思っているみたいなので、真面目に取りかかることに。

続きを読む

FPGAでプリキュアの名前をランダムに表示する

これはプリキュア Advent Calendar 2014の10日目の記事です。

登録はしたが、ネタに困ったので最近買ったFPGAボードを使ってランダムにプリキュアの名前を表示する回路を作ることにしました。

FPGADigilentのBasys3(XilinxのArtix-7が入った評価ボード)を用います。
とは言っても、表示系にVGAを用いるのは時間を考えると辛いので、7セグに表示することにしました。
7セグなので当然認識しにくい文字もありますが、その辺は割り切ることにします。
#大好きなキュアパインが識別できるならよい

まずは、仕様の確認です。
Basys3のマニュアル(pdf)を読むとアノードコモンの7セグが4つ付いていて、カソード側は4つの7セグで共通とのこと。

制御のタイミングもかかれているので、これを参考に入力を作ります。

Basys3のクロックは100MHzなので適当に分周して各アノードのトランジスタをONにする250usぐらいの信号を作ります。
1clk=1nsなので2^18カウントすると約262us。
このクロックでアノードを制御します。

さらに、4文字分しか表示できないのでスクロールする必要があるので、
分周したクロックを2^8カウントします。
このあたりは適当にチラつきとか動きが早すぎないか?遅すぎないか?と見ながら適当に調整します。

あとは、プリキュアの名前を7セグで表示するように変換します。

カソード側をON・OFFして文字を作るのでスイッチをONしたところが消灯して、OFFしたところ点灯します。
アルファベットはwikipediaの7セグをパターンを使うことにします。
1文字を{DP, CG, CF, CE, CD, CC, CB, CA}の順番に並べると
たとえば、"CURE PINE"であれば"11000110_11100011_10101111_10000110_11111111_10001100_11111011_10101011_10000110"となります。
あとは表示したいキャラ分これを作ってIDに対して名前を出力する回路を作ればOKです。
#実際にはキャラクタ名は16文字分として確保して、余った部分は消灯で埋めています。
スクロールの実装はこのデータを8bit(1文字)ずつ循環させれば簡単にできます。

さて、全員分の名前が表示されるようになったら、ランダムに選択する部分を実装します。
回路でランダムっぽいのを実現するにはLFSRをつかうのが簡単です。
プリキュアTVシリーズのメンバであれば63通りあれば充分なので、6bitのLFSRを計算し、ボタンを押した時の値をIDとして使います。

ということで、ボタンを押すとプリキュアの名前がランダムに表示される回路ができあがりました。

以上、プリキュアの名前をランダムに表示する回路でした。

https://github.com/a5teri5m/precure_7seg