”
AXI4-Stream Data Width Converter のバイト・レーン変換を確認する3 ”の続き。
Pythonの画像処理ライブラリPillow(PIL)の Image.open でオープンした画像ファイルのフォーマットを確認するということで、前回は、blue.bmp、 green.bmp、 red.bmp を用意して、ZUBoard 1CG の PYNQ Linux にアップロードし、Jupter Notebook を書き換えて実行したところ、AXI4-Stream Data Width Converter で変換された 3 バイトの AXI4-Stream は上のバイトから RGB でなく BGR であることがわかった。前回の作業は、AXI4-Stream Data Width Converter は 2 個搭載されているが、その内の 3 バイト幅の AXI4-Stream から 4 バイト幅に変換する AXI4-Stream Data Width Converter の動作を見た。今回は、4 バイト幅の AXI4-Stream から 3 バイト幅に変換する AXI4-Stream Data Width Converter の動作を見た。
前回は、Vivado 2023.1 の i3filtes プロジェクトの i3filters ブロック・デザインの axis_dwidth_converter_1 の動作を観察した。
今回は、axis_dwidth_converter_0 の動作を観察する。
axis_dwidth_converter_0 は 4 バイト幅の AXI4-Stream から 3 バイト幅に変換する AXI4-Stream Data Width Converter だ。
最初に blue.bmp を読み込んだときの axis_dwidth_converter_0 の AXI4-Stream インターフェースを観察した。
slot0 が axis_dwidth_converter_0 の入力の 4 バイト幅の AXI4-Stream インターフェースで、slot 1 が 3 バイト幅の AXI4-Stream インターフェースだ。
3 バイト幅の AXI4-Stream インターフェースでは、0xfd までしか出ていないが、これは後ろのフィルタのスタート信号がまだ入っていなくてデータが流れていないためだと推測している。
次に green.bmp を読み込んだときの axis_dwidth_converter_0 の AXI4-Stream インターフェースを観察した。
最後に red.bmp を読み込んだときの axis_dwidth_converter_0 の AXI4-Stream インターフェースを観察した。
今までの AXI4-Stream Data Width Converter のバイト・レーン変換結果を表にまとめた。
見事に BGR だった。
AXI4-Stream Subset Converter IP を使用して、AXI4-Stream のバイト・レーンを入れ替えることにする。
2023年08月31日 04:50 |
IP
| トラックバック:0
| コメント:0
”
AXI4-Stream Data Width Converter のバイト・レーン変換を確認する2 ”の続き。
Pythonの画像処理ライブラリPillow(PIL)の Image.open でオープンした画像ファイルのフォーマットを確認するということで、前回は、PNG の画像ファイルを ZUBoard 1CG の PYNQ Linux にアップロードし、Jupter Notebook を書き換えて実行したところ、PNG の画像ファイルは 4 チャネルでエラーが出てしまった。今回は、blue.bmp、 green.bmp、 red.bmp を用意して、ZUBoard 1CG の PYNQ Linux にアップロードし、Jupter Notebook を書き換えて実行したところ、AXI4-Stream Data Width Converter で変換された 3 バイトの AXI4-Stream は上のバイトから RGB でなく BGR であることがわかった。
特殊な BMP ファイルを Pinta で作った。
青、緑、赤それぞれ、最初のピクセルから 4 個だけ、値を 0xff, 0xfe, 0xfd, 0xfc にした。他のピクセルは 0xff とした。
blue.bmp、 green.bmp、 red.bmp を作成した。
下の図は、red.bmp の 4 番めのピクセルを 0xfc (252) にしたところだ。
プライマリー色を赤 252 にして、鉛筆ツールで 4 番めのピクセルを書き換えた。
出来上がった blue.bmp、 green.bmp、 red.bmp の画像ファイルを ZUBoard 1CG の PYNQ Linux にアップロードした。
blue.bmp、 green.bmp、 red.bmp の画像ファイルを ~/jupyter_notebooks/examples/i3filters ディレクトリにコピーした。
cd sudo mv *.bmp ~/jupyter_notebooks/examples/i3filters/ ~/jupyter_notebooks/examples/i3filters ディレクトリに blue.bmp、 green.bmp、 red.bmp の画像ファイルがコピーされた。
blue.bmp を Image.open() でオープンするように i3filters.ipynb を書き換えた。
#image_path = "./test2.jpg" image_path = "./blue.bmp" #image_path = "./green.bmp" #image_path = "./red.bmp" original_image = Image.open(image_path)
ガウシアン・フィルタ、メディアン・フィルタ、ソーベル・フィルタはすべてフィルタなしでスルーするように設定した。
gaussian.register_map.row_size = height gaussian.register_map.col_size = width gaussian.register_map.function_r = 2 # ORG_IMGwAxiDma #gaussian.register_map.function_r = 3 # GAUSSIANwAxiDma median.register_map.row_size = height median.register_map.col_size = width median.register_map.function_r = 2 # ORG_IMGwAxiDma #median.register_map.function_r = 3 # MEDIANwAxiDma sobel.register_map.row_size = height sobel.register_map.col_size = width sobel.register_map.function_r = 2 # ORG_IMGwAxiDma #sobel.register_map.function_r = 3 # SOBELwAxiDma
i3filters.ipynb を実行して、bit ファイルをダウンロードする行を実行したら、Vivado で ILA ダッシュボードを表示する。
Vivado 2023.1 で Project Navigator の PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target をクリックして Auto Connect を選択すると、ILA ダッシュボードが表示された。
Trigger position in window を 512 から 100 に書き換えて、Run trigger for this ILA core の右向き三角ボタンをクリックして、トリガ待ちにした。
Jupyter Notebook で run_kernel() を実行すると、ILA ダッシュボードでトリガが掛かった。
axis_dwidth_converter_1 (AXI4-Stream を 3 バイトから 4 バイトに変換する IP)の波形を示す。
slot2 が axis_dwidth_converter_1の出力(4 バイト)、slot3 が axis_dwidth_converter_1 の入力(3 バイト)となっている。
blue.bmp のときの波形を示す。
green.bmp のときの波形を示す。
red.bmp のときの波形を示す。
見てお分かりの通りに、RGB だと思っていたのが、BGR だった。orz
2023年08月30日 05:05 |
IP
| トラックバック:0
| コメント:0
”
AXI4-Stream Data Width Converter のバイト・レーン変換を確認する1 ”の続き。
Pythonの画像処理ライブラリPillow(PIL)の Image.open でオープンした画像ファイルのフォーマットを確認するということで、前回は、blue.png、 green.png、 red.png の画像ファイルを作成した。今回は、PNG の画像ファイルを ZUBoard 1CG の PYNQ Linux にアップロードし、Jupter Notebook を書き換えて実行したところ、PNG の画像ファイルは 4 チャネルでエラーが出てしまった。
blue.png、 green.png、 red.png の画像ファイルを ZUBoard 1CG の PYNQ Linux にアップロードした。
blue.png、 green.png、 red.png の画像ファイルを ~/jupyter_notebooks/examples/i3filters ディレクトリにコピーした。
cd sudo mv blue.png ~/jupyter_notebooks/examples/i3filters sudo mv green.png ~/jupyter_notebooks/examples/i3filters sudo mv red.png ~/jupyter_notebooks/examples/i3filters ~/jupyter_notebooks/examples/i3filters ディレクトリに blue.png、 green.png、 red.png の画像ファイルがコピーされた。
blue.png を Image.open() でオープンするように i3filters.ipynb を書き換えた。
#image_path = "./test2.jpg" image_path = "./blue.png" #image_path = "./green.png" #image_path = "./red.png" original_image = Image.open(image_path)
ガウシアン・フィルタ、メディアン・フィルタ、ソーベル・フィルタはすべてフィルタなしでスルーするように設定した。
gaussian.register_map.row_size = height gaussian.register_map.col_size = width gaussian.register_map.function_r = 2 # ORG_IMGwAxiDma #gaussian.register_map.function_r = 3 # GAUSSIANwAxiDma
median.register_map.row_size = height median.register_map.col_size = width median.register_map.function_r = 2 # ORG_IMGwAxiDma #median.register_map.function_r = 3 # MEDIANwAxiDma
sobel.register_map.row_size = height sobel.register_map.col_size = width sobel.register_map.function_r = 2 # ORG_IMGwAxiDma #sobel.register_map.function_r = 3 # SOBELwAxiDma
これで、i3filters.ipynb を実行していったところ、DMA 用の共有物理メモリに読み込む行でエラーが発生した。
どうやら作成した png には、アルファ・チャネルがあって、RGB と alpha があるようだ。
そこでエラーが出ている。
2023年08月29日 04:17 |
IP
| トラックバック:0
| コメント:0
”
ZUBoard 1CG の PYNQ v3.0.1 で自作のガウシアン・フィルタ、メディアン・フィルタとソーベル・フィルタを動作させる3 ”でガウシアン・フィルタの動作を確認できたが、ファイルをロードした 4 バイトのデータは AXI4-Stream Data Width Converter で 4 バイトを 3 バイトに変換してガウシアン・フィルタに入力されている。
このバイト変換は”
PYNQ の画像ファイル・フォーマットを調査するために choose_RGB IP を Vitis HLS 2021.2 で作成する8 ”で解析して、4 バイトのデータが OpenCV の MAT 形式であることは確認してある。(MAT 形式のフォーマットについては、”
Vitis Vision Library の AXI4 Master インターフェース版 medianblur をZYBO Z7-20 で使ってみる1(準備編) ”を参照)
しかし、”
PYNQ の画像ファイル・フォーマットを調査するために choose_RGB IP を Vitis HLS 2021.2 で作成する8 ”では、4 バイトを 3 バイトに変換した後についての検証が足りなかったので、もう一度、”
ZUBoard 1CG の PYNQ v3.0.1 で自作のガウシアン・フィルタ、メディアン・フィルタとソーベル・フィルタを動作させる3 ”のハードウェアで検証してみよう。
まずは、色が単一の画像ファイルを作成する。
JPEG ファイルが無難だが、画像圧縮されていて、完全にはもとに戻らないので、PNG ファイルを作成してみる。
Ubuntu 22.04 の Pinta アプリケーションで、800 x 600 ピクセルの画像を新規作成する。
パレットからプライマリー色を右クリックすると”プライマリ色の選択”ダイアログが表示される。
赤を 0、緑を 0、青を 255 に変更する。これで青一色の画像になる。
プライマリー色をペイント缶で画像全体に適用すると青一色の画像になった。
これを blue.png に保存した。
同様に、”プライマリ色の選択”ダイアログで、赤を 255、緑を 0、青を 0 にして、ペイント缶で画像に適用した。
この画像を red.png として、保存した。
同様に、”プライマリ色の選択”ダイアログで、赤を 0、緑を 255、青を 0 にして、ペイント缶で画像に適用した。
この画像を green.png として、保存した。
今日は寝坊してしまったので、ここまでとする。
2023年08月28日 05:23 |
IP
| トラックバック:0
| コメント:0
”
ZUBoard 1CG の PYNQ v3.0.1 で自作のガウシアン・フィルタ、メディアン・フィルタとソーベル・フィルタを動作させる2 ”の続き。
前回は、i3filters ブロック・デザインの axis_dwidth_converter_0 と axis_dwidth_converter_1 に System ILA を追加して、論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。hwh ファイルと bit ファイルが生成された。今回は、生成されたビット・ファイルと hwh ファイルを ZUBoard 1CG 上の Jupyter Notebook にアップロードし、i3filters.ipynb ファイルを作成して、メディアン・フィルタとソーベル・フィルタの動作を確認したところ動作した。
ZUBoard 1CG の PYNQ Linux の jupyter_notebooks/examples ディレクトリに i3filters ディレクトリを作成した。
cd jupyter_notebooks/examples/ sudo mkdir i3filters 以下のファイルを FileZilla を使って、ZUBoard 1CG の PYNQ Linux のホーム・ディレクトリにアップロードした。
HDL/2023.1/zub1cg/i3filters/i3filters.runs/impl_1/i3filters_wrapper.bit
HDL/2023.1/zub1cg/i3filters/i3filters.gen/sources_1/bd/i3filters/hw_handoff/i3filters.hwh
Vitis_HLS/ZUBoard_1CG/2023.1/gaussian_axis_RGB24/test2.jpg
なお、test2.jpg は通常画像にノイズを拡散させた画像となっている。
ファイルをホーム・ディレクトリから jupyter_notebooks/examples/i3filters ディレクトリにコピーした。
cd sudo mv i3filters.hwh jupyter_notebooks/examples/i3filters mv i3filters_wrapper.bit jupyter_notebooks/examples/i3filters/i3filters.bit sudo mv test2.jpg jupyter_notebooks/examples/i3filters Jupyter Notebook 上で examples/i3filters ディレクトリにノートブックを作成した。
名前を Jupyter Notebook 上で i3filters に変更した。
i3filters.ipynb のコードを”
ZUBoard 1CG の PYNQ v3.0.1 で自作のメディアン・フィルタとソーベル・フィルタを動作させる3 ”から持ってきて、ガウシアン・フィルタ用のコードを追加した。
from PIL import Image import numpy as np import matplotlib.pyplot as plt %matplotlib inline from pynq import allocate, Overlay i3filters = Overlay("./i3filters.bit") dma = i3filters.axi_dma_0 median = i3filters.median_axis_RGB24_0 sobel = i3filters.sobel_axis_RGB24_0 gaussian = i3filters.gaussian_axis_RGB24_0 image_path = "./test2.jpg" original_image = Image.open(image_path) canvas = plt.gcf() size = canvas.get_size_inches() canvas.set_size_inches(size*2) width, height = original_image.size print("Image size: {}x{} pixels.".format(width, height)) plt.figure(figsize=(12, 10)); _ = plt.imshow(original_image) in_buffer = allocate(shape=(height, width, 3), dtype=np.uint8, cacheable=1) out_buffer = allocate(shape=(height, width, 3), dtype=np.uint8, cacheable=1) in_buffer[:] = np.array(original_image) def run_kernel(): dma.sendchannel.transfer(in_buffer) dma.recvchannel.transfer(out_buffer) gaussian.write(0x00,0x01) # start median.write(0x00,0x01) # start sobel.write(0x00,0x01) # start dma.sendchannel.wait() dma.recvchannel.wait() print(height) print(width) gaussian.register_map.row_size = height gaussian.register_map.col_size = width #gaussian.register_map.function_r = 2 # ORG_IMGwAxiDma gaussian.register_map.function_r = 3 # GAUSSIANwAxiDma median.register_map.row_size = height median.register_map.col_size = width median.register_map.function_r = 2 # ORG_IMGwAxiDma #median.register_map.function_r = 3 # MEDIANwAxiDma sobel.register_map.row_size = height sobel.register_map.col_size = width #sobel.register_map.function_r = 2 # ORG_IMGwAxiDma sobel.register_map.function_r = 3 # SOBELwAxiDma run_kernel() sobel_image = Image.fromarray(out_buffer) print("Image size: {}x{} pixels.".format(width, height)) plt.figure(figsize=(12, 10)); _ = plt.imshow(sobel_image) del in_buffer del out_buffer
i3filters.ipynb を実行した結果を示す。
ガウシアン・フィルタでノイズを除去しながらソーベル・フィルタでエッジを抽出する。
やはり、
メディアン・フィルタ程はノイズが除去できていない 。
2023年08月27日 04:51 |
ZUBoard
| トラックバック:0
| コメント:0
”
ZUBoard 1CG の PYNQ v3.0.1 で自作のガウシアン・フィルタ、メディアン・フィルタとソーベル・フィルタを動作させる1 ”の続き。
前回は、”
RGB 24 ビットの AXI4-Stream データ入出力対応のガウシアン・フィルタを Vitis HLS 2023.1 で作成する2 ”でガウシアン・フィルタ IP が生成できた。その gaussian_axis_RGB24 IP を”
ZUBoard 1CG の PYNQ v3.0.1 で自作のメディアン・フィルタとソーベル・フィルタを動作させる1 ”のソーベル・フィルタとメディアン・フィルタの回路に追加した。今回は、i3filters ブロック・デザインの axis_dwidth_converter_0 と axis_dwidth_converter_1 に System ILA を追加して、論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。hwh ファイルと bit ファイルが生成された。
Vivado 2023.1 の Source ウインドウで i3filters_i を右クリックし右クリックメニューから Create HDL Wrapper... を選択して、ブロック・デザインの HDL Wrapper を作成した。
axis_dwidth_converter_0 と axis_dwidth_converter_1 の S_AXIS と M_AXIS の配線を選択し、右クリックして、右クリックメニューから Debug を選択する。
Run Connection Automation をクリックし、Run Connection Automation ダイアログを表示させる。
デフォルトのままOK ボタンをクリックする。
axis_dwidth_converter_0 と axis_dwidth_converter_1 の S_AXIS と M_AXIS の配線に system_ila_0 が追加された。
PROJECT MNAGER から PROGRAM AND DEBUG -> Generate Bitstream をクリックし、論理合成、インプリメンテーション、ビットストリームの生成を行った。成功だ。
Project Summary を示す。
HDL/2023.1/zub1cg/i3filters/i3filters.gen/sources_1/bd/i3filters/hw_handoff ディレクトリに i3filters.hwh ファイルが生成された。
HDL/2023.1/zub1cg/i3filters/i3filters.runs/impl_1 ディレクトリに i3filters_wrapper.bit ファイルが生成された。
2023年08月26日 16:25 |
ZUBoard
| トラックバック:0
| コメント:0
”
RGB 24 ビットの AXI4-Stream データ入出力対応のガウシアン・フィルタを Vitis HLS 2023.1 で作成する2 ”でガウシアン・フィルタ IP が生成できた。その gaussian_axis_RGB24 IP を”
ZUBoard 1CG の PYNQ v3.0.1 で自作のメディアン・フィルタとソーベル・フィルタを動作させる1 ”のソーベル・フィルタとメディアン・フィルタの回路に追加した。
”
ZUBoard 1CG の PYNQ v3.0.1 で自作のメディアン・フィルタとソーベル・フィルタを動作させる1 ”の median_sobel ブロック・デザインを tcl ファイルに出力する。
Vivado 2023.1 の median_sobel プロジェクトで、File メニューから Export ->
Export Block Design... を選択する。
Export Block Design ダイアログが表示された。
OK ボタンをクリックする。
プロジェクトのディレクトリに
median_sobel.tcl ファイルが出力された。
この tcl ファイルを実行すると median_sobel ブロック・デザインが生成される。
ZUBoard 1CG 用の Vivado 2023.1 の i3filters プロジェクトを作成した。
i3filters プロジェクトのディレクトリに先程作成した median_sobel.tcl をコピーして、名前を i3filters.tcl に変更した。
i3filters.tcl を開いて”set design_name medain_sobel”から”set design_name i3filters”に変更した。
median_sobel プロジェクトのディレクトリから sobel_axis_RGB24 IP と median_axis_RGB24 IP のディレクトリを i3filters ディレクトリにコピーした。
gaussian_axis_RGB24 ディレクトリを新規作成した。
gaussian_axis_RGB24 ディレクトリに””
RGB 24 ビットの AXI4-Stream データ入出力対応のガウシアン・フィルタを Vitis HLS 2023.1 で作成する2 ”で作成した gaussian_axis_RGB24/solution1/impl/export.zip の内容をコピーした。
Vivado の Flow Navigator から IP Catalog をクリックした。
IP Catalog ウインドウが開く。
右クリックし、右クリックメニューから Add Repository を選択し、sobel_axis_RGB24 と median_axis_RGB24、gaussian_axis_RGB24 を選択して、IP を追加した。
Vivado 2023.1 の Tcl Console で次のコマンドを実行した。
cd /media/masaaki/Ubuntu_Disk/HDL/2023.1/zub1cg/i3filters/ source i3filters.tcl すると、メディアン・フィルタとソーベル・フィルタの回路が生成された。
+アイコンをクリックして、gaussian_axis_RGB24 IP を追加した。
配線を行って、回路が完成した。
i3filers ブロック・デザインを示す。
Address Editor 画面を示す。
2023年08月25日 04:22 |
ZUBoard
| トラックバック:0
| コメント:0
”
職場のパソコンと自宅のパソコンを Ubuntu 20.04 にアップグレードした ”でウインドウのキャプチャに問題が生じたので、職場と家のパソコンを Ubuntu 22.04 にアップグレードしたのですが、家のパソコンは Chrome を起動しながらアップグレードしたので、chrome のアイコンがランチャーにどうしても入らなくなってしまった。
家のパソコンを
sudo do-release-upgrade コマンドでアップグレードした。
そのときに Google Chrome ブラウザを見ながらUbuntu 22.04 にアップグレードしたのがまずかったのか? Ubuntu 22.04 を起動したら Google Chrome ブラウザのアイコンが無くなっていた。
Google Chrome をアンインストールして再度インストールしてもアイコンが表示されない。
諦めてコマンドで Google Chrome を起動することにした。
/opt/google/chrome/chrome Google Chrome のアイコンはランチャーに入っていないが、コマンドで起動すれば良さそうなので、これで良いことにする。どうせ、Google Chrome は常に起動しているし。。。
あー、とっても焦ってしまった。。。それに糊代の問題は解決できていない。
2023年08月24日 04:07 |
パソコン関連
| トラックバック:0
| コメント:0
職場のパソコンと自宅のパソコンは AMD/Xilinx 社のチュートリアルをやるために Ubuntu 18.04 にしていたのだが、サポート期間が今年の 5 月で切れているということで、Ubuntu 20.04 にアップグレードした。
どうもアップデートが Chrome のアップデートしか無いな。。。と思っていたら、Ubuntu 18.04 のサポート期間が今年の 5 月で切れていたようだ。。。orz
ということで、遅ればせながら、職場のパソコンと自宅のパソコンを Ubuntu 20.04 にアップグレードした。こちらは、2025 年までサポートされるようなので、またサポート期間が終了したらアップグレードしよう。
ところで、Ubuntu 20.04 でブログを書くため Vivado などの画面をキャプチャするのだが、CRTL-ALT-Print Screen キーやスクリーンショット・アプリでウインドウを画面キャプチャした時に余計な糊代?が入ってしまう。
この糊代?が邪魔でいちいち範囲指定して切り取っている。
Ubuntu 18.04 に比べるとブログを書くのがひと手間増えてしまったが、対応策は無いものなんだろうか?
Ubuntu 22.04 にアップグレードすると直るのだろうか?
何か対応策をご存知でしたら、コメント欄で教えください。よろしくお願いいたします。
2023年08月23日 04:29 |
パソコン関連
| トラックバック:0
| コメント:0
”
FPGAの部屋のまとめ サイト ”を更新しました。
8月22日までの記事をまとめました。
2023年08月22日 05:20 |
その他のFPGAの話題
| トラックバック:0
| コメント:0
”
RGB 24 ビットの AXI4-Stream データ入出力対応のガウシアン・フィルタを Vitis HLS 2023.1 で作成する1 ”の続き。
RGB 24 ビットの AXI4-Stream データ入出力対応のソーベル・フィルタを Vitis HLS 2023.1 で作成するということで、前回は、ソースコードとテストベンチコードを貼って、Vitis HLS 2023.1 で gaussian_axis_RGB24 プロジェクトを作成した。今回は、gaussian_axis_RGB24 プロジェクトで、C シミュレーション、C コードの合成、C/RTL 協調シミュレーション、Export RTL、Implementation を行った。
C シミュレーションを行った。結果を示す。
gaussian_axis_RGB24/solution1/csim/build ディレクトリを示す。
gaussian.jpg と org.jpg が生成されている。
org.jpg は gaussian_axis_RGB24 の col_size 変数に ORG_IMGwAxiDma を指定した時の出力となる。つまり元画像と同じ画像ファイルであるはずだ。
org.jpg を示す。ノイズが拡散されているのが分かると思う。
ノイズが拡散された元画像に 3 x 3 のガウシアン・フィルタをかけた画像が gaussian.jpg となる。
gaussian.jpg を示す。拡散されたノイズが
メディアン・フィルタ ほどではないがある程度取れて、綺麗な画像になっていることが分かる。
C コードの合成を行った。結果を示す。
gaussian_axis_RGB24_Pipeline_LOOP_Y_LOOP_X の LOOP_Y_LOOP_X の Interval が 1 クロックとなっていて、メディアン・フィルタの出力が 1 クロック毎に 1 出力がでるようだ。問題無さそうだ。
C/RTL 協調シミュレーションを行った。結果を示す。
Avg II が 480057 クロックだった。画像サイズは 800 x 600 = 480000 ピクセルなので、ほぼ 1 ピクセル / クロックとなっているようだ。
C/RTL 協調シミュレーションの波形を示す。
全体波形を示す。
outs_TVALID もほぼ 1 でスループットが高いことが分かる。
最初の波形を拡大する。
ins_TREADY を見ると、最初はディアサートされている期間があることが分かるが、それが過ぎたら、1 のままになっている。
Export RTL を行った。
Implementation を行って、Vivado で実装した時の性能を確認した。
結果を示す。
CP achieved post-implementaion は 4.957 ns で動作周波数の 10 ns よりも小さく、2 倍のクロックで動作しそうだ。
ガウシアン・フィルタの演算は 2 の n 乗の計算で、演算器が楽に組めるのだと思う。
2023年08月20日 04:37 |
ZUBoard
| トラックバック:0
| コメント:0
RGB 24 ビットの AXI4-Stream データ入出力対応のソーベル・フィルタを Vitis HLS 2023.1 で作成した。
2023/09/21: 修正: 出力のカラーが RBG になっていたので、RGB に修正した。 最初にヘッダ・ファイルとソースコードを示す。
ヘッダ・ファイルの gaussian_axis_RGB24.h を示す。
// gaussian_axis_RGB24.h // 2023/08/18 by marsee // #ifndef __GAUSSIAN_FILTER_AXIS_RGB24_H__ #define __GAUSSIAN_FILTER_AXIS_RGB24_H__ #define HORIZONTAL 0 #define VERTICAL 1 #define ORG_IMGwAxiVdma 0 #define GAUSSIANwAxiVdma 1 #define ORG_IMGwAxiDma 2 #define GAUSSIANwAxiDma 3 #endif
ソースコードの gaussian_axis_RGB24.cpp を示す。
// median_axis_RGB24.cpp // 2023/08/18 by marsee // #include <stdint.h> #include <ap_int.h> #include <hls_stream.h> #include <ap_axi_sdata.h> #include "gaussian_axis_RGB24.h" constexpr int size = 3; void gaussian_fil(ap_int<32> (&pix_mat)[size][size], ap_uint<24> &result); ap_int<32> gaussian_fil_calc(ap_int<32> *pixd); ap_int<32> separate_rgb(ap_int<32> rgb, ap_int<32> &r, ap_int<32> &g, ap_int<32> &b); int gaussian_axis_RGB24(hls::stream<ap_axiu<24,1,1,1> >& ins, hls::stream<ap_axiu<24,1,1,1> >& outs, int32_t function, int32_t row_size, int32_t col_size){ #pragma HLS INTERFACE mode=s_axilite port=col_size #pragma HLS INTERFACE mode=s_axilite port=row_size #pragma HLS INTERFACE mode=s_axilite port=function #pragma HLS INTERFACE mode=axis register_mode=both port=outs register #pragma HLS INTERFACE mode=axis register_mode=both port=ins register #pragma HLS INTERFACE mode=s_axilite port=return ap_axiu<24,1,1,1> pix; ap_axiu<24,1,1,1> gaussian; ap_uint<24> val; ap_int<32> line_buf[2][1920]; #pragma HLS array_partition variable=line_buf block factor=2 dim=1 ap_int<32> pix_mat[size][size]; #pragma HLS array_partition variable=pix_mat complete LOOP_WAIT_USER : do { // user が 1になった時にフレームがスタートする #pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1 ins >> pix; if(function==ORG_IMGwAxiDma || function==GAUSSIANwAxiDma) break; } while(pix.user == 0); LOOP_Y: for(int y=0; y<row_size; y++){ #pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=48 LOOP_X: for(int x=0; x<col_size; x++){ #pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=64 #pragma HLS PIPELINE II=1 if (!(x==0 && y==0)) // 最初の入力はすでに入力されている ins >> pix; // AXI4-Stream からの入力 LOOP_PIX_MAT_K: for(int k=0; k<3; k++){ LOOP_PIX_MAT_M: for(int m=0; m<2; m++){ pix_mat[k][m] = pix_mat[k][m+1]; } } pix_mat[0][2] = line_buf[0][x]; pix_mat[1][2] = line_buf[1][x]; ap_int<32> y_val = pix.data; pix_mat[2][2] = y_val; line_buf[0][x] = line_buf[1][x]; // 行の入れ替え line_buf[1][x] = y_val; gaussian_fil(pix_mat, val); gaussian.data = val; if(x<2 || y<2) gaussian.data = 0; if(function==ORG_IMGwAxiVdma || function == GAUSSIANwAxiVdma){ if(x==0 && y==0) // 最初のピクセル gaussian.user = 1; else gaussian.user = 0; if(x == (col_size-1)) // 行の最後 gaussian.last = 1; else gaussian.last = 0; }else{ gaussian.user = 0; gaussian.last = pix.last; } gaussian.keep = 0x7; gaussian.strb = 0x7; if(function==GAUSSIANwAxiVdma || function==GAUSSIANwAxiDma) outs << gaussian; else outs << pix; } } return(0); } // gaussian filter // // x0y0 x1y0 x2y0 1/16 2/16 1/16 // x0y1 x1y1 x2y1 2/16 4/16 2/16 // x0y2 x1y2 x2y2 1/16 2/16 1/16 // void gaussian_fil(ap_int<32> (&pix_mat)[size][size], ap_uint<24> &result){ ap_int<32> pix_1d_r[9], pix_1d_b[9], pix_1d_g[9]; ap_int<32> y_r, y_b, y_g, y; for(int i=0; i<9; i++){ separate_rgb(pix_mat[i/3][i%3], pix_1d_r[i], pix_1d_g[i], pix_1d_b[i]); } y_r = gaussian_fil_calc(pix_1d_r); y_b = gaussian_fil_calc(pix_1d_b); y_g = gaussian_fil_calc(pix_1d_g); result = (y_r << 16) + (y_g << 8) + y_b; } // gaussian_fil_calc ap_int<32> gaussian_fil_calc(ap_int<32> *pixd){ ap_int<32> y; y = pixd[0] + 2 * pixd[1] + pixd[2] + 2 * pixd[3] + 4 * pixd[4] + 2 * pixd[5] + pixd[6] + 2 * pixd[7] + pixd[8]; y = y / 16; if(y<0) y = -y; //y = 0; else if(y>255) // 8 bits y = 255; return(y); } // separate_rgb // RGBを分離する // RBGのフォーマットは、{R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits // ap_int<32> separate_rgb(ap_int<32> rbg, ap_int<32> &r, ap_int<32> &g, ap_int<32> &b){ b = rbg & 0xff; g = (rbg>>8) & 0xff; r = (rbg>>16) & 0xff; return(0); }
テストベンチの gaussian_axis_RGB24_tb.cpp を示す。
// gaussian_axis_RGB24_tb.cpp // 2023/08/18 by marsee // GAUSSIANwXilinxVideoStandard を define すると axi_vdma 用となり、コメントアウトすると axi_dma 用になる // #include <stdio.h> #include <stdint.h> #include <ap_int.h> #include <hls_stream.h> #include <ap_axi_sdata.h> #include "opencv2/opencv.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgcodecs/imgcodecs.hpp" #include "gaussian_axis_RGB24.h" //#define GAUSSIANwXilinxVideoStandard constexpr int size = 3; int gaussian_axis_RGB24(hls::stream<ap_axiu<24,1,1,1> >& ins, hls::stream<ap_axiu<24,1,1,1> >& outs, int32_t function, int32_t row_size, int32_t col_size); int gaussian_axis_RGB24_soft(hls::stream<ap_axiu<24,1,1,1> >& ins, hls::stream<ap_axiu<24,1,1,1> >& outs, int32_t function, int32_t row_size, int32_t col_size); void gaussian_fil_soft(ap_int<32> (&pix_mat)[size][size], ap_uint<24> &result); ap_int<32> gaussian_fil_calc_soft(ap_int<32> *pixd); ap_int<32> separate_rgb_soft(ap_int<32> rgb, ap_int<32> &r, ap_int<32> &g, ap_int<32> &b); const char INPUT_JPG_FILE[] = "test2.jpg"; const char OUTPUT_JPG_FILE[] = "gaussian.jpg"; const char ORG_OUT_JPG_FILE[] = "org.jpg"; int main(){ hls::stream<ap_axiu<24,1,1,1> > ins, ins2; hls::stream<ap_axiu<24,1,1,1> > ins_soft; hls::stream<ap_axiu<24,1,1,1> > outs, outs2; hls::stream<ap_axiu<24,1,1,1> > outs_soft; ap_axiu<24,1,1,1> pix; ap_axiu<24,1,1,1> vals, vals_soft; // JPG ファイルをMat に読み込む cv::Mat img = cv::imread(INPUT_JPG_FILE); // ピクセルを入れる領域の確保 std::vector<int32_t> rd_bmp(sizeof(int32_t)*img.cols*img.rows); std::vector<int32_t> hw_gaussian(sizeof(int32_t)*(img.cols)*(img.rows)); std::vector<int32_t> sw_gaussian(sizeof(int32_t)*(img.cols)*(img.rows)); // rd_bmp にJPGのピクセルを代入 cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img); for (int y=0; y<img.rows; y++){ for (int x=0; x<img.cols; x++){ cv::Vec3b pixel; pixel = dst_vec3b(y,x); rd_bmp[y*img.cols+x] = (pixel[0] & 0xff) | ((pixel[1] & 0xff)<<8) | ((pixel[2] & 0xff)<<16); // RGB 8 bits // blue - pixel[0]; green - pixel[1]; red - pixel[2]; } } #ifdef GAUSSIANwXilinxVideoStandard // ins に入力データを用意する for(int i=0; i<5; i++){ // dummy data pix.user = 0; pix.data = i; pix.last = 0; pix.user = 0; pix.keep = 0x7; pix.strb = 0x7; ins << pix; } #endif for(int j=0; j < img.rows; j++){ for(int i=0; i < img.cols; i++){ pix.data = (int32_t)rd_bmp[(j*img.cols)+i]; #ifdef GAUSSIANwXilinxVideoStandard if (j==0 && i==0) // 最初のデータの時に TUSER を 1 にする pix.user = 1; else pix.user = 0; if (i == img.cols-1) // 行の最後でTLASTをアサートする pix.last = 1; else pix.last = 0; #else if(j==img.rows-1 && i==img.cols-1) pix.last = 1; else pix.last = 0; pix.user = 0; #endif pix.keep = 0x7; pix.strb = 0x7; ins << pix; ins2 << pix; ins_soft << pix; } } #ifdef GAUSSIANwXilinxVideoStandard gaussian_axis_RGB24(ins, outs, GAUSSIANwAxiVdma, img.rows, img.cols); // ハードウェアのメディアンフィルタ gaussian_axis_RGB24_soft(ins_soft, outs_soft, GAUSSIANwAxiVdma, img.rows, img.cols); // ソフトウェアのメディアンフィルタ #else gaussian_axis_RGB24(ins, outs, GAUSSIANwAxiDma, img.rows, img.cols); // ハードウェアのメディアンフィルタ gaussian_axis_RGB24_soft(ins_soft, outs_soft, GAUSSIANwAxiDma, img.rows, img.cols); // ソフトウェアのメディアンフィルタ #endif // ハードウェアとソフトウェアのメディアンフィルタの値のチェック for (int y=0; y<img.rows; y++){ // 結果の画像サイズはx-2, y-2 for (int x=0; x<img.cols; x++){ outs >> vals; outs_soft >> vals_soft; ap_uint<32> val = vals.data; hw_gaussian[y*img.cols+x] = (int32_t)val; if (val != vals_soft.data){ printf("ERROR HW and SW results mismatch x = %ld, y = %ld, HW = %x, SW = %x\n", x, y, val, vals_soft.data); return(1); } } } printf("Success HW and SW results match\n"); const int gaussian_row = img.rows; const int gaussian_cols = img.cols; cv::Mat wbmpf(gaussian_row, gaussian_cols, CV_8UC3); // wbmpf にgaussian フィルタ処理後の画像を入力 cv::Mat_<cv::Vec3b> sob_vec3b = cv::Mat_<cv::Vec3b>(wbmpf); for (int y=0; y<wbmpf.rows; y++){ for (int x=0; x<wbmpf.cols; x++){ cv::Vec3b pixel; pixel = sob_vec3b(y,x); int32_t rbg = hw_gaussian[y*wbmpf.cols+x]; pixel[0] = ((rbg >> 8) & 0xff); // blue pixel[1] = (rbg & 0xff); // green pixel[2] = ((rbg >> 16) & 0xff); // red sob_vec3b(y,x) = pixel; } } // ハードウェアのメディアンフィルタの結果を jpg ファイルへ出力する cv::imwrite(OUTPUT_JPG_FILE, wbmpf); #ifdef GAUSSIANwXilinxVideoStandard gaussian_axis_RGB24(ins2, outs2, ORG_IMGwAxiVdma, img.rows, img.cols); // ハードウェアのメディアンフィルタ #else gaussian_axis_RGB24(ins2, outs2, ORG_IMGwAxiDma, img.rows, img.cols); // ハードウェアのメディアンフィルタ #endif cv::Mat wbmpf2(gaussian_row, gaussian_cols, CV_8UC3); // wbmpf2 に元画像を入力 sob_vec3b = cv::Mat_<cv::Vec3b>(wbmpf2); for (int y=0; y<wbmpf.rows; y++){ for (int x=0; x<wbmpf.cols; x++){ cv::Vec3b pixel; pixel = sob_vec3b(y,x); outs2 >> vals; int32_t val = vals.data; pixel[0] = (val & 0xff); // blue pixel[1] = ((val >> 8) & 0xff); // green pixel[2] = ((val >> 16) & 0xff); // red sob_vec3b(y,x) = pixel; } } // 元画像を jpg ファイルへ出力する cv::imwrite(ORG_OUT_JPG_FILE, wbmpf2); return(0); } int gaussian_axis_RGB24_soft(hls::stream<ap_axiu<24,1,1,1> >& ins, hls::stream<ap_axiu<24,1,1,1> >& outs, int32_t function, int32_t row_size, int32_t col_size){ ap_axiu<24,1,1,1> pix; ap_axiu<24,1,1,1> gaussian; ap_uint<24> val; ap_int<32> line_buf[2][1920]; ap_int<32> pix_mat[size][size]; LOOP_WAIT_USER : do { // user が 1になった時にフレームがスタートする ins >> pix; if(function==ORG_IMGwAxiDma || function==GAUSSIANwAxiDma) break; } while(pix.user == 0); for(int y=0; y<row_size; y++){ for(int x=0; x<col_size; x++){ if (!(x==0 && y==0)) // 最初の入力はすでに入力されている ins >> pix; // AXI4-Stream からの入力 LOOP_PIX_MAT_K: for(int k=0; k<3; k++){ LOOP_PIX_MAT_M: for(int m=0; m<2; m++){ pix_mat[k][m] = pix_mat[k][m+1]; } } pix_mat[0][2] = line_buf[0][x]; pix_mat[1][2] = line_buf[1][x]; ap_int<32> y_val = pix.data; pix_mat[2][2] = y_val; line_buf[0][x] = line_buf[1][x]; // 行の入れ替え line_buf[1][x] = y_val; gaussian_fil_soft(pix_mat, val); gaussian.data = val; if(x<2 || y<2) gaussian.data = 0; if(function==ORG_IMGwAxiVdma || function == GAUSSIANwAxiVdma){ if(x==0 && y==0) // 最初のピクセル gaussian.user = 1; else gaussian.user = 0; if(x == (col_size-1)) // 行の最後 gaussian.last = 1; else gaussian.last = 0; }else{ gaussian.user = 0; gaussian.last = pix.last; } gaussian.keep = 0x7; gaussian.strb = 0x7; if(function==GAUSSIANwAxiVdma || function==GAUSSIANwAxiDma) outs << gaussian; else outs << pix; } } return(0); } // gaussian filter // // x0y0 x1y0 x2y0 1/16 2/16 1/16 // x0y1 x1y1 x2y1 2/16 4/16 2/16 // x0y2 x1y2 x2y2 1/16 2/16 1/16 // void gaussian_fil_soft(ap_int<32> (&pix_mat)[size][size], ap_uint<24> &result){ ap_int<32> pix_1d_r[9], pix_1d_g[9], pix_1d_b[9]; ap_int<32> y_r, y_b, y_g, y; for(int i=0; i<9; i++){ separate_rgb_soft(pix_mat[i/3][i%3], pix_1d_r[i], pix_1d_g[i], pix_1d_b[i]); } y_r = gaussian_fil_calc_soft(pix_1d_r); y_b = gaussian_fil_calc_soft(pix_1d_b); y_g = gaussian_fil_calc_soft(pix_1d_g); result = (y_r << 16) + (y_g << 8) + y_b; } // gaussian_fil_calc ap_int<32> gaussian_fil_calc_soft(ap_int<32> *pixd){ ap_int<32> y; y = pixd[0] + 2 * pixd[1] + pixd[2] + 2 * pixd[3] + 4 * pixd[4] + 2 * pixd[5] + pixd[6] + 2 * pixd[7] + pixd[8]; y = y / 16; if(y<0) y = -y; //y = 0; else if(y>255) // 8 bits y = 255; return(y); } // separate_rgb // RGBを分離する // RBGのフォーマットは、{R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits // ap_int<32> separate_rgb_soft(ap_int<32> rbg, ap_int<32> &r, ap_int<32> &g, ap_int<32> &b){ b = rbg & 0xff; g = (rbg>>8) & 0xff; r = (rbg>>16) & 0xff; return(0); }
Vitis HLS 2023.1 で gaussian_axis_RGB24 プロジェクトを作成した。このプロジェクトは ZUBoard 1CG 用だ。
今回のテストベンチ・コードでは OpenCV ライブラリを使用している。
Vitis HLS 2023.1 には内蔵された OpenCV は無いので、別にインストールした OpenCV を指定する。
Vitis HLS の Project メニューから Project Settings... を選択して、Project Settings ダイアログを開いた。
Simulation タブを開いて、sobel_axis_RGB24_tb.cpp の CFLAGS に
-I/usr/local/include
を設定した。
Linker Flags に
-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc
を設定した。
更に、 Synthesis をクリックして、 Top Function に gaussian_axis_RGB24 を指定した。
2023年08月19日 04:00 |
ZUBoard
| トラックバック:0
| コメント:0
”
AVNET からダウンロードした BSP を使って、Petalinux プロジェクトを作成して、xmutil をやってみたがやはりエラーだった ”で Ver. 2022.2 の BSP をダウンロードして、Petalinux 2022.2 でやってみたが、エラーだった。今回は、Ver. 2022.1 の BSP をダウンロードして、Petalinux 2022.1 でやってみたが、エラーだった。
Ver. 2022.2 の BSP を AVNET のサイトからダウンロードし、”
AVNET からダウンロードした BSP を使って、Petalinux プロジェクトを作成して、xmutil をやってみたがやはりエラーだった ”の手順で構築していった。
できあがった rootfs.wic を balenaEtcher で MicroSD カードに書き込んだ。
書き込んだ MicroSD カードの /home/petalinux 上に binary_container_1.xclbin, pl.dtbo, pl.dtbi, shell.json, zub1cg_sbc_vadd をコピーした。
ZUBoard 1CG で Petalinux 2022.2 を起動した。
ホーム・ディレクトリに examples/zub1cg_sbc_vadd ディレクトリを作成した。
cd mkdir examples cd examples mkdir zub1cg_sbc_vadd cd zub1cg_sbc_vadd FileZilla を起動して、ZUBoard 1CG の Petalinux 2022.2 へ SFTP で vadd_file_transfer ディレクトリのファイルを転送した。
/lib/firmware/xilinx/zub1cg_sbc_vadd ディレクトリを作成した。
sudo mkdir /lib/firmware/xilinx/zub1cg_sbc_vadd binary_container_1.xclbin の名前を binary_container_1.bin に変更する。こうしないと、XRT は FPGA ビットストリームを抽出して Kria のプログラマブル ロジックをコンフィグレーションすることができないそうだ。
mv binary_container_1.xclbin binary_container_1.bin pl.dtbo binary_container_1.bin shell.json ファイルを /lib/firmware/xilinx/zub1cg_sbc_vadd ディレクトリにコピーした。
sudo cp pl.dtbo binary_container_1.bin shell.json /lib/firmware/xilinx/zub1cg_sbc_vadd アクセラレーション・アプリケーションを確認して、zub1cg_sbc_vadd をロードしたところエラーになった。
sudo xmutil loadapp zub1cg_sbc_vadd Ver. 2022.1 でもダメだった。この方法ではダメそうだ。
2023年08月18日 10:59 |
ZUBoard
| トラックバック:0
| コメント:0
”
ZUBoard 1CG の PYNQ v3.0.1 で自作のメディアン・フィルタとソーベル・フィルタを動作させる2 ”の続き。
”
RGB 24 ビットの AXI4-Stream データ入出力対応のメディアン・フィルタを Vitis HLS 2023.1 で作成する2 ”で作成したメディアン・フィルタを使ってみようということで、前回は、作成したブロック・デザインの HDL Wrapper ファイルを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行って、成功した。hwh ファイルと bit ファイルが生成された。今回は、生成されたビット・ファイルと hwh ファイルを ZUBoard 1CG 上の Jupyter Notebook にアップロードし、median_sobel.ipynb ファイルを作成して、メディアン・フィルタとソーベル・フィルタの動作を確認したところ動作した。
ZUBoard 1CG の PYNQ Linux の jupyter_notebooks/examples ディレクトリに median_sobel ディレクトリを作成した。
cd jupyter_notebooks/examples/ sudo mkdir median_sobel 以下のファイルを FileZilla を使って、ZUBoard 1CG の PYNQ Linux のホーム・ディレクトリにアップロードした。
HDL/2023.1/zub1cg/medain_sobel/medain_sobel.runs/impl_1/median_sobel_wrapper.bit
HDL/2023.1/zub1cg/medain_sobel/medain_sobel.gen/sources_1/bd/median_sobel/hw_handoff/median_sobel.hwh
Vitis_HLS/ZUBoard_1CG/2023.1/median_axis_RGB24/test2.jpg
なお、
test2.jpg は通常画像にノイズを拡散させた画像 となっている。
ファイルをホーム・ディレクトリから jupyter_notebooks/examples/median_sobel ディレクトリにコピーした。
cd sudo mv median_sobel.hwh jupyter_notebooks/examples/median_sobel mv median_sobel_wrapper.bit jupyter_notebooks/examples/median_sobel/median_sobel.bit sudo mv test2.jpg jupyter_notebooks/examples/median_sobel Jupyter Notebook で examples/median_sobel ディレクトリを見た。
Jupyter Notebook 上で examples/median_sobel ディレクトリにノートブックを作成した。
名前を Jupyter Notebook 上で median_sobel に変更しようとしたが、どうしてもできない。
ターミナルで jupyter_notebooks/examples/median_sobel ディレクトリに行って、mv コマンドで名前を変更した。
cd jupyter_notebooks/examples/median_sobel sudo mv Untitled.ipynb median_sobel.ipynb median_sobel.ipynb のコードを”
KV260 の PYNQ で自作のメディアン・フィルタとソーベル・フィルタを動作させる2 ”からコピーして、一部修正した。
from PIL import Image import numpy as np import matplotlib.pyplot as plt %matplotlib inline from pynq import allocate, Overlay median_sobel = Overlay("./median_sobel.bit") dma = median_sobel.axi_dma_0 median = median_sobel.median_axis_RGB24_0 sobel = median_sobel.sobel_axis_RGB24_0 image_path = "./test2.jpg" original_image = Image.open(image_path) canvas = plt.gcf() size = canvas.get_size_inches() canvas.set_size_inches(size*2) width, height = original_image.size print("Image size: {}x{} pixels.".format(width, height)) plt.figure(figsize=(12, 10)); _ = plt.imshow(original_image) in_buffer = allocate(shape=(height, width, 3), dtype=np.uint8, cacheable=1) out_buffer = allocate(shape=(height, width, 3), dtype=np.uint8, cacheable=1) in_buffer[:] = np.array(original_image) def run_kernel(): dma.sendchannel.transfer(in_buffer) dma.recvchannel.transfer(out_buffer) median.write(0x00,0x01) # start sobel.write(0x00,0x01) # start dma.sendchannel.wait() dma.recvchannel.wait() print(height) print(width) median.register_map.row_size = height median.register_map.col_size = width #median.register_map.function_r = 2 # ORG_IMGwAxiDma median.register_map.function_r = 3 # MEDIANwAxiDma sobel.register_map.row_size = height sobel.register_map.col_size = width #sobel.register_map.function_r = 2 # ORG_IMGwAxiDma sobel.register_map.function_r = 3 # SOBELwAxiDma run_kernel() sobel_image = Image.fromarray(out_buffer) print("Image size: {}x{} pixels.".format(width, height)) plt.figure(figsize=(12, 10)); _ = plt.imshow(sobel_image) del in_buffer del out_buffer
最初に
median.register_map.function_r = 3 # MEDIANwAxiDma
と
sobel.register_map.function_r = 3 # SOBELwAxiDma
でやってみた結果を示す。
つまり、メディアン・フィルタでノイズを除去しながら、ソーベル・フィルタでエッジを抽出する。
次に、
median.register_map.function_r = 2 # ORG_IMGwAxiDma
と
sobel.register_map.function_r = 3 # SOBELwAxiDma
でやってみた結果を示す。
つまり、メディアン・フィルタを掛けずにソーベル・フィルタでエッジを抽出する。
ノイズもエッジを抽出されている。
2023年08月16日 06:47 |
ZUBoard
| トラックバック:0
| コメント:0
”
ZUBoard 1CG の PYNQ v3.0.1 で自作のメディアン・フィルタとソーベル・フィルタを動作させる1 ”の続き。
”
RGB 24 ビットの AXI4-Stream データ入出力対応のメディアン・フィルタを Vitis HLS 2023.1 で作成する2 ”で作成したメディアン・フィルタを使ってみようということで、前回は、medain_axis_RGB24 IP を”
ZUBoard 1CG の PYNQ v3.0.1 で自作のソーベル・フィルタを動作させる1 ”で作成したブロック・デザインに追加した。今回は、作成したブロック・デザインの HDL Wrapper ファイルを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行って、成功した。hwh ファイルと bit ファイルが生成された。
median_sobel ブロック・デザインの HDL Wrapper ファイルを生成する。
Vivado 2023.1 で Source タブをクリックして Source ウインドウを表示し、Desgin Sources の median_sobel_i を右クリックし右クリックメニューから Create HDL Wrapper... を選択し、HDL Wrapper ファイルの median_sobel_wrapper.v を生成した。
Flow Navigator で PROGRAM AND DEBUG -> Generate Bitstream をクリックし、論理合成、インプリメンテーション、ビットストリームの生成を行って、成功した。
Project Summary を示す。
HDL/2023.1/zub1cg/medain_sobel/medain_sobel.runs/impl_1 ディレクトリに
median_sobel_wrapper.bit ファイルが生成された。
HDL/2023.1/zub1cg/medain_sobel/medain_sobel.gen/sources_1/bd/median_sobel/hw_handoff ディレクトリに median_sobel.hwh ファイルが生成された。
2023年08月15日 04:41 |
ZUBoard
| トラックバック:0
| コメント:0
”
RGB 24 ビットの AXI4-Stream データ入出力対応のメディアン・フィルタを Vitis HLS 2023.1 で作成する2 ”でメディアン・フィルタが作成できた。その medain_axis_RGB24 IP を”
ZUBoard 1CG の PYNQ v3.0.1 で自作のソーベル・フィルタを動作させる1 ”で作成したブロック・デザインに追加した。
”
ZUBoard 1CG の PYNQ v3.0.1 で自作のソーベル・フィルタを動作させる1 ”の sobel ブロック・デザインを出力する。
File メニューから Export -> Export Block Design... を選択する。
Export Block Design ダイアログが表示された。
OK ボタンをクリックする。
プロジェクトのディレクトリに sobel.tcl ファイルが出力された。
この tcl ファイルを実行すると sobel ブロック・デザインが生成される。
ZUBoard 1CG 用の Vivado 2023.1 の median_sobel プロジェクトを作成した。
median_sobel プロジェクトのディレクトリに先程作成した sobel.tcl をコピーして、名前を medain_sobel.tcl に変更した。
medain_sobel.tcl を開いて”set design_name sobel”から”set design_name median_sobel”に変更した。
sobel_pynq プロジェクトのディレクトリから sobel_axis_RGB24 IP のディレクトリを median_sobel ディレクトリにコピーした。
median_axis_RGB24 ディレクトリを新規作成した。
median_axis_RGB24 ディレクトリに”
RGB 24 ビットの AXI4-Stream データ入出力対応のメディアン・フィルタを Vitis HLS 2023.1 で作成する2 ”で作成した median_axis_RGB24/solution1/impl/export.zip の内容をコピーした。
Vivado の Flow Navigator から IP Catalog をクリックした。
IP Catalog ウインドウが開く。
右クリックし、右クリックメニューから Add Repository を選択し、sobel_axis_RGB24 と median_axis_RGB24 を選択して、IP を追加した。
Vivado 2023.1 の Tcl Console で次のコマンドを実行した。
cd /media/masaaki/Ubuntu_Disk/HDL/2023.1/zub1cg/medain_sobel/ source median_sobel.tcl すると、ソーベル・フィルタの回路が生成された。
+アイコンをクリックして、median_axis_RGB24 IP を追加した。
配線を行って、回路が完成した。
median_sobel ブロック・デザインを示す。
Address Editor を示す。
2023年08月14日 04:55 |
ZUBoard
| トラックバック:0
| コメント:0
”
RGB 24 ビットの AXI4-Stream データ入出力対応のメディアン・フィルタを Vitis HLS 2023.1 で作成する1 ”の続き。
メディアン・フィルタを ZUBoard 1CG の PYNQ v3.0.1 で使用するために Vitis HLS 2023.1 で RGB 24 ビットの AXI4-Stream データ入出力対応のメディアン・フィルタを Vitis HLS 2023.1 で作成するということで、前回は、Vitis HLS 2023.1 で median_axis_RGB24 プロジェクトを作成し、C シミュレーションを行った。今回は、C コードの合成、C/RTL 協調シミュレーション、Export RTL、Implementation を行った。
C コードの合成を行った。結果を示す。
median_axis_RGB24_Pipeline_LOOP_Y_LOOP_X の LOOP_Y_LOOP_X の Interval が 1 クロックとなっていて、メディアン・フィルタの出力が 1 クロック毎に 1 出力がでるようだ。問題無さそうだ。
C/RTL 協調シミュレーションを行った。結果を示す。
Avg II が 480057 クロックだった。画像サイズは 800 x 600 = 480000 ピクセルなので、ほぼ 1 ピクセル / クロックとなっているようだ。
C/RTL 協調シミュレーションの波形を示す。
全体波形を示す。
outs_TVALID もほぼ 1 でスループットが高いことが分かる。
最初の波形を拡大する。
ins_TREADY を見ると、最初はディアサートされている期間があることが分かるが、それが過ぎたら、1 のままになっている。
Export RTL を行った。
Implementation を行って、Vivado で実装した時の性能を確認した。
結果を示す。
CP achieved post-implementaion は 6.928 ns で動作周波数の 10 ns よりも小さく、問題無さそうだ。
2023年08月13日 03:52 |
ZUBoard
| トラックバック:0
| コメント:0
メディアン・フィルタを ZUBoard 1CG の PYNQ v3.0.1 で使用するために Vitis HLS 2023.1 で RGB 24 ビットの AXI4-Stream データ入出力対応のメディアン・フィルタを Vitis HLS 2023.1 で作成した。
Vitis HLS 2023.1 で median_axis_RGB24 プロジェクトを作成した。
part は
xczu1cg-sbva484-1-e を指定した。
ソースコードとテストベンチ・コードは、”
RGB 24 ビット・データ入出力対応のメディアン・フィルタを Vitis HLS 2021.2 で作成する1 ”のファイルを使用した。
今回のテストベンチ・コードでは OpenCV ライブラリを使用している。
Vitis HLS 2021.1 には内蔵された OpenCV は無いので、別にインストールした OpenCV を指定する。
Vitis HLS の Project メニューから Project Settings... を選択して、Project Settings ダイアログを開いた。
Simulation タブを開いて、median_axis_RGB24_tb.cpp の CFLAGS に
-I/usr/local/include
を設定した。
Linker Flags に
-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc
を設定した。
更に、 Synthesis をクリックして、 Top Function に median_axis_RGB24 を指定した。
C シミュレーションを行った。結果を示す。
median_axis_RGB24/solution1/csim/build ディレクトリを示す。
median.jpg と org.jpg が生成されている。
org.jpg は median_axis_RGB24 の col_size 変数に ORG_IMGwAxiDma を指定した時の出力となる。つまり元画像と同じ画像ファイルであるはずだ。
org.jpg を示す。ノイズが拡散されているのが分かると思う。
ノイズが拡散された元画像に 3 x 3 のメディアン・フィルタをかけた画像が median.jpg となる。
median.jpg を示す。拡散されたノイズが取れて、綺麗な画像になっていることが分かる。
2023年08月12日 11:17 |
ZUBoard
| トラックバック:0
| コメント:0
”
ZUBoard 1CG の PYNQ v3.0.1 で自作のソーベル・フィルタを動作させる1 ”の続き。
前回は、Vivado 2023.1 の sobel_pynq プロジェクトを作成し、
sobel_axis_RGB24 を使用して、sobel ブロック・デザインを作成した。論理合成、インプリメンテーション、ビットストリームの生成を行って、成功した。hwh ファイルと bit ファイルが生成された。今回は、hwh ファイルと bit ファイル、画像ファイルを ZUBoard 1CG に転送し、Jupyter Notebook を作成し、ソーベル・フィルタの動作を確認した。
HDL/2023.1/zub1cg/sobel_pynq/sobel_pynq.gen/sources_1/bd/sobel/hw_handoff/sobel.hwh ファイルと HDL/2023.1/zub1cg/sobel_pynq/sobel_pynq.runs/impl_1/sobel_wrapper.bit ファイルを FileZilla で ZUBoard 1CG の pynq linux に SFTP でホーム・ディレクトリにアップロードした。
~/jupyter_notebooks/examples/sobel ディレクトリを Jupyter Notebook 上で作成した。
ZUBoard 1CG の pynq linux 上でホーム・ディレクトリ上の sobel.hwh と sobel_wrapper.bit を ~/jupyter_notebooks/examples/sobel ディレクトリにコピーする。
sobel_wrapper.bit は sobel.bit に名前を変更した。
sudo mv sobel.hwh jupyter_notebooks/examples/sobel/ sudo mv sobel_wrapper.bit jupyter_notebooks/examples/sobel/sobel.bit Jupyter Notebook 上の examples/sobel ディレクトリを示す。
test2.jpg を転送するのを忘れていたので、FileZilla で ZUBoard 1CG の pynq linux 上のホーム・ディレクトリにアップロードする。
test2.jpg を ~/jupyter_notebooks/examples/sobel ディレクトリにコピーする。
sudo mv test2.jpg jupyter_notebooks/examples/sobel/ Jupyter Notebook 上で examples/sobel ディレクトリに sobel.ipynb を作成した。
sobel.ipynb に”
KV260 の PYNQ で自作のソーベル・フィルタを動作させる5 ”のコードをコピーして実行した。
test2.jpg のソーベル・フィルタ実行結果が表示されている。成功だ。
2023年08月11日 04:08 |
ZUBoard
| トラックバック:0
| コメント:0
”
RGB 24 ビットの AXI4-Stream データ入出力対応のソーベル・フィルタを Vitis HLS 2023.1 で作成する ”の続き。
”
RGB 24 ビットの AXI4-Stream データ入出力対応のソーベル・フィルタを Vitis HLS 2023.1 で作成する ”で Vitis HLS 2023.1 を使用して、ソーベル・フィルタ IP の sobel_axis_RGB24 を作成した。今回は、Vivado 2023.1 の sobel_pynq プロジェクトを作成し、sobel_axis_RGB24 を使用して、sobel ブロック・デザインを作成した。論理合成、インプリメンテーション、ビットストリームの生成を行って、成功した。hwh ファイルと bit ファイルが生成された。
ZUBoard 1CG 用の Vivado 2023.1 の sobel_pynq プロジェクトを作成した。
sobel_pynq ディレクトリの下に sobel_axis_RGB24 ディレクトリを作成し、”
RGB 24 ビットの AXI4-Stream データ入出力対応のソーベル・フィルタを Vitis HLS 2023.1 で作成する ”で生成された sobel_axis_RGB24/solution1/impl/export.zip を展開して sobel_axis_RGB24 ディレクトリにコピーした。
IP Catalog に sobel_axis_RGB24 IP を追加した。
sobel ブロック・デザインを作成し、完成させた。
axi dma を使用して、DMA したデータを AXI4-Stream で流して、sobel_axis_RGB24 に入力して、ソーベル・フィルタを掛ける。DMA するデータが OpenCV の MAT 形式なので、RGB のピクセルが 32 ビット幅(4 バイト)のデータバスに散らばっている。それを 3 バイト幅の RGB に戻すのが axis_dwidth_converter_0 の役割だ。その後、ソーベル・フィルタを掛けた 3 バイト幅のデータは axis_dwidth_converter_1 で 4 バイト幅(32 ビット幅)に変換される。つまり、OpenCV の MAT 形式に変換されて、PYNQ の Jupyter Notebook でその画像を表示することができるようになる。
zynq_ultra_ps_e_0 は、Re-customize IP ダイアログの PS-PL Configuration で PS-PL Interface の AXI HPM0 FPD と AXI HPC0 FPD のみにチェックを入れた。(ちなみに、Re-customize IP ダイアログを表示させるには、IP をダブル・クリックする)
axi_dma_0 は Re-customize IP ダイアログで Enable Scatter Gather Engine のチェックを外した。
更に、800 x 600 ピクセルの画像を一度に DMA するために Width of Buffer Length Resiger を 26 bits に変更した。
axis_dwidth_converter_0 の Master interface TDATA width (bytes) を 3 に設定した。
OpenCV の MAT 形式から RGB 3 バイト幅に変換する。
axis_dwidth_converter_1 の Master interface TDATA width (bytes) を 4 に設定した。
RGB 3 バイト幅から Open CV の MAT 形式に変換する。
Address Editor 画面を示す。
sobel ブロック・デザインの HDL Wrapper を作成した。
Vivado の Flow Navigator から Generate Bitstream をクリックし、論理合成、インプリメンテーション、ビットストリームの生成を行って、成功した。
Project Summary を示す。
HDL/2023.1/zub1cg/sobel_pynq/sobel_pynq.gen/sources_1/bd/sobel/hw_handoff ディレクトリに
sobel.hwh ファイルが生成された。
HDL/2023.1/zub1cg/sobel_pynq/sobel_pynq.runs/impl_1 ディレクトリに
sobel_wrapper.bit ファイルが生成された。
2023年08月10日 04:20 |
ZUBoard
| トラックバック:0
| コメント:0
ソーベル・フィルタを ZUBoard 1CG の PYNQ v3.0.1 で使用するために Vitis HLS 2023.1 で RGB 24 ビットの AXI4-Stream データ入出力対応のソーベル・フィルタを Vitis HLS 2023.1 で作成した。
ソースコードとテストベンチ・コードは、”
RGB 24 ビット・データ入出力対応のソーベル・フィルタを Vitis HLS 2021.2 で作成する3 ”の物を使用した。
Vitis HLS 2023.1 で sobel_axis_RGB24 プロジェクトを作成した。
part は
xczu1cg-sbva484-1-e を指定した。
今回のテストベンチ・コードでは OpenCV ライブラリを使用している。
Vitis HLS 2023.1 には内蔵された OpenCV は無いので、別にインストールした OpenCV を指定する。
Vitis HLS の Project メニューから Project Settings... を選択して、Project Settings ダイアログを開いた。
Simulation タブを開いて、sobel_axis_RGB24_tb.cpp の CFLAGS に
-I/usr/local/include
を設定した。
Linker Flags に
-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc
を設定した。
更に、 Synthesis をクリックして、 Top Function に sobel_axis_RGB24 を指定した。
現在の Vitis_HLS/ZUBoard_1CG/2023.1/median_axis_RGB24 ディレクトリを示す。
C シミュレーションを行った。
下の、Console では成功と表示されているが、_csim.log では、エラーになっている。これは、最初に OpenCV の設定を忘れていてエラーなったのが残っている状況だ。このログは消えないのだろうか?
solution1/csim/build ディレクトリを示す。
sobel.jpg が生成されていた。
C コードの合成を行った。結果を示す。
C/RTL 協調シミュレーションを行った。
結果を示す。
C/RTL 協調シミュレーション波形を示す。
ins_TREADY と outs_TVALID がほとんど 1 なので、スループットが高いことが分かる。
Export RTL を行った。
Implementation を行った。
CP achieved post-implementation が 5.934 ns で、良さそうだ。
2023年08月09日 04:51 |
ZUBoard
| トラックバック:0
| コメント:0
”
”Getting Started with PYNQ and the ZUBoard”をやってみる4 ”の続き。
Adam Taylor さんの”
Getting Started with PYNQ and the ZUBoard ”をやってみようということで、前回は、ブロック・デザインの HDL Wrapper ファイルを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。bit ファイルと hwh ファイルが生成された。今回は、前回生成した bit ファイルと hwh ファイルを ZUBoard 1CG の PYNQ v3.0.1 に転送し、”
Getting Started with PYNQ and the ZUBoard ”の Python3 のソフトウェアを動作せたところ、成功した。
ZUBoard 1CG の PYNQ v3.0.1 を起動して、Chrome ブラウザで IP アドレス の TCP ポート 9090 を見た。
Jupyter Notebook のログイン画面が出ているので、パスワードの xilinx を入れてログインした。
ディレクトリが表示されるので、右の New ボタンから Folder を選択して、新しいフォルダを作成する。
Untitle Folder が作成された。
Untitle Folder の前のチェックボックスにチェックを入れて、Rename ボタンをクリックする。
新しいディレクトリ名に tpg_overlay と入力して、Rename ボタンをクリックした。
するとフォルダの名前が tpg_overlay に変更された。
ZUBoard 1CG の PYNQ v3.0.1 のホーム・ディレクトリの下の jupyter_notebooks/tpg_overlay ディレクトリが生成されたので、
FileZilla で tpg_bd.hwh ファイルと tpg_bd_wrapper.bit ファイルをホーム・ディレクトリに SFTP でアップロードした。
これは、jupyter_notebooks/tpg_overlay ディレクトリのオーナーが root なので、直接 SFTP でアップロードできないためだ。
ここから ZUBoard 1CG の PYNQ v3.0.1 での作業となる。
tpg_bd.hwh ファイルと tpg_bd_wrapper.bit ファイルをホーム・ディレクトリから、jupyter_notebooks/tpg_overlay ディレクトリにリネームして移動した。
cd ~ sudo mv tpg_bd.hwh jupyter_notebooks/tpg_overlay/tpg.hwh sudo mv tpg_bd_wrapper.bit jupyter_notebooks/tpg_overlay/tpg.bit Jupter Notebook を見ると、tpg.hwh と tpg.bit ファイルが見える。
”
Getting Started with PYNQ and the ZUBoard ”の Python3 のソフトウェアを引用する。
import time import numpy as np from pynq import pl from pynq import Overlay from pynq.lib.video import * import cv2 import matplotlib.pyplot as plt ol = Overlay('/home/xilinx/jupyter_notebooks/tpg_overlay/tpg.bit') pixel_in = ol.pixel_pack_2_0 pixel_in.bits_per_pixel = 24 colourspace_in = ol.color_convert_2_0 rgb2bgr = [0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] colourspace_in.colorspace = rgb2bgr cam_vdma = ol.axi_vdma_0 lines = 512 framemode = VideoMode(640, lines, 24) cam_vdma.readchannel.mode = framemode cam_vdma.readchannel.start() tpg = ol.v_tpg_0 tpg.write(0x10,512) tpg.write(0x18,640) tpg.write(0x40,0) tpg.write(0x30,0) tpg.write(0x20,0xB) tpg.write(0x00,0x81) frame_camera = cam_vdma.readchannel.readframe() frame_color=cv2.cvtColor(frame_camera,cv2.COLOR_BGR2RGB) pixels = np.array(frame_color) plt.imshow(pixels) plt.show()
引用したコードで 右の New ボタンから Python3(ipykernel) を選択して、新しいノートブックを生成した。
新しいノートブックの前のチェックボックスにチェックを入れて、Rename ボタンをクリックして、名前を tpg.ipynb に変更した。
”
Getting Started with PYNQ and the ZUBoard ”の Python3 のソフトウェアを tpg.ipynb に入力した。
ノートブックを実行していくとテスト・パターンが表示された。成功だ。
2023年08月08日 04:05 |
ZUBoard
| トラックバック:0
| コメント:0
”
”Getting Started with PYNQ and the ZUBoard”をやってみる3 ”の続き。
Adam Taylor さんの”
Getting Started with PYNQ and the ZUBoard ”をやってみようということで、前回は、Color Convert (2ppc) IP と Pixel Pack (2 ppc) IP、 AXI Interrupt Controller IP を追加して、自動配線を行った。Validate Desgin を行ったところ、成功した。よって、ブロック・デザインが完成した。今回は、ブロック・デザインの HDL Wrapper ファイルを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。bit ファイルと hwh ファイルが生成された。
Source ウインドウに切り替えて tpg_bd を右クリックし、右クリックメニューから Create HDL Wrapper... を選択て、HDL Wrapper ファイルの tpg_bd_wrapper.v を生成した。
Flow Navigator から Generate Bitstream をクリックし、論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。
Project Summary を示す。
HDL/2023.1/zub1cg/test_pattern_gen/test_pattern_gen.gen/sources_1/bd/tpg_bd/hw_handoff ディレクトリに tpg_bd.hwh ファイルが生成された。
HDL/2023.1/zub1cg/test_pattern_gen/test_pattern_gen.runs/impl_1 ディレクトリに tpg_bd_wrapper.bit ファイルが生成された。
2023年08月07日 04:15 |
ZUBoard
| トラックバック:0
| コメント:0
”
”Getting Started with PYNQ and the ZUBoard”をやってみる2 ”の続き。
Adam Taylor さんの”
Getting Started with PYNQ and the ZUBoard ”をやってみようということで、前回は、生成した IP を使用してテスト・パターン・ジェネレーターのブロック・デザインを作成した。次に、Video Test Pattern Generator と AXI Video Direct Memory Access を Add IP して、自動配線を行った。今回は、Color Convert (2ppc) IP と Pixel Pack (2 ppc) IP、 AXI Interrupt Controller IP を追加して、自動配線を行った。Validate Desgin を行ったところ、成功した。よって、ブロック・デザインが完成した。
Color Convert (2ppc) IP を Add IP して、v_tpg_0 の m_axis_video 出力ポートから color_convert_2_0 の stream_in_48 入力ポートに配線を接続した。
Run Connection Automation をクリックして自動配線を行った。
Run Connection Automation ダイアログが開いた。
All Automation にチェックが入っていない場合はチェックを入れる。
OK ボタンをクリックして自動配線を行った。
現在のブロック・デザインを示す。
Pixel Pack (2 ppc) IP を Add IP した。
Run Connection Automation をクリックして自動配線を行った。
Run Connection Automation ダイアログが開いた。
All Automation にチェックが入っていない場合はチェックを入れる。
OK ボタンをクリックして自動配線を行った。
現在のブロック・デザインを示す。
color_convert_2_0 の stream_out_48 出力ポートから pixel_pack_2_0 の stream_in_48 入力ポートに配線を接続した。
pixel_pack_2_0 の stream_out_64 出力ポートから axi_vdma_0 の S_AXIS_S2MM 入力ポートへ配線を接続した。
Add IP を行って、AXI Interrupt Controller IP を追加した。
Run Connection Automation をクリックして自動配線を行った。
Run Connection Automation ダイアログが開いた。
All Automation にチェックが入っていない場合はチェックを入れる。
OK ボタンをクリックして自動配線を行った。
現在のブロック・デザインを示す。
axi_intr_0 をダブル・クリックして、設定を変更した。
Interrupt Output Connection を
Single に変更した。
OK ボタンをクリックした。
現在のブロック・デザインを示す。
Add IP を行って、Concat IP を追加した。
axi_vdma_0 の s2mm_introut 出力ポートから xlconcat_0 の In0 入力ポートへ配線を接続した。
v_tpg_0 の interrupt 出力ポートから xlconcat_0 の In1 入力ポートへ配線を接続した。
xlconcat_0 の dout から axi_intc_0 の intr 入力ポートへ配線を接続した。
これで配線が終了した。
Validate Design ボタンをクリックし、デザインをチェックした。
Validate Desgin ダイアログが表示されて、成功したので、配線のミスは無いようだ。
完成したブロック・デザインを示す。
Address Editor 画面を示す。
2023年08月06日 04:28 |
ZUBoard
| トラックバック:0
| コメント:0
Adam Taylor さんの”
Getting Started with PYNQ and the ZUBoard ”をやってみようということで、前回は、PYNQ の github リポジトリを git clone して、PYNQ リポジトリの下の boards/ip/hls ディレクトリに行って、build_ip.sh を実行して、Vitis HLS の IP を生成した。Vivado 2023.1 で test_pattarn_gen プロジェクトを作成し、生成した IP を IP Catlog に登録した。今回は、前回、生成した IP を使用してテスト・パターン・ジェネレーターのブロック・デザインを作成した。次に、Video Test Pattern Generator と AXI Video Direct Memory Access を Add IP して、自動配線を行った。
Adam Taylor さんの”
Getting Started with PYNQ and the ZUBoard ”のやり方を引用しているが、自分のやり方も加味している。
Vivado 2023.1 で Flow Navigator から IP INTEGRATOR -> Create Block Design をクリックして、ブロック・デザインを作成する。
Create Block Design ダイアログが開くので、Design Name に
tpg_bd と入力して、OK ボタンをクリックした。
Diagram ウインドウが表示されるので、真ん中の
+ ボタンをクリックして、Zynq UltraScale+ MPSoC を追加する。
IP を選択するダイアログが表示された。
Search: に
z と入力して、
Zynq UltraScale+ MPSoC をダブル・クリックして追加した。
Zynq UltraScale+ MPSoC が追加された。
Run Block Automation をクリックして、設定を行う。
Run Block Automation ダイアログが表示された。
OK ボタンをクリックする。
ZUBoard 1CG の設定が Zynq UltraScale+ MPSoC に設定された。
Zynq UltraScale+ MPSoC をダブル・クリックして設定を行う。
Page Navigator から PS-PL Configuration を選択する。
General -> Interrupts -> PL to PS -> IRQ0[0-7] の Select を 1 にして、割り込みの設定を行った。
PS-PL Interface -> Master Interface -> AXI HPM1 FPD のチェックボックスのチェックを外した。
PS-PL Interface -> Slave Interface -> AXI HP -> AXI HPC0 FPD のチェックボックスのチェックを入れた。
現在の Zynq UltraScale+ MPSoC を示す。
+ ボタンをクリックして
Video Test Pattern Generator を追加した。
Video Test Pattern Generator をダブル・クリックして設定を行った。
Samples per Clock を
2 に変更した。
+ ボタンをクリックして
AXI Video Direct Memory Access を Add IP した。
AXI Video Direct Memory Access をダブル・クリックして、設定を行い、
Enable Read Channel のチェックボックスのチェックを外した。
Run Connection Automation をクリックして、自動配線を行う。
Run Connection Automation ダイアログが開く。
All Automation をクリックして、自動配線を行う。
現在のブロック・デザインを示す。
2023年08月05日 15:01 |
ZUBoard
| トラックバック:0
| コメント:0
Adam Taylor さんの”
Getting Started with PYNQ and the ZUBoard ”をやってみよう。
Vivado, Vitis HLS 2023.1 を使用する。
Vitis の環境設定を行った。
source /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis/2023.1/settings64.sh 最初に
PYNQ の github リポジトリ を git clone した。
git clone https://github.com/Xilinx/PYNQ.git PYNQ リポジトリの下の boards/ip/hls ディレクトリに行って、build_ip.sh を実行した。
cd PYNQ/boards/ip/hls ./build_ip.sh Vitis HLS 2023.1 が起動して、高位合成を行った。
color_convert を見ると、solution1 ディレクトリが生成され、IP が生成されていた。
Vivado 2023.1 を起動して、test_pattarn_gen プロジェクトを作成する。
Avnet 社の ZUBoard 1CG 用のプロジェクトに設定した。
test_pattarn_gen プロジェクトが作成された。
PROJECT MANAGER の IP Catalog をクリックした。
IP Catlog ウインドウが開く。
ウインドウ内を右クリックし、右クリックメニューから Add Repository... を選択した。
Repositories ダイアログが開く。
PYNQ/boards/ip をクリックして、Select ボタンをクリックした。
Add Repository ダイアログが開いた。
OK ボタンをクリックした。
IP が IP Catlog に登録されたが、VITIS HLS IP は 3 個だけ登録されていた。
VITIS HLS IP の 3 個のパートは xc7z020-clg400-1 だった。他の IP は xczu7ev-ffvc1156-2-i とかで、ZYNQ じゃなかった。
他の IP はパートが違っているから IP Catalog に登録されないようだ?
Zynq MPSoC じゃなく Zynq でも ZUBoard 1CG の IP Catlog に入るということだと思う。結構賢い?
2023年08月04日 05:01 |
ZUBoard
| トラックバック:0
| コメント:0