”
”IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort”をやってみる8 ”の続き。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトをやってみることにしたということで、前回は、正常に動作した Vivado 2019.2 のプロジェクトを Vivado 2020.1 に変換して、カメラ画像がディスプレイに表示できるかどうか?確かめてみたところ、正常に画像を表示できた。今回は、更に Vivado 2020.2 に変換してカメラ画像がディスプレイに表示できるか?確かめてみよう。
結論から言うと Vivado 2020.1 プロジェクトを Vivado 2020.2 に変換しても、正常にカメラ画像を表示することができた。
これで、無料になった MIPI CSI-2 Rx Subsystem を使うことができるようなった。
次に自分で新規の Vivado 2020.2 プロジェクトを作成して IP を追加して、ブロックデザインを作ってみた(ultra96v2_picam2_dp_202_2)が、こちらはカメラ画像をディスプレイに表示することができなかった。何かが足りないようだ。
File メニューから Export -> Export Block Design... を選択して、 design_1.tcl ファイルを作成した。
新規の Vivado 2020.2 プロジェクトをもう一度作成して、 design_1.tcl ファイルでブロックデザインを再生して、やってみたところカメラ画像をディスプレイに表示することができた。
gtkterm の表示内容を示す。
ディスプレイのカメラ画像を示す。(使いまわしだ)
2021年01月31日 04:32 |
Ultra96
| トラックバック:0
| コメント:0
”
”IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort”をやってみる7 ”の続き。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトをやってみることにしたということで、前回は、Vivado の他のバージョンではどうなんだろう?ということで、Vivado 2019.2 を使ってやってたところ、正常にカメラ画像がディスプレイに表示できた。今回は、正常に動作した Vivado 2019.2 のプロジェクトを Vivado 2020.1 に変換して、カメラ画像がディスプレイに表示できるかどうか?確かめてみよう。
Vivado 2019.2 の前回のプロジェクトを Vivado 2020.1 で読み込むと IP をアップグレードするかを聞いてくるので、アップグレードを選択して、IP をアップグレードした。
プロジェクトを示す。
ブロックデザインを示す。
論理合成、インプリメンテーション、ビデオストリームの生成を行った。結果を示す。
Vitis 2020.1 の画面を示す。Vitis プロジェクトは作り直した。
Ultra96V2 で試したところ、正常にカメラ画像をディスプレイに表示することができた。
gtkterm の表示を示す。
ただし、Vitis 2019.2 のプロジェクトもそうだけど、画面がほんの少し揺れるときがある。昨日の晩は少し揺れたけど、今朝はピッタリ止まって表示されている。何らかの原因があるのだろうか?
2021年01月30日 04:00 |
Ultra96
| トラックバック:0
| コメント:0
”
”IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort”をやってみる6 ”の続き。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトをやってみることにしたということで、前回は、Mini DisplayPort のポートがあるディスプレイを購入したので、カメラ画像が映るかどうか?確かめた。カメラ画像は映ったのだが、チラチラしていて正常に表示されない。今回は、Vivado の他のバージョンではどうなんだろう?ということで、Vivado 2019.2 を使ってやってみることにした。
まずは、
source tools/Xilinx/Vitis/2019.2/settings64.sh を実行して、 Vivado 2019.2 の環境を整える。
ultra96v2_imx219_to_displayport/fpga ディレクトリに行って、
make clean を行った。
ultra96v2_imx219_to_displayport/fpga ディレクトリの Makefile を下のように修正した。
make build/design_1/design_1.bd を実行した。
design_1 ブロックデザインが生成された。
Vivado 2019.2 を立ち上げて、 ultra96v2_picam2_dp_192 プロジェクトを作成した。
design_1 ブロックデザインをインポートして、Create HDL Wrapper で Verilog HDL のラッパーファイルを生成した。
Ulra96_V2_constraints_190430.xdc をインポートした。
ブロックデザインを示す。
Address Editor を示す。
論理合成、インプリメンテーション、ビデオストリームの生成を行った。
Project Summary を示す。
Export Hardware を行った。
Vivado 2020.2 の Tools メニューから Launch Vitis IDE を選択して Vitis 2020.2 を立ち上げる。
Vitis IDE Launcher ダイアログが表示される。
Workspace を選択するのに Brows... ボタンをクリックする。
ultra96v2_picam2_dp_192 ディレクトリで vitis_work 新規フォルダーを作成する。
ltra96v2_picam2_dp_192/vitis_work ディレクトリに入る。”開く”ボタンをクリックする。
Vitis IDE Launcher ダイアログに戻って、ultra96v2_picam2_dp_192/vitis_work ディレクトリが選択されているので、Launch ボタンをクリックする。
Vitis IDE が開いた。
PROJECT から Create Application Project をクリックする。
New Application Project ダイアログが開く。
Platform 画面で Create a new platform from hardware (XSA) タブをクリックする。
XSA File の Brows... ボタンをクリックする。
ultra96v2_picam2_dp_192/design_1_wrapper.xsa ファイルを選択し、”開く”ボタンをクリックする。
XSA File が指定され、Platfom name には design_1_wrapper が表示された。
Application Project Details 画面では、Application project name に ultra96v2_picam2_dp を指定した。
Domain 画面。デフォルトのまま。
Templetes 画面では、Empty Application を選択する。
プラットフォームとアプリケーション・プロジェクトが作成された。
ultra96v2_picam2_dp_system -> ultra96v2_picam2_dp -> src を選択して、右クリックし右クリックメニューから Import Sources... を選択する。
Import Sources ダイアログが開く。
lscript.ld 以外のすべてのファイルにチェックを入れて、Finish ボタンをクリックする。
ultra96v2_picam2_dp_system -> ultra96v2_picam2_dp -> src に選択したファイルがインポートされた。
design_1_wrapper プラットフォームを展開して、 platform.spr をクリックする。
design_1_wrapper -> psu_cortexa53_0 -> zynqmp_fsbl -> Board Support Package をクリックする。
Modify BSP Settings ボタンをクリックする。
Board Support Package Settings ダイアログで standalone をクリックすると、stdin, stdout が psu_uart_0 に設定されているのが分かる。
それを psu_uart_1 に変更する。
同様に、standalone _psu_cortex53_0 -> Board Support Package の Modify BSP Settings ボタンをクリックする。
Board Support Package Settings ダイアログで standalone をクリックし、stdin, stdout を psu_uart_1 に変更する。
psu_pmu_0 -> zynqmp_pmufw -> Board Support Package の Modify BSP Settings ボタンをクリックする。
Board Support Package Settings ダイアログで standalone をクリックし、stdin, stdout を psu_uart_1 に変更する。
ultra96v2_picam2_dp_system を右クリックし右クリックメニューから Build Project を選んだらビルドが始まって、成功した。
Ultra96V2 + Picam2 と MIPI Adapter Mezzanine を用意し、Ultra96V2 を JTAG モードにして、電源をON した。
Vitis 2020.2 IDE の Assistant ウインドウで ultra96v2_picam2_dp_system -> ultra96v2_picam2_dp -> Debug を右クリックし右クリックメニューから Launch on Hardware (Single Application Debug) を選択した。
ZynqMP がコンフィギュレーションされて、カメラ画像が正常に表示された。成功だ。。。
gtkterm の画面を示す。
2021年01月29日 04:54 |
Ultra96
| トラックバック:0
| コメント:0
”
”IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort”をやってみる5 ”の続き。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトをやってみることにしたということで、前回は、Vivado プロジェクトにデバック用の ILA IP が実装されているので、Vivado Analyzer で実機の波形を確認したが波形が出ていて動作していそうだった。今回は、Mini DisplayPort のポートがあるディスプレイを購入したので、カメラ画像が映るかどうか?確かめてみる。
購入したディスプレイはいっとうさんと同じ
13.3インチのモバイル・ディスプレイ だ。
このディスプレイにはネイティブに Mini DisplayPort の入力端子がある。
Vitis から Ultra96V2 をコンフィギュレーションして、アプリケーション・ソフトウェアを起動した。
ターミナルの表示を示す。
今度は
、Lane count = 2 Link rate = 540Gbps
になっている。
表示はカメラ画像は映っているようなのだが、チラチラして、画像位置もおかしいようだ。
う〜ん。何処が悪いのだろうか?
148.5 MHz の HD 解像度のビデオストリーム出力を 100 MHz で出力しているということで、AXI4-Stream to Video Out IP が underflow しているんじゃないだろうか?ということで、Vivado Analyzer で AXI4-Stream to Video Out IP の underflow の Rise をトリガにしてみたが、トリガかからなかった。つまり underflow していない。。。
あれ?もしかして、Zynq UltraScale MPSoC の DisplayPort って dp_video_out の hsync と vsync 、 de_out に同期させる必要があったんじゃなかったかな? (追記)もしかすると、ベアメタルだとDPDMAとか設定されていないから、こちらから供給してもOKとかあるのかな? (更に追記)PLから入れるクロックと切り替えができると教えてもらった。調べてみると、displayport.c の中で、XAVBuf_SetAudioVideoClkSrc(&avbuf, XAVBUF_PL_CLK, XAVBUF_PS_CLK);
を実行しているので、PLからのクロックに切り替わっているようだ。 ”
Ultra96のDisplayPortを使用するためのテスト3(XGA解像度のdisplay_cont) ”
”
Ultra96のDisplayPortを使用するためのプロジェクトを作成する1(DisplayPort_test_XGA1_sync) ”
”
MX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort ”では、 dp_video_out_hsync と dp_video_out_vsync が使われていないので、画像が流れるのは、もしかして当たり前なんじゃないだろうか?
2021年01月28日 05:26 |
Ultra96
| トラックバック:0
| コメント:0
”
IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort ”については、いっとうさんがカメラ画像が写ったということなので、同じディスプレイを購入した。今日届くので、試してみようと思う。
MIPI について調べたいと思っていたので、MIPI CS-2 Receiver Subsystem IP を見てみよう。
”
IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort ”のブロックデザインでの MIPI CS-2 Receiver Subsystem IP を示す。
MIPI CS-2 Receiver Subsystem IP をダブルクリックして設定を確認する。
現在のカメラは Raspberry Pi Camera Ver.2.1 のソニー製のカメラだ。
MIPI CS-2 Receiver Subsystem IP の設定ダイアログの Configuration タブを示す。
Pixel Format は RAW10 Serial Data Lanes は 2 レーンだった。
Include Video Format Bridge にチェックが入っている。
DPHY の Line Rate (Mbps) は 912 Mbps だった。
CSI-2 Option は CSI2 Conroller Registor Interface にチェックが入っている。
Line Buffer Depth は 4096 だった。
(2021/01/30:追記) 動作した Vivado 2019.2 では 512 だった。
VFB Options の Allowed VC は All 、 Pixels Per Clock は 1 、 TUSER Width は 1 だった。
Shared Login タブを示す。
Select whether the MMCM and PLL are included in the core itself or in the example design は Include Shared Logic in core のラジオボタンにチェックが入っている。
Pin Assignment タブを示す。
Clock Lane や Data Lane のピン配置の設定がある。
このピン配置は、特定の位置のピンに決まっているようで、例えば、 Clock Lane の選択肢を示すが、これらから選択となるようだ。
Application Example Design タブを示す。
Target Board は ZCU102 、 FCM Model は LI-IMX274MIPI-FMC V1.0 Single Sensor 、 Design Topology は MIPI Video Pipe Camera to Display だった。
ここで Target Board の選択肢を見てみよう。
他に SP701 と VCK190 がある。
SP701 は
Spartan-7 SP701 FPGA 評価キット で 7 シリーズ用の MIPI CS-2 Receiver Subsystem IP のようだ。
VCK190 は
Versal AI コア シリーズ VCK190 評価キット で、Versal 用の MIPI CS-2 Receiver Subsystem IP のようだ。
(2021/01/29:追記)
すべてのバスを展開した MIPI CS-2 Receiver Subsystem IP を示す。
video_out_tdata[15:0] と 16 ビット幅となっている。
2021年01月27日 05:14 |
IP
| トラックバック:0
| コメント:0
”
”IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort”をやってみる4 ”の続き。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトをやってみることにしたということで、前回は、 Ultra96V2 + Picam2 と MIPI Adapter Mezzanine を用意し、アプリケーション・ソフトウェアを起動してカメラをディスプレイに表示しようとしたが黒い画像が表示されただけだった。今回は、Vivado プロジェクトにデバック用の ILA IP が実装されているので、Vivado Analyzer で実機の波形を確認してみよう。
Vitis 2020.2 でアプリケーション・ソフトウェアを起動してから、Vivado 2020.2 で Flow Navigator の PRGRAM AND DEBUG -> Open Hardware Manager -> Open Target -> Auto Connect を選択した。
Vivado Analyzer の画面が表示された。
最初に ila_0 の波形を観察する。
ila_0 は、 mipi_csi2_rx_subsyst_0 の video_out に入れてある。
hw_ila_1 が ila_0 の波形のようだ。
拡大してみよう。
TDATA[15:0] を見ると、上位バイトは 00 だが、下位バイトに値が入っているようだ。
hw_ila_2 には、ビデオ関係の各種制御信号が入っている。
hsync などが動いているのが分かる。
vsync にトリガを掛けてみたが、動いていた。
hw_ila_3 は、 AXI_VDMA の M_AXIS_MM2S の AXI4-Stream 出力を受けた Video Test Pattern Generator の vtg_0 の m_axis_video 出力に接続されている。
拡大すると TDATA にデータが出力されているのが分かる。
hw_ila_4 は、 v_gamma_lut_0 の出力 m_axi_video に接続されている。これは、 AXI VDMA の S_AXIS_S2MM に接続されている。つまりカメラ側の最終ステージとなる。
拡大すると、やはりデータが流れているのが分かる。
hw_ila_5 は AXI_VDMA の M_AXIS_MM2S の AXI4-Stream 出力に接続されている。 Video Test Pattern Generator の vtg_0 の s_axis_video に接続されている。
拡大すると、やはり TDATA にデータが流れているのが分かる。
今まで見てきた Vivado Analyzer の波形はすべて問題無さそうなのだが、何処が悪いのだろうか?
ソフトウェアを詳しく見ていこう。
2021年01月26日 04:27 |
Ultra96
| トラックバック:0
| コメント:0
”
”IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort”をやってみる3 ”の続き。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトをやってみることにしたということで、前回は、Vitis 2020.2 を起動してプラットフォームとアプリケーション・プロジェクトを作成して、ビルドを行って成功した。今回は、 Ultra96V2 + Picam2 と
MIPI Adapter Mezzanine を用意し、アプリケーション・ソフトウェアを起動してカメラをディスプレイに表示してみよう。
最初に、UART を ps_uart_1 にするのを忘れていた。これでは、ターミナルに表示できないので、変更しよう。
design_1_wrapper プラットフォームを展開して、 platform.spr をクリックする。
design_1_wrapper -> psu_cortexa53_0 -> zynqmp_fsbl -> Board Support Package をクリックする。
Modify BSP Settings ボタンをクリックする。
Board Support Package Settings ダイアログで standalone をクリックすると、stdin, stdout が psu_uart_0 に設定されているのが分かる。
それを psu_uart_1 に変更する。
同様に、standalone _psu_cortex53_0 -> Board Support Package の Modify BSP Settings ボタンをクリックする。
Board Support Package Settings ダイアログで standalone をクリックし、stdin, stdout を psu_uart_1 に変更する。
psu_pmu_0 -> zynqmp_pmufw -> Board Support Package の Modify BSP Settings ボタンをクリックする。
Board Support Package Settings ダイアログで standalone をクリックし、stdin, stdout を psu_uart_1 に変更する。
Ultra96V2 + Picam2 と
MIPI Adapter Mezzanine を用意し、Ultra96V2 を JTAG モードにして、電源をON した。
Vitis 2020.2 IDE の Assistant ウインドウで ultra96v2_picam2_dp_system -> ultra96v2_picam2_dp -> Debug を右クリックし右クリックメニューから Launch on Hardware (Single Application Debug) を選択した。
ZynqMP がコンフィギュレーションされて、ディスプレイでは黒い画像が表示されているのだろうか?画面は真っ暗だが、No Signal にはならない。。。
gtkterm に表示はされている。(115200 bps, 8 bit, 1 Stop bit)
現在のUltra96V2 + Picam2 と
MIPI Adapter Mezzanine の接続の様子を示す。
MIPI Adapter Mezzanine の上に PMOD 出力のドータボードが乗っている。そこの設定ピンは下の
MIPI Adapter Mezzanine と同じ位置に設定ピンをすればOKだ。
2021年01月24日 09:55 |
Ultra96
| トラックバック:0
| コメント:0
”
”IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort”をやってみる2 ”の続き。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトをやってみることにしたということで、前回は、Vivado 2020.2 を起動して、プロジェクトを作成し、 make で生成されたブロックデザイン・ファイルをインポートしたところ、不完全だったので、 tcl ファイルを起動してブロックデザインを作り直した。制約ファイルを追加して、論理合成、インプリメンテーション、ビットストリームの生成を行い、XSA ファイルを生成した。今回は、Vitis 2020.2 を起動してプラットフォームとアプリケーション・プロジェクトを作成して、ビルドを行う。
Vivado 2020.2 の Tools メニューから Launch Vitis IDE を選択して Vitis 2020.2 を立ち上げる。
Vitis IDE Launcher ダイアログが表示される。
Workspace を選択するのに Brows... ボタンをクリックする。
ultra96v2_picam2_dp ディレクトリで vitis_work 新規フォルダーを作成する。
ultra96v2_picam2_dp/vitis_work ディレクトリに入る。”開く”ボタンをクリックする。
Vitis IDE Launcher ダイアログに戻って、ultra96v2_picam2_dp/vitis_work ディレクトリが選択されているので、Launch ボタンをクリックする。
Vitis IDE が開いた。
PROJECT から Create Application Project をクリックする。
New Application Project ダイアログが開く。
Platform 画面で Create a new platform from hardware (XSA) タブをクリックする。
XSA File の Brows... ボタンをクリックする。
ultra96v2_picam2_dp/design_1_wrapper.xsa ファイルを選択し、”開く”ボタンをクリックする。
XSA File が指定され、Platfom name には design_1_wrapper が表示された。
Application Project Details 画面では、Application project name に ultra96v2_picam2_dp を指定した。
Domain 画面。デフォルトのまま。
Templetes 画面では、Empty Application を選択する。
プラットフォームとアプリケーション・プロジェクトが作成された。
ultra96v2_picam2_dp_system -> ultra96v2_picam2_dp -> src を選択して、右クリックし右クリックメニューから Import Sources... を選択する。
Import Sources ダイアログが開く。
lscript.ld 以外のすべてのファイルにチェックを入れて、Finish ボタンをクリックする。
ultra96v2_picam2_dp_system -> ultra96v2_picam2_dp -> src に選択したファイルがインポートされた。
design_1_wrapper プラットフォームを展開して、 platform.spr をクリックする。
design_1_wrapper -> psu_cortexa53_0 -> zynqmp_fsbl -> Board Support Package をクリックする。
Modify BSP Settings ボタンをクリックする。
drivers をクリックして、 psu_dp を見ると Driver は dppsu になっている。これでツィッターの情報によると良いようなのだが、Ubuntu 20.04 LTS では、 avbuf になっていたのだが、この Ubuntu 18.04 だとデフォルト値が違うのだろか?
修正する手間がなくてよいが、何か納得行かない。。。
3 個すべての Board Support Package の psu_dp の Driver は dppsu になっていた。
これで、 ultra96v2_picam2_dp_system を右クリックし右クリックメニューから Build Project を選んだらビルドが始まって、成功した。
2021年01月23日 14:01 |
Ultra96
| トラックバック:0
| コメント:0
”
”IMX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort”をやってみる1 ”の続き。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトをやってみることにしたということで、前回は、”
MX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort ”を git clone して、 make を行った。今回は、Vivado 2020.2 を起動して、プロジェクトを作成し、前回 make で生成されたブロックデザイン・ファイルをインポートしたところ、不完全だったので、 tcl ファイルを起動してブロックデザインを作り直した。制約ファイルを追加して、論理合成、インプリメンテーション、ビットストリームの生成を行い、XSA ファイルを生成する。
Vivado 2020.2 を立ち上げて、Create Project をクリックした。
New Project ダイアログの Project Name 画面では、 Project name に ultra96v2_picam2_dp を入力した。
Default Part 画面では、 Boards をクリックして、 Vendor に avnet.com を選択し、 Ultra96v2 Single Board Computer を選択した。
ultra96v2_picam2_dp プロジェクトが生成された。
make で生成されたブロックデザインをインポートしよう。
Sources ウインドウで右クリックし右クリックメニューから Add Sources... を選択する。
Add Sources ダイアログが立ち上がる。
Add or create design sources のラジオボタンをクリックする。
Add or Create Design Soures 画面で Add Files ボタンをクリックする。
ultra96v2_imx219_to_displayport/fpga/build/design_1 ディレクトリの design_1.bd を選択する。
Add or Create Design Soures 画面に戻って、 Copy soures into project のチェックボックスにチェックを入れる。
Sources ウインドウの Design Sources に design_1 が入った。
ブロックデザインを見ると不完全とうことが分かる。
ツィッターで知ったのだが、このブロックデザインを削除して、tcl ファイルを起動して、ブロックデザインを作り直すと良いそうだ。
ultra96v2_imx219_to_displayport/fpga/bd ディレクトリの imx219_to_mpsoc_displayport_vivado2020.2.tcl ファイルを実行する。
design_1 ブロックデザインを削除した。
Vivado 2020.2 の TCL Console で次のコマンドを実行した。
cd /media/masaaki/Ubuntu_Disk/HDL/Ultra96V2/ultra96v2_imx219_to_displayport/fpga/bd source ./imx219_to_mpsoc_displayport_vivado2020.2.tcl すると、ブロックデザインが生成された。
ブロックデザインを拡大する。
今度は大丈夫そうだ。
Address Editor 画面を示す。
Address Map 画面を示す。
Sources ウインドウで design_1 _i を右クリックし右クリックメニューから Create HDL Wrapper... をクリックして、 design_1_wrapper を生成した。
次は制約ファイルだが、 ultra96v2_imx219_to_displayport/fpga/constraints ディレクトリの Ultra96_V2_constraints_190430.xdc をインポートしよう。
Sources ウインドウで右クリックし右クリックメニューから Add Sources... を選択する。
Add Sources ダイアログが立ち上がる。
Add or create constraints のラジオボタンをクリックする。
Add Files ボタンをクリックして、ultra96v2_imx219_to_displayport/fpga/constraints ディレクトリの Ultra96_V2_constraints_190430.xdc を選択した。
Copy soures into project のチェックボックスにチェックを入れて、Finish ボタンをクリックする。
Ultra96_V2_constraints_190430.xdc がプロジェクトに入った。
Flow Navigator で Generate Bitstream をクリックして、論理合成、インプリメンテーション、ビットストリームの生成を行う。
ビットストリームの生成が成功した。 Project Summary を示す。
File メニューから Export -> Export Hardware... を選択する。
Export Hardware Platform ダイアログが表示される。
Export Hardware Platform 画面は Next > ボタンをクリックして進める。
Output 画面では、 Include bitstream ラジオボタンをクリックする。
Files 画面では、 XSA ファイル名と Export されるディレクトリが表示されている。
Exporting Hardware Platform 画面では、 Finish ボタンをクリックする。
design_1_wrapper.xsa ファイルが生成された。
2021年01月22日 04:46 |
Ultra96
| トラックバック:0
| コメント:0
このところ、ツィッターで話題の”
MX219 MIPI sensor to Ultra96-V2 FPGA DisplayPort ”をやってみたいということでやってみることにした。
これは、Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続して、 DisplayPort で表示するプロジェクトだ。
Raspberry Pi のソニー製Ver. 2 カメラを Ultra96V2 に接続するには、
AISTARVISION MIPI Adapter V2.1 が必要になる。これはすでに販売中止だが、幸運なことに私はすでに持っている。
最初に Vivado 2020.2 の settings64.sh を走らせておく。
例
source /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis/2020.2/settings64.sh 最初に ultra96v2_imx219_to_displayport を git clone する。
git clone https://github.com/gtaylormb/ultra96v2_imx219_to_displayport.git ultra96v2_imx219_to_displayport ディレクトリを示す。
ultra96v2_imx219_to_displayport/fpga ディレクトリを見ると Makefile がある。
Makefile を見ると build/design_1/design_1.bd を実行すれば良さそうだ。
BD_SRC = \ bd/imx219_to_mpsoc_displayport_vivado2020.2.tcl
なので Vivado 2020.2 で実行できそうだ。
cd ultra96v2_imx219_to_displayport/fpga/ して、
make build/design_1/design_1.bd を実行した。
build ディレクトリが生成され、その下に design_1 ディレクトリができて、その下に ip ディレクトリと design_1.bd ファイルが生成されている。
2021年01月21日 04:47 |
Ultra96
| トラックバック:0
| コメント:0
”
Vitis Vision Library の medianblur を ZYBO Z7-20 で使ってみる3 ”の続き。
AXI4 Master 版のメディアン・フィルタと XF_8UC3 を XF_8UC4 に変換する IP を使用して、メディアン・フィルタ処理後の画像をディスプレイに出力するシステムを作成しようということで、前回は、 Vitis 2020.2 を立ち上げて、プラットフォームとアプリケーション・プロジェクトを作成し、実機検証を行い、フィルタ処理画像を見ることができた。今回は、複雑な構成になっているので、後先間違っているようだが、ブロック図を書いて、構成を説明する。
使用するボードは ZYBO Z7-20 で、使用ツールは Vivado 2020.2, Vitis 2020.2 だ。
まずは、今回の Vivado 2020.2 の median_vision プロジェクトの構成図を示す。
ソフトウェア側には、 bmp_data.h と median_vision.c がある。
bmp_data.h は 800 x 600 ピクセルの画像に、ノイズを拡散した画像を C のヘッダ・ファイルにしたコードとなっている。 median_vision.c は bmp_data.h を読み込んで、 CV_8UC3 の画像データ(ORG_CV_8UC3 とする)と CV_8UC4 の画像データ(ORG_CV_8UC4 とする)を DDR SDRAM のアドレスに書き込む。
median_vision.c は各 IP の初期化や、設定、ターミナルにプロンプトを表示して、ビットマップ・ディスプレイ・コントローラーの表示画像を切り替えている。
ORG_CV_8UC3 が CV::Mat のデータの部分で、このフォーマットは”
Vitis Vision Library の AXI4 Master インターフェース版 medianblur をZYBO Z7-20 で使ってみる1(準備編) ”で解析していて、下に示すようなフォーマットになっている。
ORG_CV_8UC4 は 1 ピクセルが 32 ビット単位で、上のバイトレーンから順番にアルファ・チャネル 8 ビット、 Red 8 ビット、 Green 8 ビット、 Blue 8 ビットとなっていて、ビットマップ・ディスプレイ・コントローラーが直接表示できるフォーマットとなっている。
メディアン・フィルタ(median_blur_accel)は CV_8UC3 のデータ部分(ORG_CV_8UC3)を DMA Read して、CV_8UC3 のデータ部分のフィルタ結果(FILT_CV_8UC3 とする)を DMA Write する。 CV_8UC3 のデータではビットマップ・ディスプレイ・コントローラーが表示できないので、 CV_8UC4 に変換する必要がある。そこで、CV_8UC3 を画像フォーマット変換(Xf_8uc3_2rgb)で CV_8UC4 (FILT_CV_8UC4 とする)に変換している。その結果をビットマップ・ディスプレイ・コントローラーで表示する。
それで、ビットマップ・ディスプレイ・コントローラー は ORG_CV_8UC4 と FILT_CV_8UC4 を切り替えてディスプレイに表示する。切り替えの指示はターミナルに 0 を入力するか? 1 を入力するか?で切り替える。
0 の時は、 ORG_CV_8UC4 を表示して、 1 の時は FILT_CV_8UC4 をディスプレイに表示する。
2021年01月20日 04:43 |
Vitis_Vision
| トラックバック:0
| コメント:0
AXI4 Master 版のメディアン・フィルタと XF_8UC3 を XF_8UC4 に変換する IP を使用して、メディアン・フィルタ処理後の画像をディスプレイに出力するシステムを作成しようということで、前回は、タイミングエラーを解消して、ビットストリームの生成が成功して、XSA ファイルを生成した。今回は、Vitis 2020.2 を立ち上げて、プラットフォームとアプリケーション・プロジェクトを作成し、実機検証を行う。
Vitis 2020.2 を立ち上げて、前回生成した median_v_bd_wrapper.xsa ファイルを元に、median_v_bd_wrapper プラットフォームを作成し、median_vision アプリケーション・プロジェクトを作成した。
画像をヘッダに変換した bmp_data.h を用意して、アプリケーション・ソフトウェアの median_vision.c を作成した。
median_vision.c のコードを貼っておく。
// median_vision.c // 2021/01/16 by marsee // #include <stdio.h> #include <stdint.h> #include "xil_io.h" #include "xparameters.h" #include "xmedian_blur_accel.h" #include "xxf_8uc3_2rgb.h" #include "bmp_data.h" #define ORG_PICT_XF_8UC4_ADDR 0x10000000 #define ORG_PICT_XF_8UC3_ADDR 0x10200000 #define FILTER_XF_8UC3_ADDR 0x10400000 #define FILTER_XF_8UC4_ADDR 0x10600000 #define HORIZONTAL_PIXELS 800 #define VERTICAL_LINES 600 int bmp_write_xf_8uc3(uint32_t xf_8uc4_addr, uint32_t xf_8uc3_addr); void Xil_DCacheFlush(void); int main(){ XMedian_blur_accel XMedian_blur_accel_ap; XXf_8uc3_2rgb XXf_8uc3_2rgb_ap; int inbyte_in; XMedian_blur_accel_Initialize(&XMedian_blur_accel_ap, 0); XXf_8uc3_2rgb_Initialize(&XXf_8uc3_2rgb_ap, 0); XMedian_blur_accel_Set_rows(&XMedian_blur_accel_ap, (u32)VERTICAL_LINES); XMedian_blur_accel_Set_cols(&XMedian_blur_accel_ap, (u32)HORIZONTAL_PIXELS); XXf_8uc3_2rgb_Set_rows(&XXf_8uc3_2rgb_ap, (u32)VERTICAL_LINES); XXf_8uc3_2rgb_Set_cols(&XXf_8uc3_2rgb_ap, (u32)HORIZONTAL_PIXELS); XMedian_blur_accel_Set_img_in(&XMedian_blur_accel_ap, (u32)ORG_PICT_XF_8UC3_ADDR); XMedian_blur_accel_Set_img_out(&XMedian_blur_accel_ap, (u32)FILTER_XF_8UC3_ADDR); XXf_8uc3_2rgb_Set_p_src(&XXf_8uc3_2rgb_ap, (u32)FILTER_XF_8UC3_ADDR); XXf_8uc3_2rgb_Set_p_dst(&XXf_8uc3_2rgb_ap, (u32)FILTER_XF_8UC4_ADDR); bmp_write_xf_8uc3(ORG_PICT_XF_8UC4_ADDR, ORG_PICT_XF_8UC3_ADDR); Xil_DCacheFlush(); XMedian_blur_accel_Start(&XMedian_blur_accel_ap); while(!XMedian_blur_accel_IsDone(&XMedian_blur_accel_ap)); XXf_8uc3_2rgb_Start(&XXf_8uc3_2rgb_ap); while(!XXf_8uc3_2rgb_IsDone(&XXf_8uc3_2rgb_ap)); Xil_Out32(XPAR_BITMAP_DISP_CNTRLER_0_BASEADDR, ORG_PICT_XF_8UC4_ADDR); while(1){ printf("\nPlease input <0> or <1> (<q> : exit) = "); fflush(stdout); inbyte_in = inbyte(); printf("%c", inbyte_in); fflush(stdout); switch(inbyte_in) { case '0': //bmp image Xil_Out32(XPAR_BITMAP_DISP_CNTRLER_0_BASEADDR, ORG_PICT_XF_8UC4_ADDR); break; case '1': // Laplacian filter Xil_Out32(XPAR_BITMAP_DISP_CNTRLER_0_BASEADDR, FILTER_XF_8UC4_ADDR); break; case 'q': // exit return(0); } } } int bmp_write_xf_8uc3(uint32_t xf_8uc4_addr, uint32_t xf_8uc3_addr){ uint32_t pix[4]; for(int y=0; y<VERTICAL_LINES; y++){ for(int x=0; x<HORIZONTAL_PIXELS; x++){ int xf_8uc4 = 0xff000000 + ((uint32_t)bmp_file_array[y][x][2]<<16) +((uint32_t)bmp_file_array[y][x][1]<<8)+(uint32_t)bmp_file_array[y][x][0]; Xil_Out32(xf_8uc4_addr+(y*HORIZONTAL_PIXELS+x)*sizeof(uint32_t), xf_8uc4); switch((x+y*HORIZONTAL_PIXELS)%4){ case 0 : pix[0] = xf_8uc4; break; case 1 : pix[1] = xf_8uc4; Xil_Out32(xf_8uc3_addr, ((pix[1]&0xff)<<24)+(pix[0]&0xffffff)); xf_8uc3_addr += sizeof(uint32_t); break; case 2 : pix[2] = xf_8uc4; Xil_Out32(xf_8uc3_addr, ((pix[2]&0xffff)<<16)+((pix[1]&0xffff00)>>8)); xf_8uc3_addr += sizeof(uint32_t); break; default : // 3 pix[3] = xf_8uc4; Xil_Out32(xf_8uc3_addr, ((pix[3]&0xffffff)<<8)+((pix[2]&0xff0000)>>16)); xf_8uc3_addr += sizeof(uint32_t); break; } } } return(0); }
ビルドすると median_vision.elf ができた。
ZYBO Z7-20 を接続して、電源ON した。
ターミナルで
sudo gtkterm を入力して、 gtkterm を立ち上げて、 115200 bps, 8bit, 1 stop bit に設定した。
Assistant ウインドウの median_vision_system -> median_vision -> Debug を右クリックし、右クリックメニューから Run -> Launch on Hardware (Single Application Debug) を選択して、アプリケーションを起動した。
gtkterm に表示されている。
0 を入力すると元画像で、 1 を入力するとメディアン・フィルタ処理されているはずだ。
最初に表示された元画像は正常に表示されている。 gtkterm で 0 を入力しても同様だ。
ノイズが追加されているのが分かると思う。
gtkterm で 1 を入力したところ、メディアン・フィルタ処理画像が表示された。成功だ。
元画像のノイズが取り除かれている。
2021年01月19日 05:04 |
Vitis_Vision
| トラックバック:0
| コメント:0
AXI4 Master 版のメディアン・フィルタと XF_8UC3 を XF_8UC4 に変換する IP を使用して、メディアン・フィルタ処理後の画像をディスプレイに出力するシステムを作成しようということで、前回は、IP を用意して、ブロックデザインを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行ったところ、タイミング・エラーが発生した。今回は、タイミング・エラーの解消をめざそう。
Intra-Clock のタイミング・エラーが出ているので、 clk_fpga_0 の動作周波数を 100 MHz から 80 MHz に下げてみよう。
これで、再度、論理合成、インプリメンテーション、ビットストリームの生成を行ったが、やはり、タイミング・エラーで clk_fpga_0 の Intra-Clock エラーが出ている。
ここで、CDC は大丈夫と検証されている(ということにしているので)、clk_fpga_0 から pclk_buf へのパスと、 pclk_buf から clk_fpga_0 へのパスに False Path を設定した。
これで、再々度、論理合成、インプリメンテーション、ビットストリームの生成を行った。今度はタイミングがメットした。
ハードウェアをエクスポートして、median_v_bd_wrapper.xsa ファイルを作成した。
2021年01月18日 04:59 |
Vitis_Vision
| トラックバック:0
| コメント:0
”
Vitis HLS 2020.2 で Vitis Vision Library を使用する4(medianblur 編) ”で AXI4 Master による DMA 版のメディアン・フィルタを実装した。この実装は、CV_8UC3 のデータを DMA Read してメディアン・フィルタ処理をして、また CV_8UC3 で DMA Write する。そして、”
XF_8UC3 を XF_8UC4 に変換する xf_8uc3_2rgb プロジェクトを作成する1 ”と”
XF_8UC3 を XF_8UC4 に変換する xf_8uc3_2rgb プロジェクトを作成する2 ”で CV_8UC3 と同等の XF_8UC3 のデータを DMA Read して CV_8UC4 と同等の XF_8UC4 フォーマットで DMA Write する IP ができた。
これら 2 つの IP を組み合わせれば、 CV_8UC3 のデータを DMA Read して、 CV_8UC4 で DMA Write する実装が作れる。 CV_8UC4 のデータはアルファ・チャネル、Red、Green、Blue の 8 ビットずつの 32 ビット幅フォーマットになっているので、既存の自作ビットマップ・ディスプレイ・コントローラーを使用すれば、画像としてディスプレイに表示することができる。
そういうことで早速、Vivado 2020.2 を使用してプロジェクトを作っていこう。
Vivado 2020.2 で median_vision プロジェクトを作成した。
ビットマップ・ディスプレイ・コントローラー IP の BMDispCaL 、medianblur、xf_8uc3_2rgb のディレクトリを作成して、各 IP のファイルを中に入れた。
IP Catalog に各 IP を追加した。
median_v_bd ブロックデザインを作成し、各 IP を Add IP してブロックデザインを完成させた。
なお、 processing_system7_0 の FCLK_CLK0 は 100 MHz で、 FCLK_CLK1 は 25 MHz に設定した。
Address Editor 画面を示す。
Address Map 画面を示す。
median_blur_accel_0 は Vitis HLS で INTERFACE オプションの s_axilite で実装された s_axi_control と Vitis HLS の INTERFACE オプションの m_axi で実装された DMA のオフセットアドレスの s_axi_control_r の 2 つのアドレス領域がある。
ビットマップ・ディスプレイ・コントローラーの HDMI 出力ピンを指定する制約ファイルの median_filter_axis.xdc を作成した。
これで準備が整ったので、論理合成、インプリメンテーション、ビットストリームの生成を行った。
結果を示すと、タイミングエラーが発生している。
Flow Navigator から IMPLEMENTATION -> Open Implemented Design をクリックして、Timing Error を表示した。
clk_fpga_0 の内部のタイミング違反と pclk_buf -> clk_fpga_0 のクロック間のパスのタイミング違反、Other Path Groups の **async_default** で clk_fpga_0 -> pclk_buf のクロック間のパスのタイミング違反がでていた。
2021年01月17日 04:27 |
Vitis_Vision
| トラックバック:0
| コメント:0
”
XF_8UC3 を XF_8UC4 に変換する xf_8uc3_2rgb プロジェクトを作成する1 ”の続き。
XF_8UC3 を XF_8UC4 に変換する xf_8uc3_2rgb プロジェクトを作成してみようと思うということで、前回はソースコードとテストベンチを貼って、 Vitis HLS 2020.2 のプロジェクトを示した。今回は、 C シミュレーション、 C コードの合成、 C/RTL 協調シミュレーション、 Export RTL を行う。
Vitis HLS 2020.2 の xf_8uc3_2rgb プロジェクトの設定を示す。
Vitis HLS 2020.1 から Vitis HLS に同梱される OpenCV のインストールは無いということだ。よって、OpenCV を使用しているテストベンチのインクルード・パスとリンク・パスの設定が必要となる。
Project メニューから Project Settings... を選択して、ダイアログを表示させる。
Simulation をクリックして、 CFLAGS にインストール済みの OpenCV のインクルード・パスを入力する。
-I/usr/local/include
Linker Flagに
-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc
を入力する。
Input Argument に画像のファイル名
128x128_blue123.png
を入力する。
C シミュレーションから。ここでは、
#define DEBUG
のコメントアウトを外す。
結果を示す。
最初は CV_8UC3 のフォーマットの 10 個の入力値が表示され、その下の 10 個の出力値が CV_8UC4 で出力されていることが分かる。
次に、
#define DEBUG
のコメントアウトを行う。
これで C コードの合成を行った。結果を示す。
レイテンシは 480053 クロックだった。 LOOP_TRIPCOUNT が 480000 だったので、レイテンシは良い感じだ。
C/RTL 協調シミュレーションを行ったが、当初 INTERFACE 指示子の m_axi オプションの depth が画像ピッタリのサイズの指定ではなかったため当初はエラーになってしまった。
このようなエラーが起こった場合は、 INTERFACE 指示子の m_axi オプションの depth が画像ピッタリのサイズになっているか?をチェックすることをお勧めする。なお、Vivado HLS 2019.2 と Vitis HLS 2020.1 は Vitis HLS 2020.2 よりも進んで、C/RTL 協調シミュレーションの波形は出力されるが、最終的にエラーになる。
さて、C/RTL 協調シミュレーションを行うには、今回は、画像ファイルのファイル名を指定する必要がある。
C/RTL 協調シミュレーションを開始したら、 Co-Simulation Dialog が表示されるので、 Input Argument に画像ファイルの名前を入れる。波形を観察するために Dump Trace も all にしておく。
結果を示す。
レイテンシは 16446 クロックだった。画像の総ピクセル数は 16384 なので、優秀だ。
C/RTL 協調シミュレーションの波形を示す。
WVALID がほとんど 1 なのが分かる。
波形の最初の部分を拡大してみよう。
無事に CV_8UC4 に変換されていることが分かる。
Export RTL を行って、IP にした。結果を示す。
AXI4 Lite のレジスタマップを示す。
// ============================================================== // Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2020.2 (64-bit) // Copyright 1986-2020 Xilinx, Inc. All Rights Reserved. // ============================================================== // control // 0x00 : Control signals // bit 0 - ap_start (Read/Write/COH) // bit 1 - ap_done (Read/COR) // bit 2 - ap_idle (Read) // bit 3 - ap_ready (Read) // bit 7 - auto_restart (Read/Write) // others - reserved // 0x04 : Global Interrupt Enable Register // bit 0 - Global Interrupt Enable (Read/Write) // others - reserved // 0x08 : IP Interrupt Enable Register (Read/Write) // bit 0 - enable ap_done interrupt (Read/Write) // bit 1 - enable ap_ready interrupt (Read/Write) // others - reserved // 0x0c : IP Interrupt Status Register (Read/TOW) // bit 0 - ap_done (COR/TOW) // bit 1 - ap_ready (COR/TOW) // others - reserved // 0x10 : Data signal of ap_return // bit 31~0 - ap_return[31:0] (Read) // 0x18 : Data signal of p_src // bit 31~0 - p_src[31:0] (Read/Write) // 0x1c : reserved // 0x20 : Data signal of rows // bit 31~0 - rows[31:0] (Read/Write) // 0x24 : reserved // 0x28 : Data signal of cols // bit 31~0 - cols[31:0] (Read/Write) // 0x2c : reserved // 0x30 : Data signal of p_dst // bit 31~0 - p_dst[31:0] (Read/Write) // 0x34 : reserved // (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)
2021年01月15日 04:36 |
Vitis_Vision
| トラックバック:0
| コメント:0
もうだいぶ、Vitis Vision Library には嫌気が差してきたのだが、最後に XF_8UC3 を XF_8UC4 に変換する xf_8uc3_2rgb プロジェクトを作成してみようと思う。
xf_8uc3_2rgb プロジェクトを何で作るのか?だが、とりあえずは Vitis HLS 2020.2 でやってみよう。
まずは、 ソースコードの xf_8uc3_2rgb.cpp を示す。
// xf_8uc3_2rgb.cpp // 2021/01/12 by marsee // 2021/01/12: for Vitis HLS 2020.2 // #include "ap_int.h" #include "hls_stream.h" int dmar2axis(ap_uint<32>* _src, int rows, int cols, hls::stream<ap_uint<32> >& axis_out); int xf_8uc3_2axis(hls::stream<ap_uint<32> >& axis_in, int rows, int cols, hls::stream<ap_uint<32> >& axis_out); int axis2dmaw(hls::stream<ap_uint<32> >& axis_in, int rows, int cols, ap_uint<32>* _dst); #define DEBUG int xf_8uc3_2rgb(ap_uint<32>* _src, int rows, int cols, ap_uint<32>* _dst){ #pragma HLS DATAFLOW #pragma HLS INTERFACE m_axi depth=16384 bundle=gmem port=_dst offset=slave #pragma HLS INTERFACE s_axilite port=cols #pragma HLS INTERFACE s_axilite port=rows #pragma HLS INTERFACE m_axi depth=12288 bundle=gmem port=_src offset=slave #pragma HLS INTERFACE s_axilite port=return hls::stream<ap_uint<32> > axis0, axis1; dmar2axis(_src, rows, cols, axis0); xf_8uc3_2axis(axis0, rows, cols, axis1); axis2dmaw(axis1, rows, cols, _dst); return(0); } int dmar2axis(ap_uint<32>* _src, int rows, int cols, hls::stream<ap_uint<32> >& axis_out){ const int rows_cols_limit = (int)((float)rows * (float)cols * 3.0/4.0 + 0.7); ap_uint<32> pix; //printf("rows_cols_limit = %d\n",rows_cols_limit); LOOP_dr2a: for(int xy=0; xy<rows_cols_limit; xy++){ #pragma HLS PIPELINE II=1 #pragma HLS LOOP_TRIPCOUNT avg=360000 max=360000 min=360000 pix = _src[xy]; axis_out << pix; #ifdef DEBUG if(xy < 10) printf("%x\n", (unsigned int)pix); #endif } return(0); } int xf_8uc3_2axis(hls::stream<ap_uint<32> >& axis_in, int rows, int cols, hls::stream<ap_uint<32> >& axis_out){ ap_uint<32> rgb[3]; ap_uint<32> pix; const int rows_cols_limit = rows * cols; LOOP_x2s:for(int xy=0; xy<rows_cols_limit; xy++){ #pragma HLS PIPELINE II=1 #pragma HLS LOOP_TRIPCOUNT avg=480000 max=480000 min=480000 switch(xy%4){ case 0 : axis_in >> rgb[0]; pix = (rgb[0] & 0xffffff) + 0xff000000; axis_out << pix; break; case 1 : axis_in >> rgb[1]; pix = ((rgb[1] & 0xffff)<<8) + ((rgb[0] & 0xff000000)>>24) + 0xff000000; axis_out << pix; break; case 2 : axis_in >> rgb[2]; pix = ((rgb[2] & 0xff)<<16) + ((rgb[1] & 0xffff0000)>>16) + 0xff000000; axis_out << pix; break; default : // 3 pix = ((rgb[2] & 0xffffff00)>>8) + 0xff000000; axis_out << pix; break; } } return(0); } int axis2dmaw(hls::stream<ap_uint<32> >& axis_in, int rows, int cols, ap_uint<32>* _dst){ const int rows_cols_limit = rows * cols; ap_uint<32> pix; #ifdef DEBUG printf("\n"); #endif LOOP_a2dw:for(int xy=0; xy<rows_cols_limit; xy++){ #pragma HLS PIPELINE II=1 #pragma HLS LOOP_TRIPCOUNT avg=480000 max=480000 min=480000 axis_in >> pix; _dst[xy] = pix; #ifdef DEBUG if(xy < 10) printf("%x\n", (unsigned int)pix); #endif } return(0); }
テストベンチの xf_8uc3_2rgb_tb.cpp を示す。
// xf_8uc3_2rgb_tb.cpp // 2021/01/12 by marsee // #include "ap_int.h" #include "hls_stream.h" #include "opencv2/opencv.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgcodecs/imgcodecs.hpp" int xf_8uc3_2rgb(ap_uint<32>* _src, int rows, int cols, ap_uint<32>* _dst); int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Usage: %s <INPUT IMAGE>", argv[0]); exit(1); } cv::Mat in_img, out_img, conv_img; in_img = cv::imread(argv[1], 1); // reading in the color image if (in_img.data == NULL) { fprintf(stderr, "ERROR: Cannot open image %s\n ", argv[1]); exit(1); } out_img.create(in_img.rows, in_img.cols, CV_8UC4); conv_img.create(in_img.rows, in_img.cols, CV_8UC3); xf_8uc3_2rgb((ap_uint<32> *)in_img.data, in_img.rows, in_img.cols, (ap_uint<32> *)out_img.data); cv::cvtColor(out_img, conv_img, cv::COLOR_BGRA2BGR); cv::imwrite("output.png", conv_img); return(0); }
Vitis HLS 2020.2 の xf_8uc3_2rgb プロジェクトを示す。
xf_8uc3_2rgb.cpp の
#define DEBUG
を生かすと XF_8UC3 と XF_8UC4 の最初の 10 個のデータを表示する。
C コードの合成の時は、コメントにする。
2021年01月14日 04:42 |
Vitis_Vision
| トラックバック:0
| コメント:0
ちょっとタイトルが長くなってしまったが、今まで、Vivado HLS で複数の関数を並列に実行させるのに、 hls::stream<ap_axiu<32,1,1,1> >& axis_out と言うように、hls::stream の ap_axis, ap_axiu データイプのポートを使用してきたが、これは、Vitis HLS 2020.2 では使用できないようだ。当然ながら、外部への AXI4-Stream 入出力としては使用できるが、内部のポートとしてはエラーになってしまう。
xf_8uc3_2rgb.cpp を示す。このソースコードは、XF_8UC3 を RGB のバイト・レーンにに変換して、hls ストリームとして出力する xf_8uc3_2axis() 関数と、hls ストリームを DMA Write する関数 axis2dmaw() を xf_8uc3_2rgb() 関数で連結してある。
// xf_8uc3_2rgb.cpp // 2021/01/12 by marsee // #include <ap_int.h> #include <hls_stream.h> #include <ap_axi_sdata.h> int xf_8uc3_2axis(ap_uint<32>* _src, int rows, int cols, hls::stream<ap_axiu<32,1,1,1> >& axis_out){ ap_uint<32> rgb[3]; const int rows_cols_limit = rows * cols; ap_axiu<32,1,1,1> pix; int po = 0; pix.last = 0; LOOP_x2s:for(int xy=0; xy<rows_cols_limit; xy++){ #pragma HLS PIPELINE II=1 #pragma HLS LOOP_TRIPCOUNT avg=480000 max=480000 min=480000 switch(xy%4){ case 0 : rgb[0] = _src[po++]; pix.data = (rgb[0] & 0xffffff) + 0xff000000; if(xy == 0) pix.user = 1; else pix.user = 0; axis_out << pix; break; case 1 : rgb[1] = _src[po++]; pix.data = ((rgb[1] & 0xffff)<<8) + ((rgb[0] & 0xff000000)>>24) + 0xff000000; axis_out << pix; break; case 2 : rgb[2] = _src[po++]; pix.data = ((rgb[2] & 0xff)<<16) + ((rgb[1] & 0xffff0000)>>16) + 0xff000000; axis_out << pix; break; default: // 3 pix.data = ((rgb[2] & 0xffffff00)>>8) + 0xff000000; axis_out << pix; break; } } return(0); } int axis2dmaw(hls::stream<ap_axiu<32,1,1,1> >& axis_in, int rows, int cols, ap_uint<32>* _dst){ const int rows_cols_limit = rows * cols; ap_axiu<32,1,1,1> pix; LOOP_a2dw:for(int xy=0; xy<rows_cols_limit; xy++){ #pragma HLS PIPELINE II=1 #pragma HLS LOOP_TRIPCOUNT avg=480000 max=480000 min=480000 axis_in >> pix; _dst[xy] = pix.data; } return(0); } int xf_8uc3_2rgb(ap_uint<32>* _src, int rows, int cols, ap_uint<32>* _dst){ #pragma HLS DATAFLOW #pragma HLS INTERFACE m_axi depth=480000 port=_dst offset=slave #pragma HLS INTERFACE s_axilite port=cols #pragma HLS INTERFACE s_axilite port=rows #pragma HLS INTERFACE s_axilite port=_src #pragma HLS INTERFACE m_axi depth=4800000 port=_src offset=slave #pragma HLS INTERFACE s_axilite port=return hls::stream<ap_axiu<32,1,1,1> > axis; xf_8uc3_2axis(_src, rows, cols, axis); axis2dmaw(axis, rows, cols, _dst); return(0); }
Vitis HLS 2020.2 で xf_8uc3_2rgb プロジェクトを作成して、ソースコードとして xf_8uc3_2rgb.cpp を登録して、C コードの合成を行うとエラーが発生した。
エラー内容を示す。
ERROR: [HLS 214-208] The ap_axis|ap_axiu|qdma_axis|hls::axis data types must only be used for AXI-Stream ports in the interface. 'axis_out' is not an AXI-Stream and/or is not a port in the interface (xf_8uc3_2rgb/xf_8uc3_2rgb.cpp:9:0) ERROR: [HLS 214-208] The ap_axis|ap_axiu|qdma_axis|hls::axis data types must only be used for AXI-Stream ports in the interface. 'axis_in' is not an AXI-Stream and/or is not a port in the interface (xf_8uc3_2rgb/xf_8uc3_2rgb.cpp:48:0)
Vivado HLS 2019.2 で xf_8uc3_2rgb プロジェクトを作成して、同じソースコードの C コードの合成をしたところ、問題なく合成できた。
やはり、Vitis HLS 2020.2 では、関数間の内部のポートとしては、 hls::stream<ap_axiu<32,1,1,1> > が使えなくなってしまったようだ。
それでは、Vitis HLS 2020.1 はどうなんだろう?ということで、同様にやってみたが、 C コードの合成は成功した。
ということで、 hls::stream<ap_axiu<32,1,1,1> > が関数内部のポートとして使えなくなったのは、 Vitis HLS 2020.2 からのようだ。
2021年01月13日 04:13 |
Vitis HLS
| トラックバック:0
| コメント:2
”
OpenCV Mat 形式での .data のデータフォーマットを検証する ”では画像ファイルを読み込んだデータを一旦 CV_8UC4 (BGRA)に変換してから、 array2axis() を呼び出すと 32 ビット幅のバイト・レーンに アルファ・チャネル、Red , Green 、Blue が並ぶことが確認できた。こうなると、自分の IP から使用しやすくなる。 medianblur も XF_8UC4 を使って実装してみよう。
まずは、 xf_median_blur_config.h の TYPE の定義を XF_8UC4 に変更した。
xf_median_blur_tb.cpp を変更した。これは全部のソースコードを貼っておく。
/* * Copyright 2019 Xilinx, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "common/xf_headers.hpp" #include "xf_median_blur_config.h" int main(int argc, char** argv) { if (argc != 2) { fprintf(stderr, "Usage: %s <INPUT IMAGE PATH 1>", argv[0]); return EXIT_FAILURE; } cv::Mat in_img, out_img, ocv_ref, diff, cnv_img, cnv_out_img; // Reading in the image: #if GRAY in_img = cv::imread(argv[1], 0); // reading in the gray image #else in_img = cv::imread(argv[1], 1); // reading in the color image cnv_img.create(in_img.rows, in_img.cols, CV_8UC4); cv::cvtColor(in_img, cnv_img, cv::COLOR_BGR2BGRA); #endif if (in_img.data == NULL) { fprintf(stderr, "ERROR: Cannot open image %s\n ", argv[1]); return EXIT_FAILURE; } // create memory for output image #if GRAY ocv_ref.create(in_img.rows, in_img.cols, CV_8UC1); out_img.create(in_img.rows, in_img.cols, CV_8UC1); // create memory for output image diff.create(in_img.rows, in_img.cols, CV_8UC1); #else ocv_ref.create(in_img.rows, in_img.cols, CV_8UC3); out_img.create(in_img.rows, in_img.cols, CV_8UC4); // create memory for output image cnv_out_img.create(in_img.rows, in_img.cols, CV_8UC3); diff.create(in_img.rows, in_img.cols, CV_8UC3); #endif // OpenCV reference: cv::medianBlur(in_img, ocv_ref, WINDOW_SIZE); // OpenCL section: #if GRAY size_t image_in_size_bytes = in_img.rows * in_img.cols * 1 * sizeof(unsigned char); #else size_t image_in_size_bytes = in_img.rows * in_img.cols * 3 * sizeof(unsigned char); #endif size_t image_out_size_bytes = image_in_size_bytes; // Call the top function median_blur_accel((ap_uint<PTR_WIDTH>*)cnv_img.data, cnv_img.rows, cnv_img.cols, (ap_uint<PTR_WIDTH>*)out_img.data); cv::cvtColor(out_img, cnv_out_img, cv::COLOR_BGRA2BGR); // Write down output images: cv::imwrite("hls_out.jpg", cnv_out_img); // kernel output cv::imwrite("ref_img.jpg", ocv_ref); // reference image absdiff(ocv_ref, cnv_out_img, diff); // Save the difference image for debugging purpose: cv::imwrite("error.png", diff); float err_per; xf::cv::analyzeDiff(diff, 10, err_per); return 0; }
xf_median_blur_accel.cpp は変更していない。
これで、 C シミュレーションを行ったところ、エラーになってしまった。
/media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/imgproc/xf_median_blur.hpp: In instantiation of ‘void xf::cv::xFMedianNxN(xf::cv::Mat<TYPE, ROWS, COLS, NPC>&, xf::cv::Mat<TYPE, ROWS, COLS, NPC>&, ap_uint<8>, uint16_t, uint16_t) [with int ROWS = 600; int COLS = 800; int PLANES = 4; int TYPE = 7; int NPC = 1; int WORDWIDTH = 0; int TC = 801; int WIN_SZ = 3; int WIN_SZ_SQ = 9; uint16_t = short unsigned int]’: /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/imgproc/xf_median_blur.hpp:462:56: required from ‘void xf::cv::medianBlur(xf::cv::Mat<TYPE, ROWS, COLS, NPC>&, xf::cv::Mat<TYPE, ROWS, COLS, NPC>&) [with int FILTER_SIZE = 3; int BORDER_TYPE = 1; int TYPE = 7; int ROWS = 600; int COLS = 800; int NPC = 1]’ ../../../xf_median_blur_accel.cpp:41:104: required from here /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/imgproc/xf_median_blur.hpp:363:22: エラー: no type named ‘uname’ in ‘struct PixelType<7>’ XF_PTUNAME(TYPE) OutputValues[XF_NPIXPERCYCLE(NPC)]; ^~~~~~~~~~~~ /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/imgproc/xf_median_blur.hpp:368:22: エラー: no type named ‘uname’ in ‘struct PixelType<7>’ XF_PTUNAME(TYPE) src_buf[WIN_SZ][XF_NPIXPERCYCLE(NPC) + (WIN_SZ - 1)]; ^~~~~~~ /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/imgproc/xf_median_blur.hpp:368:22: エラー: no type named ‘uname’ in ‘struct PixelType<7>’ /media/masaaki/Ubuntu_Disk/Xilinx_github/Vitis_Libraries/vision/L1/include/imgproc/xf_median_blur.hpp:363:22: エラー: no type named ‘uname’ in ‘struct PixelType<7>’ XF_PTUNAME(TYPE) OutputValues[XF_NPIXPERCYCLE(NPC)]; ^~~~~~~~~~~~ make: *** [obj/xf_median_blur_accel.o] Error 1 ERROR: [SIM 211-100] 'csim_design' failed: compilation error(s). INFO: [SIM 211-3] *************** CSIM finish *************** INFO: [HLS 200-111] Finished Command csim_design CPU user time: 4.12 seconds. CPU system time: 0.3 seconds. Elapsed time: 3.89 seconds; current allocated memory: 164.609 MB.
どうやら、 XF_8UC4 は対応していないようだ。とっても残念。。。
2021年01月12日 04:27 |
Vitis_Vision
| トラックバック:0
| コメント:0
Vitis Vision Library の examples では、OpenCV Mat 形式の .data を ap_uint<***> * でキャストして、ハードウェア化する関数に渡していた。そのフォーマットを検証してみよう。
ハードウェア化する関数に渡すDMA の 32 ビット幅のデータ形式については、”
Vitis Vision Library の AXI4 Master インターフェース版 medianblur をZYBO Z7-20 で使ってみる1(準備編) ”でやっていたのだが、その確認と、それに、ツィッターで @waka3_m さんに CV_8UC4 について教えていただいた。( @waka3_m さんには Mat のデータ形式についてもアドバイスいただいた。ありがとうございました。)
そのような理由から、Mat 形式の画像のピクセルを AXI4-Stream にする Vitis HLS 2020.2 の array2axi プロジェクトを作って検証してみよう。
array2axis プロジェクトは Mat 形式データを AXI4-Stream に変換するが、あくまで Mat 形式のデータを検証するためのものだ。ハードウェア化する関数にも printf() でデータフォーマットを書き出しているのだが、気にしないようにして欲しい。
まずは、 array2axis.h から貼っておく。
CONFIG_8UC3 と CONFIG_8UC4 の定義を切り替えるようになっている。
CONFIG_8UC3 が定義されている時は、画像ファイルを読み込んだデータを CV_8UC3 のまま array2axis() を呼び出す。
CONFIG_8UC4 が定義されている時は、画像ファイルを読み込んだデータを一旦 CV_8UC4 (BGRA)に変換してから、 array2axis() を呼び出す。
// array2axis.h // 2021/01/05 by marsee // #ifndef __ARRAY2AXIS_H__ #define __ARRAY2AXIS_H__ #define PICT_WIDTH 128 #define PICT_HEIGHT 128 #define PICT_LIMIT (PICT_WIDTH * PICT_HEIGHT) #define PICT_MAT_LIMIT (((float)PICT_LIMIT*3.0)/4.0) #define CONFIG_8UC3 //#define CONFIG_8UC4 #endif
array2axis.cpp を貼っておく。
// array2axis.cpp // 2021/01/05 by marsee // #include <ap_int.h> #include <hls_stream.h> #include <ap_axi_sdata.h> #include "array2axis.h" ap_uint<32> cutout_bit8(ap_uint<32> data, ap_uint<32> bottom_bit){ return((data>>bottom_bit) & 0xff); } int array2axis(ap_uint<32> *array_in, hls::stream<ap_axiu<32,1,1,1> >& axis_out){ #pragma HLS INTERFACE s_axilite port=return #pragma HLS INTERFACE axis port=axis_out register_mode=both register #pragma HLS INTERFACE s_axilite port=array_in #pragma HLS INTERFACE m_axi port=array_in offset=slave depth=480000 ap_uint<32> mat_array[3]; ap_axiu<32,1,1,1> mat_pix; int pict_mat_8UC3 = (int)(PICT_MAT_LIMIT+(float)0.7); // Round up #ifdef CONFIG_8UC4 LOOP_XY: for(int xy=0; xy<PICT_LIMIT; xy++){ #else LOOP_XY: for(int xy=0; xy<pict_mat_8UC3; xy++){ #endif unsigned int temp = array_in[xy]; printf("xy = %d , array_in[xy] = %x\n", xy, temp); mat_pix.data = (ap_uint<32>)temp; if(xy == 0) mat_pix.user = 1; else mat_pix.user = 0; mat_pix.last = 0; axis_out.write(mat_pix); } return(0); }
array2axis_tb.cpp を貼っておく。
// array2axis_tb.cpp // 2021/01/06 by marsee // // Refers to "Vitis_Libraries/vision/L1/examples/medianblur/xf_median_blur_tb.cpp" // https://github.com/Xilinx/Vitis_Libraries/blob/master/vision/L1/examples/medianblur/xf_median_blur_tb.cpp // #include <opencv2/opencv.hpp> #include <stdint.h> #include <ap_int.h> #include <hls_stream.h> #include <ap_axi_sdata.h> #include "array2axis.h" int array2axis(ap_uint<32> *array_in, hls::stream<ap_axiu<32,1,1,1> >& axis_out); int main(int argc, char** argv) { hls::stream<ap_axiu<32,1,1,1> > outs; hls::stream<ap_axiu<32,1,1,1> > outs_soft; ap_axiu<32,1,1,1> vals; ap_axiu<32,1,1,1> vals_soft; cv::Mat cnv_img; if (argc != 2) { fprintf(stderr, "Usage: Please input image files name"); return(1); } cv::Mat in_img = cv::imread(argv[1], 1); // reading in the color image #ifdef CONFIG_8UC4 cnv_img.create(in_img.rows, in_img.cols, CV_8UC4); cv::cvtColor(in_img, cnv_img, cv::COLOR_BGR2BGRA); array2axis((ap_uint<32>*)cnv_img.data, outs); #else array2axis((ap_uint<32>*)in_img.data, outs); #endif return(0); }
Vitis HLS 2020.2 の array2axis プロジェクトを示す。
Project メニューから Project Settings... を選択して、 Project Settings (array2axis) ダイアログを開いた。
Simulation をクリックする。
array2axis_tb.cpp の CFLAGS に -I/usr/local/include を指定した。フルパスで設定しても相対パスに直されるようだ。
Linker Flaos には
-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc
を指定した。
Input Argument には、”
Vitis Vision Library の AXI4 Master インターフェース版 medianblur をZYBO Z7-20 で使ってみる1(準備編) ”で作った
128x128_blue123.png
を指定した。
128x128_blue123.png は最初のピクセルの RGB の値を 1, 2, 3 にしてある。その次のピクセルの RGB の値は 4, 5, 6 と言うように順番に RGB の値を増やしている画像で、つまりどの RGB が現在転送されているかを一目瞭然で分かるようにした画像だ。
まずは、 array2axis.h で CONFIG_8UC3 を定義して C シミュレーションを行った。結果を示す。
出力された画像データのフォーマットは”
Vitis Vision Library の AXI4 Master インターフェース版 medianblur をZYBO Z7-20 で使ってみる1(準備編) ”と同じように見える。
xy = 0 , array_in[xy] = 6010203 xy = 1 , array_in[xy] = 8090405 xy = 2 , array_in[xy] = a0b0c07 xy = 3 , array_in[xy] = 120d0e0f xy = 4 , array_in[xy] = 14151011 xy = 5 , array_in[xy] = 16171813 xy = 6 , array_in[xy] = 1e191a1b xy = 7 , array_in[xy] = 20211c1d xy = 8 , array_in[xy] = 2223241f xy = 9 , array_in[xy] = 2a252627 xy = 10 , array_in[xy] = ff2829
次に、 array2axis.h で CONFIG_8UC4 を定義し、CONFIG_8UC4 をコメントアウトして、C シミュレーションを行った。結果を示す。
CV_8UC4 は 8 バイトが 4 個、つまり 1 ピクセルが 4 バイト = 32 ビットなので、 32 ビット幅と相性が良い。
xy = 0 , array_in[xy] = ff010203 xy = 1 , array_in[xy] = ff040506 xy = 2 , array_in[xy] = ff070809 xy = 3 , array_in[xy] = ff0a0b0c xy = 4 , array_in[xy] = ff0d0e0f xy = 5 , array_in[xy] = ff101112 xy = 6 , array_in[xy] = ff131415 xy = 7 , array_in[xy] = ff161718 xy = 8 , array_in[xy] = ff191a1b xy = 9 , array_in[xy] = ff1c1d1e xy = 10 , array_in[xy] = ff1f2021 xy = 11 , array_in[xy] = ff222324 xy = 12 , array_in[xy] = ff252627 xy = 13 , array_in[xy] = ff28292a
CV_8UC4 では、一番上のバイト・レーンにアルファ・チャネルが付くので、これを無視すれば、 AXI4 Master インターフェースのビットマップ・ディスプレイ・コントローラーで、そのまま DMA すれば画像を表示できそうだ。
2021年01月11日 04:57 |
OpenCV
| トラックバック:0
| コメント:0
”
ZYBO Z7-20 に xfOpenCV の median フィルタを実装する1(Vivado HLS 編) ”の続き。
以前、xfOpenCV のサンプルとして Vivado HLS 2019.2 で medianblur を実装したが、それを ZYBO Z7-20 に実装してみようということで、前回は、Vivado HLS 2019.2 で medianblur を再度 IP にした。今回は、その IP を使用して、Vivado 2019.2 でプロジェクトを作成して、ブロックデザインを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行う。 XSA ファイルを生成して、Vitis 2019.2 を立ち上げて、プラットフォームとアプリケーション・プロジェクトを作成し、ZYBO Z7-20 で実機検証を行う。
Vivado 2019.2 で median_filter_axis プロジェクトを作成した。
BMDispCaL , DMA2axis2st , axis2DMA2st , xf_median_blur(これは、Vivado HLS 2019.2 で作成した medianblur IP)をコピーした。
IP Catalog に先程の IP を登録した。
ブロックデザインを作成して、IP を追加して、配線を行った。
Address Editor を示す。
ブロックデザインの HDL Wrapper を作成した。
制約ファイルの median_filter_axis.xdc を作成した。
論理合成、インプリメンテーション、ビットストリームの生成を行った。結果を示す。
XSA ファイルをエクスポートした。
Vivado から Vitis 2019.2 を立ち上げて、プラットフォームとアプリケーション・プロジェクトを作成した。
アプリケーション・ソフトウェアを作成した。
画像のピクセルをヘッダファイルの配列に書いてある bmp_data.h と、その配列を読み込んで、RGB のデータに変換する median_filter_axis.c をプロジェクトに入れた。この RGB の配置については、”
xfOpenCV の cvMat2AXIvideoxf() の AXI4-Stream の RGB バイト割当 ”を参照した。
Ubuntu 18.04 LTS から gtkterm を起動して、設定を行った。
Vitis からアプリケーション・ソフトウェアを Run すると Zynq をコンフィギュレーションして、アプリケーションを起動した。
gtkterm にプロンプトが表示された。
デフォルトでは、ノイズの乗った画像が ZYBO Z7-20 の HDMI OUT から出力されている。
1 をキーボードから入力するとメディアン・フィルタ処理されて、ノイズが除かれた画像が表示された。
”
FPGAの部屋 プレゼンツ 「 Zynq&HLSハンズオンセミナー応用編」 ”では、前回の記事と今回の記事の内容を私と一緒に実装していきます。皆さんもよろしければご参加ください。オンラインなので、全国何処からでもご参加いただけます。
もし、Vivado HLS や Zynq に慣れていないとう方は”
FPGAの部屋 プレゼンツ 「 Zynq&HLSハンズオンセミナー基礎編」 ”からご参加ください。(ステマです。。。)
2021年01月10日 06:34 |
reVISION, xfOpenCV
| トラックバック:0
| コメント:0
Vitis HLS 2020.2 の Vitis Vision Library の medianblur をやっていたが、今の所、どうしても AXI4-Stream インターフェースにすることができなかった。また、Mat.data のアドレスを与える方法も、そのデータフォーマットがよく分からずにハードウェアすることができていない。(ツィッターで教えてもらったので、うまく行きそうだ。ありがとうございます。)
そこで、以前やってみた AXI4-Stream 版 xfOpenCV の medianblur を ZYBO Z7-20 に実装してみよう。
これは、筑波大学の Vivado HLS セミナでやっている一部でもあり、”
FPGAの部屋 プレゼンツ 「 Zynq&HLSハンズオンセミナー応用編」 ”で行う内容の一部でもある。ただし、HDLab では、 ZYBO Z7-10 で行う様になっているが、ZYBO Z7-20 でも同様に行うことができる。オンラインで行うので全国何処からでもご参加いただけます。もしよろしければ、”
FPGAの部屋 プレゼンツ 「 Zynq&HLSハンズオンセミナー応用編」 ”にご参加ください。(ステマです。)
”
Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる1 ”
”
Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる2 ”
”
Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる3 ”
の記事の xfOpenCV の medianblur を元にやってみよう。
すでに、 xfOpenCV の xf::AXIvideo2xfMat() による AXI4-Stream の RGB のバイト・フィールドは、”
xfOpenCV の cvMat2AXIvideoxf() の AXI4-Stream の RGB バイト割当 ”によって、分かっているので、そのAXI4-Stream の RGB フォーマットに合わせればよい。
Vivado HLS 2019.2 の xfOpenCV の medianblur プロジェクトを示す。
medianblur プロジェクトにノイズを拡散させた 800 x 600 ピクセルの test2.jpg 画像ファイルを追加した。
Solution メニューから Solution Settings... を選択して、 Clock Period を 10 ns に、Part Selection を Zybo Z7-20 (xc7z020clg400-1) に設定した。
Project メニューから Project Settings... を選択して、 Simulation を選択し、 Input Arguments を test2.jpg に変更した。
Vivado HLS 2019.2 の medianblur プロジェクトの Explorer で Test Bench を右クリックし右クリックメニューから Add Files... を選択して test2.jpg を加えた。
C シミュレーションを実行した。
medianblur/solution1/csim/build ディレクトリを示す。
hls.jpg が生成されている。
元画像ファイルの test2.jpg を示す。
ノイズが重畳されているのが分かると思う。
そして、この hls.jpg がハードウェアになる予定のメディアン・フィルタ処理した画像となる。ノイズが消えている。
C コードの合成結果を示す。これは以前と変化なしだ。
C/RTL 協調シミュレーションを行う。
Co-simulation Dialog でInput Arguments に test2.jpg を入力した。
結果を示す。
Latency は 488452 クロックだった。総ピクセル数は 480000 ピクセルなので、 488452 / 480000 ≒ 1.02 クロック/ピクセルだった。
Export RTL を行った。
最初は Timing met しなかったが、 Solution メニューから Solution Settings... を選択して、Synthesis Settings の Uncertainty を 3 ns に設定したら、Timing met した。
2021年01月09日 17:02 |
reVISION, xfOpenCV
| トラックバック:0
| コメント:0
”
GPS と 3軸加速度センサーを使ったシステム9(基板の作成) ”の続き。
前回は、3 種類の基板が届いたところまでだった。今回は、部品を実装して動作テストを行った。
まずは 3 軸加速度センサー基板を示す。
GPS 基板を示す。
ZYBO Z7-20 に接続されるメイン基板を示す。
ZYBO Z7-20 と接続したところだ。うまく勘合している。
3 軸加速度センサー基板 1 個と GPS 基板をメイン基板に LAN ケーブルで接続して行った動作テストは問題なかった。
今後は、 3 軸加速度センサー基板を 8 個作成して完全なシステムでの動作テストを行う。
2021年01月08日 05:01 |
FPGAを使用したシステム
| トラックバック:0
| コメント:0
”
GPS と 3軸加速度センサーを使ったシステム8(LAN ケーブルを 5m, 7m, 10m に伸ばした) ”の続き。
現在はなぜか? 20m の LAN ケーブルでも I2C の伝送ミスが無くなっている。
今回は、去年の 12 月半ばに KiCad で 3 種類の基板を設計した。
1. 3 軸加速度センサーを搭載する基板
2. GPS センサーを搭載する基板
3. ZYBO Z7-20 の PMOD に接続するコネクタを持ち、 3 軸加速度センサー基板、GPS センサー基板を LAN ケーブルで接続するメイン基板
FusionPCB に頼んだ 3 つの基板ができあがってきた。
LAN コネクタもピッタリハマった。。。良かった〜。
しかし、早速、PMOD からの電源と USB microB コネクタからの電源を切り替える設定ピンのシルクが反対になっているのを発見した。orz
基板の裏面を示す。
部品を実装してテストするのが楽しみだ。。。
2021年01月07日 04:47 |
FPGAを使用したシステム
| トラックバック:0
| コメント:0
”
Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる1 ”
”
Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる2 ”
”
Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる3 ”
この 3 つの記事でやってきた AXI4-Stream インターフェース版のメディアン・フィルタを自分の環境で使用したい。テストベンチでは cvMat2AXIvideoxf() で cv::Mat を AXI4-Stream に変換しているが、RGB の 8 ビットのバイトは 32 ビット幅でどのバイト・フィールドにあるのかを確かめる。
それを確かめるために、 im0.png を作成した。
im0.png は上 1/3 が赤、真ん中 1/3 が緑、下 1/3 が青の画像だ。これで、Vivado HLS 2019.2 で C/RTL 協調シミュレーションを行うと RGB のバイト位置が分かるはずだ。
”
Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる2 ”の medianblur プロジェクトで im0.png を使用して、 C/RTL 協調シミュレーションを行った。
C/RTL 協調シミュレーションの内の入力の AXI4-Stream 波形を示す。
これで、
24 ビット 〜 16 ビットが赤 15 ビット 〜 8 ビットが緑 7 ビット 〜 0 ビットが青
ということが分かった。
2021年01月05日 20:55 |
reVISION, xfOpenCV
| トラックバック:0
| コメント:0
Vitis Vision Library の AXI4 Master インターフェース版 medianblur をZYBO Z7-20 で実際に使ってみたい。
それで、
Vitis Vision Library の AXI4 Master インターフェース版 medianblur を使用する際に確かめておかなくてはならないことがある。
それは、カメラのピクセル・データを渡す際のバイトの配置のことだ。ピクセルの RGB ごとの位置がわからないとカメラからのデータを配置することができない。
ピクセルの RGB ごとの位置を検証するために特殊な画像を作成した。
それは、PNG画像の最初のピクセルの RGB の値を 1, 2, 3 に設定し、
次のピクセルの RGB の値を 4, 5, 6 に設定した。というように、順番に RGB の値を増やした画像だ。
その画像を、 Vitis HLS 2020.2 の medianblur プロジェクトで C/RTL 協調シミュレーションを行って、 img_in の RDATA で読まれるピクセルの順番を検証する。
img_in の RDATA で読まれるピクセルの順番をまとめた表を示す。
表によると、32 ビット幅の AXI4 Master には 4 バイトのデータが入るので、 1 ピクセルの RGB 値の 3 個とぴったり合うのは最小公倍数の 3 個ということになるようだ。
メモリに、このように入れれば良いとは思うのだが、変換する IP を作る必要があるかな?
2021年01月04日 05:03 |
Vitis_Vision
| トラックバック:0
| コメント:0
”
Xilinx 社の AXI IIC IP で ADXL355 を使用する ”で作った ADXL355 (3軸加速度センサー)の I2C の回路に”
Watchdog timer を Vitis HLS 2020.1 で実装する3(デバック修正) ”の WDTimer を実装する。
Vivado 2020.1 の acc_sensor プロジェクトを示す。
このプロジェクトに WDTimer IP を追加した。
WDTimer_0 の rst_out はインバータを通して、 rst_ps7_0_100M IP の aux_rest_in に接続されている。
WDTimer のタイムアウト時間は 5.24 ms だった。今回は、 300 Hz なので、 3.333 ms 毎に加速度データを取得しているので、その間隔でアプリケーション・ソフトウェアでAXI_GPIO 経由で rst_in に 1 を入れて WDTimer をリセットする。
Address Editor 画面を示す。
論理合成、インプリメンテーション、ビットストリームの生成を行った。
Project Summary を示す。
ハードウェアをエクスポートして XSA ファイルを作った。
Vitis 2020.1 を起動した。
すでにプラットフォームとアプリケーション・プロジェクトは作ってあるので、アップデートした。
ソフトウェアも、WDTimer をリセットするために AXI GPIO に 1 を書き込む部分を追加した。
今の所、 I2C が止まっていないので、よく分からない。結局、I2C の途中で止まっていると、ADXL355 をリセットできないので、ダメそうだ。 ADXL355 はリセット端子が無いので、電源をON, OFF できればよいのだが。。。
acc_sensor_test.c を貼っておく。
// acc_sensor_test.c // 2020/10/12 by marsee // #include <stdio.h> #include <stdint.h> #include <unistd.h> #include "xtime_l.h" #include "xparameters.h" #define TX_FIFO_EMPTY 0x80 #define RX_FIFO_EMPTY 0x40 #define BB 0x04 void acc_sensor_init(volatile uint32_t *axi_iic_ad){ axi_iic_ad[72] = 0x0F; // RX_FIFI_PIRQ axi_iic_ad[64] = 0x2; // Control Register (100h) reset tx fifo axi_iic_ad[64] = 0x1; // Control Register (100h) enable i2c } void idle_check(volatile uint32_t *axi_iic_ad){ int32_t status_reg; int32_t check_bit; do{ status_reg = axi_iic_ad[65]; // Status Register (104h)) check_bit = status_reg & (TX_FIFO_EMPTY | RX_FIFO_EMPTY | BB); }while(check_bit != (TX_FIFO_EMPTY | RX_FIFO_EMPTY)) ; } void acc_sensor_write(volatile uint32_t *axi_iic_ad, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){ idle_check(axi_iic_ad); axi_iic_ad[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo axi_iic_ad[66] = write_addr & 0xff; // address axi_iic_ad[66] = 0x200 | (write_data & 0xff); // data } uint32_t acc_sensor_read(volatile uint32_t *axi_iic_ad, uint32_t device_addr, uint32_t read_addr){ int32_t status_reg, rx_fifo_empty; idle_check(axi_iic_ad); axi_iic_ad[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo axi_iic_ad[66] = read_addr & 0xff; // address byte axi_iic_ad[66] = 0x100 | device_addr & 0xff; // Slave IIC Read Address, address is 0x108, i2c_tx_fifo, with repeat start axi_iic_ad[66] = 0x201; // 1 byte data, NACK condition do{ status_reg = axi_iic_ad[65]; rx_fifo_empty = status_reg & RX_FIFO_EMPTY; }while(rx_fifo_empty); // Wait untill not RX_FIFO_EMPTY(Status Register (104h)) int32_t read_data = axi_iic_ad[67] & 0xff; // Read Receive FIFO (10Ch) return(read_data); } int main(){ volatile uint32_t *axi_iic_ad; volatile uint32_t *axi_gpio0_ad, *axi_gpio1_ad; int32_t dataX, dataY, dataZ; int32_t read_data, data_ready; XTime cur_time; axi_iic_ad = (volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR; axi_gpio0_ad = (volatile uint32_t *)XPAR_AXI_GPIO_0_BASEADDR; axi_gpio1_ad = (volatile uint32_t *)XPAR_AXI_GPIO_1_BASEADDR; acc_sensor_init(axi_iic_ad); acc_sensor_write(axi_iic_ad, 0x3a, 0x2f, 0x52); // Reset axi_gpio1_ad[0] = 1; // reported reset usleep(1000); acc_sensor_write(axi_iic_ad, 0x3a, 0x2c, 0x82); // I2C speed is Hi speed, +-4g acc_sensor_write(axi_iic_ad, 0x3a, 0x1e, 0x00); // OFFSET_X_H acc_sensor_write(axi_iic_ad, 0x3a, 0x1f, 0x00); // OFFSET_X_L acc_sensor_write(axi_iic_ad, 0x3a, 0x20, 0x00); // OFFSET_Y_H acc_sensor_write(axi_iic_ad, 0x3a, 0x21, 0x00); // OFFSET_Y_L acc_sensor_write(axi_iic_ad, 0x3a, 0x22, 0x00); // OFFSET_Z_H acc_sensor_write(axi_iic_ad, 0x3a, 0x23, 0x00); // OFFSET_Z_L acc_sensor_write(axi_iic_ad, 0x3a, 0x2d, 0x00); // stanby clear do{ read_data = acc_sensor_read(axi_iic_ad, 0x3b, 0x04); data_ready = read_data & 0x01; }while(data_ready != 0x01); axi_gpio0_ad[2] = 1; // WDTimer enable //for(int i=0; i<10000; i++){ while(1){ dataX = acc_sensor_read(axi_iic_ad, 0x3b, 0x08) << 12; // XDATA3 dataX |= (acc_sensor_read(axi_iic_ad, 0x3b, 0x09) << 4); // XDATA2 dataX |= ((acc_sensor_read(axi_iic_ad, 0x3b, 0x0a) & 0xf0) >> 4); // XDATA1 if(dataX & 0x80000) // Is the 19th bit 1? dataX |= 0xfff00000; // sign extension dataY = acc_sensor_read(axi_iic_ad, 0x3b, 0x0b) << 12; // YDATA3 dataY |= (acc_sensor_read(axi_iic_ad, 0x3b, 0x0c) << 4); // YDATA2 dataY |= ((acc_sensor_read(axi_iic_ad, 0x3b, 0x0d) & 0xf0) >> 4); // YDATA1 if(dataY & 0x80000) // Is the 19th bit 1? dataY |= 0xfff00000; // sign extension dataZ = acc_sensor_read(axi_iic_ad, 0x3b, 0x0e) << 12; // ZDATA3 dataZ |= (acc_sensor_read(axi_iic_ad, 0x3b, 0x0f) << 4); // ZDATA2 dataZ |= ((acc_sensor_read(axi_iic_ad, 0x3b, 0x10) & 0xf0) >> 4); // ZDATA1 if(dataZ & 0x80000) // Is the 19th bit 1? dataZ |= 0xfff00000; // sign extension XTime_GetTime(&cur_time); //printf("time = %lf ms, datax = %x, dataY = %x, dataZ = %x\n", (double)((long long int)cur_time)/335000.0, (int)dataX, (int)dataY, (int)dataZ); printf("%lf,%x,%x,%x,%x\n", (double)((long long int)cur_time)/335000.0, (int)dataX, (int)dataY, (int)dataZ, axi_gpio1_ad[0]); axi_gpio0_ad[0] = 1; axi_gpio0_ad[0] = 0; axi_gpio1_ad[0] = 0; // usleep(2434); // for 400 kHz usleep(1581); // for 200 kHz } return(0); }
2021年01月03日 20:41 |
FPGAを使用したシステム
| トラックバック:0
| コメント:0
”
Vitis Vision Library で AXI4-Stream 入出力の medianblur を実装する1 ”で Vitis Vision Library で AXI4-Stream 入出力の medianblur を実装したのだが、C シミュレーションはエラーで実行できなかった。
それでは、 xfOpenCV を Vitis HLS 2020.2 では使えないのだろうか? ということでやってみた。
”
Vivado HLS 2019.2 で xfOpenCV のAXI4-Stream 版 medianblur をやってみる1 ”のコードをそのまま使用して、”
Vivado HLS 2019.2 で xfOpenCV の medianblur をやってみる1 ”の Vivado HLS の設定をそのまま使用するのだが、多少変更する必要がある。
Vitis HLS 2020.2 で xfopencv ディレクトリの下に medainblur プロジェクトを作成した。
”
Vitis Vision Library で AXI4-Stream 入出力の medianblur を実装する1 ”と同じファイルを持ってきて、Vitis HLS の Source に xf_median_blur.cpp を Test Bench に im0.jpg と xf_median_blur_tb.cpp を登録した。
Vitis HLS 2020.2 の Project メニューから Project Settings... を選択すると、Project Settings (medianblur) ダイアログが開く。
Project Settings (medianblur) ダイアログで、Simulation をクリックして、xf_median_blur_tb.cpp の CFLAGS に
-D__SDSVHLS__ -I/home/masaaki/xfopencv/include --std=c++0x -I/usr/local/include
を入力した。これは、Vitis HLS 2020.2 は OpenCV へのリンクが無いので、自分でインストールした OpenCV 3.4.9 の include へのパスを追加した。
Linker Flags に
-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc
を入力した。
Input Arguments に
im0.jpg
を設定した。
Project Settings (medianblur) ダイアログで、Synthesis をクリックして、
-D__SDSVHLS__ -I/home/masaaki/xfopencv/include --std=c++0x
を設定した。
これで準備が整った。
Project メニューから Run Simulation を選択して、 C シミュレーションをスタートしたが、エラーで終了した。
エラー内容を示す。
INFO: [SIM 2] *************** CSIM start *************** INFO: [SIM 4] CSIM will launch GCC as the compiler. Compiling ../../../xf_median_blur_tb.cpp in debug mode csim.mk:73: recipe for target 'obj/xf_median_blur_tb.o' failed In file included from ../../../../../../../../../home/masaaki/xfopencv/include/common/xf_axi_io.h:33:0, from ../../../../../../../../../home/masaaki/xfopencv/include/common/xf_infra.h:43, from ../../../xf_median_blur_tb.cpp:11: /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2020.2/include/utils/x_hls_utils.h:243:40: 警告: ‘hls_preserve’ 属性指示が無視されました [-Wattributes] __attribute__((hls_preserve)) T reg(T d) ^ In file included from ../../../xf_median_blur_tb.cpp:12:0: ../../../../../../../../../home/masaaki/xfopencv/include/common/xf_axi.h: In instantiation of ‘void cvMat2AXIvideoxf(cv::Mat&, hls::stream<ap_axiu<W, 1, 1, 1> >&) [with int NPC = 1; int W = 32]’: ../../../xf_median_blur_tb.cpp:63:38: required from here ../../../../../../../../../home/masaaki/xfopencv/include/common/xf_axi.h:144:18: エラー: conversion from ‘cv::Mat’ to non-scalar type ‘IplImage {aka _IplImage}’ requested IplImage img = cv_mat; ^~~~~~ ../../../../../../../../../home/masaaki/xfopencv/include/common/xf_axi.h: In instantiation of ‘void AXIvideo2cvMatxf(hls::stream<ap_axiu<W, 1, 1, 1> >&, cv::Mat&) [with int NPC = 1; int W = 32]’: ../../../xf_median_blur_tb.cpp:65:39: required from here ../../../../../../../../../home/masaaki/xfopencv/include/common/xf_axi.h:259:17: エラー: conversion from ‘cv::Mat’ to non-scalar type ‘IplImage {aka _IplImage}’ requested IplImage img = cv_mat; ^~~~~~ make: *** [obj/xf_median_blur_tb.o] Error 1 ERR: [SIM 100] 'csim_design' failed: compilation error(s). INFO: [SIM 3] *************** CSIM finish ***************
エラー内容は”conversion from ‘cv::Mat’ to non-scalar type ‘IplImage {aka _IplImage}’”ということだ。
これは、”
Vitis Vision Library で AXI4-Stream 入出力の medianblur を実装する1 ”と同じエラーだ。
2021年01月02日 05:36 |
reVISION, xfOpenCV
| トラックバック:0
| コメント:0
”
Vitis HLS 2020.2 で Vitis Vision Library を使用する4(medianblur 編) ”で Vitis Vision Library で medianblur をたぶん実装できたのだが、(たぶんというのはノイジーな画像を入力していないからだ)配列からDMA してフィルタをかけた、つまり、DMA Read ー フィルタ ー DMA Write ということだ。これを AXI4-Stream ー フィルタ ー AXI4-Stream の方式でフィルタしたい。こうした方がメモリ帯域を消費しなくてすむ。
xfOpenCV 版の AXI4-Stream 入出力 medianblur を持ってきて変更する。
xfOpenCV からの変更点としては、 Vitis_Libraries/vision/L1/include/common ディレクトリにあるファイルが .h でなく .hpp になっているということだ。
common ディレクトリからのインクルード文を .h から .hpp にすべて変更した。
C シミュレーションを行ったところ、エラーになってしまった。
INFO: [SIM 2] *************** CSIM start *************** INFO: [SIM 4] CSIM will launch GCC as the compiler. Compiling ../../../xf_median_blur_tb.cpp in debug mode csim.mk:73: recipe for target 'obj/xf_median_blur_tb.o' failed In file included from ../../../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_structs.hpp:27:0, from ../../../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_common.hpp:20, from ../../../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_sw_utils.hpp:20, from ../../../xf_headers.h:51, from ../../../xf_median_blur_tb.cpp:9: /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2020.2/include/ap_axi_sdata.h:97:40: 警告: variable templates only available with -std=c++14 or -std=gnu++14 template <typename T> constexpr size_t bitwidth = sizeof(T) * CHAR_BIT; ^~~~~~~~ /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2020.2/include/ap_axi_sdata.h:99:38: 警告: variable templates only available with -std=c++14 or -std=gnu++14 template <size_t W> constexpr size_t bitwidth<ap_int<W>> = W; ^~~~~~~~~~~~~~~~~~~ /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2020.2/include/ap_axi_sdata.h:100:38: 警告: variable templates only available with -std=c++14 or -std=gnu++14 template <size_t W> constexpr size_t bitwidth<ap_uint<W>> = W; ^~~~~~~~~~~~~~~~~~~~ /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2020.2/include/ap_axi_sdata.h:102:18: 警告: variable templates only available with -std=c++14 or -std=gnu++14 constexpr size_t bitwidth<ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>> = _AP_W; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2020.2/include/ap_axi_sdata.h:104:18: 警告: variable templates only available with -std=c++14 or -std=gnu++14 constexpr size_t bitwidth<ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>> = _AP_W; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2020.2/include/ap_axi_sdata.h:107:18: 警告: variable templates only available with -std=c++14 or -std=gnu++14 constexpr size_t bytewidth = (bitwidth<T> + CHAR_BIT - 1) / CHAR_BIT; ^~~~~~~~~ In file included from ../../../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_axi.hpp:23:0, from ../../../xf_median_blur.h:15, from ../../../xf_median_blur_tb.cpp:10: /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis_HLS/2020.2/include/utils/x_hls_utils.h:243:40: 警告: ‘hls_preserve’ 属性指示が無視されました [-Wattributes] __attribute__((hls_preserve)) T reg(T d) ^ In file included from ../../../xf_median_blur.h:15:0, from ../../../xf_median_blur_tb.cpp:10: ../../../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_axi.hpp: In instantiation of ‘void xf::cv::cvMat2AXIvideoxf(cv::Mat&, hls::stream<hls::axis<ap_uint<W>, 1ul, 1ul, 1ul> >&) [with int NPC = 1; int W = 32]’: ../../../xf_median_blur_tb.cpp:62:41: required from here ../../../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_axi.hpp:124:20: エラー: conversion from ‘cv::Mat’ to non-scalar type ‘IplImage {aka _IplImage}’ requested IplImage img = cv_mat; ^~~~~~ ../../../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_axi.hpp: In instantiation of ‘void xf::cv::AXIvideo2cvMatxf(hls::stream<hls::axis<ap_uint<W>, 1ul, 1ul, 1ul> >&, cv::Mat&) [with int NPC = 1; int W = 32]’: ../../../xf_median_blur_tb.cpp:64:42: required from here ../../../../../../../Xilinx_github/Vitis_Libraries/vision/L1/include/common/xf_axi.hpp:221:20: エラー: conversion from ‘cv::Mat’ to non-scalar type ‘IplImage {aka _IplImage}’ requested IplImage img = cv_mat; ^~~~~~ make: *** [obj/xf_median_blur_tb.o] Error 1 ERR: [SIM 100] 'csim_design' failed: compilation error(s). INFO: [SIM 3] *************** CSIM finish ***************
エラー内容は”conversion from ‘cv::Mat’ to non-scalar type ‘IplImage {aka _IplImage}’”ということだ。
エラー内容を検索すると、”
Vitis Library for Video-Stream Core, OpenCV Version? ”が見つかった。エラー内容は同じだが、解決策は提示されていない。
”
Vitis Vision cores AXI4 Stream buggy ”も検索できた。Vitis Vision Library で AXI4-Stream はバギーなのかも知れない?が、この例では、テストベンチでも xf::cv::Mat をインスタンスして、xf::cv::xfMat2AXIvideo() で AXI4-Stream に変換している。一度、この通りにやってみようと思う。
2021年01月01日 07:49 |
Vitis_Vision
| トラックバック:0
| コメント:0
新年あけましておめでとうございます。今年もよろしくお願いします。
昨年中は正の
FC2 Blog と副の
livedoor Blog 合わせて 557,536 アクセスいただきました。
そういえば、去年は
Tsukuba Mini Maker Faire 2020 に参加したんですね。遠い昔のようですが、コロナ騒ぎでギリギリの開催だったけど、でられてよかったです。今年もコロナが蔓延してきているようですが、ならないように気をつけたいと思います。
今年も”FPGAの部屋”のブログをどうぞ、よろしくお願いします。
2021年01月01日 04:39 |
日記
| トラックバック:0
| コメント:0