LoginSignup
2
3

More than 1 year has passed since last update.

1500円ZYNQ基板とPiCamV2でZyboのPcam5Cデモを動かす(前編)

Last updated at Posted at 2021-05-19

(2021.5.21 更新)
8-2. Digilent 製 IP のアップグレード の項目を追加しました。
これをやらないと、エクスポートした .xsa に含まれるドライバの makefile が古い物になり、プロットフォームプロジェクトのビルドでエラーになります。

EBAZ4205_CSI-2_RX.xdc も更新。
(SCL/SDA が逆だったので入れ替え、MIPI も一部修正)

1. はじめに

1500円 ZYNQ 基板( EBAZ4205 )で、Digilent Zybo Z7-20 の Pcam 5C デモを動かしてみます。

このデモでは、CMOS カメラから映像を入力し、HDMI 出力してモニタに映すことができます。
前回投稿した Zybo Z7 HDMI Demo と違って信号発生器が不要で、実施しやすいデモになっています。

カメラは、手持ちの Raspberry Pi Camera Module V2 を使用します。

記述が長くなるため、記事を前編と後編に分けています。

前編: Vivado での作業
後編: 接続ケーブルの作成と、Vitis での動作確認

前編の今回は、Vivado を使ってプロジェクトを合成し、エクスポートするまでの作業を行います。

2. 使用環境

  1. Windows10 Pro (20H2)
  2. Vivado 2020.1 (Windows 版)
  3. Vitis 2020.1 (同上)
  4. EBAZ4205
  5. Raspberry Pi Camera Module V2 (SONY IMX219)
  6. HDMI Monitor (Leader LV5382)

3. 参考資料

Zybo Z7 Pcam 5C Demo
OV5640 datasheet
IMX219 datasheet
XAPP894 D-PHY Solutions
UG471 7Series FPGAs SelectIO Resources User Guide

4. Zybo Pcam 5C デモと使用カメラについて

Pcam 5C プロジェクトは、もともと Zybo Z7-20 (XC7Z020) と Pcam 5C の組み合わせ用に作成されています。

EBAZ4205 はそれより小さい XC7Z010 を搭載していて、PL のロジック規模は XC7Z020 の 1/3 しかありません。
容量的に無謀かと思いましたが、FPGA で CSI-2 受信は、個人的に画像処理プロセスの大きなテーマです。
試しにプロジェクトを開いてみると、リソース使用量は非常に少ないことがわかりました。

<XC7Z 020 でのリソース使用量>
1_Z7-20.png

試しにコンパイルしてみると、XC7Z010 でもそのまま移植できそうなことがわかりました。

<XC7Z 010でのリソース使用量>
2_Z7-10.png

本家の Zybo Z7-10 も、Pcam コネクタは搭載されていますので、ターゲットデバイス変更で動くのではないでしょうか。


デモで使用するカメラは、Digilent Pcam 5Cが指定されています。
結構いいお値段です。

ここは、手持ちのカメラ Raspberry Pi Camera Module V2 を使用してみることにします。

2つの製品で、搭載カメラモジュールに、

Pcam 5C : Ominivision OV5640 (2592 x 1944, 5M pixel)
PiCam V2 : SONY IMX219 (3280 x 2464, 8M pixel)

の違いがあります。

PiCam V2 の方が画素数が多く、裏面照射型の高感度センサで画質が良いのに、安価に入手できます。

ただし、Pcam 5C の代わりに使用するうえで、注意しないといけない点がいくつかあります。

4-1. 相違点1: カメラ内部設定

基板から出力されるコネクタのピン配置と、設定を I2C で行うところは同じですが、設定内容には互換性がありません。

IMX219 用のカメラ設定を、新規に作成します。

4-2. 相違点2: ベイヤー配列の色順

OV5640 と IMX219 ではベイヤー配列の画素の配置が違っています。

ベイヤー配列では、イメージセンサの田の字の単位画素の中に、緑が2つ、赤と青がそれぞれ一つづつ配置されています。

OV5640 と IMX219 を比較してみると、緑の位置は同じですが、赤と青の位置が逆になっています。

・OV5640 の画素配列
3.png

・IMX219 の画素配列
4.png

OV5640 用のベイヤーから RGB に変換する IP をそのまま使うと、赤と青のデータが入れ替わって色がおかしくなってしまいます。
Digilent 社の Bayer2RGB の IP を修正して対応します。

4-3. CSI-2 の信号速度

カメラ接続で使われる MIPI CSI-2 規格は、映像を高速シリアル差動信号で伝送します。
IMX219 は OV5640 より画素数が多い分、信号の周波数が高くなります。

IMX219 の出力は、最大 912 Mbps/レーン (2レーン接続時)とされています。
送出速度は解像度とフレームレートで決まりますので、適切な設定であれば、ZYNQ の通常の I/O ピンでも受信することができます。

4-4. その他の注意点

プログラムは、最小限の改造で、とりあえず動作確認ができるところまでを目指します。

実機で確認はしていませんが、本家 Zybo Z7 で Raspberry Pi Camera Module V2 を使う時も、このプログラムが流用できる筈です。

ZYNQ の I2C からカメラの設定を行うだけなので、Zybo Z7 でもプログラムは変わりません。

5. CSI-2 入力時の I/O ピン規格について

Xapp894 の Figure 11 に、7 シリーズの HR I/O ピンを使って MIPI D-PHY (CSI-2 or DSI) 入力を実装する例が示されています。

MIPI の HS 信号を LVDS_25 規格の差動入力で、
LP 信号を HSUL_12 規格のシングルエンド入力で、

それぞれ受信します。
H1.png

通常、LVDS_25 規格を使用するとき、その BANK の I/O 電源(VCCO)は 2.5V を供給します。
(UG471 Table 1-55)
H3.png

Zybo Z7 基板では、カメラコネクタの CSI-2 入力信号は、すべて ZNYQ の BANK_35 の I/O ピンに接続されています。
LVDS_25 規格で使う場合、VCCO_35 = 3.3V が供給されているのはまずいような感じがします。

しかし、UG471 Table 1-55 の注記: 1 で、下記の記述があります。

  1. これらの規格の差動入力は、出力の要求レベルと異なる VCCO レベルのバンクに配置できます。この場合に考慮すべき注意事項を次に示します。

 a. VCCO 電圧が出力で要求されるレベルでない限り、オプションの内部差動終端は使用されない(デフォルトで DIFF_TERM = FALSE)
 b. 入力ピンの差動信号は、各デバイスファミリのデータシートに記載されている推奨動作条件を示す表の VIN 要件を満たしている。
 c. 入力ピンの差動信号は、各デバイスファミリのデータシートに記載されている、 対応する LVDS または LVDS_25 DC 仕様の表にある VIDIFF および VICM の要件を満たしている。

MIPI D-PHY 信号では a.~c. の条件を満たすので、VCCO = 3.3V を供給しつつ LVDS_25 設定した HR I/O に直結できるようです。

HSUL_12 規格の入力は、VREF に内蔵 0.6V を指定すれば、VCCO 供給電圧は標準範囲内(1.8~3.3V)であれば OK です。
(前掲 UG471 Table 1-55 に ANY 記載あり)

forum 参考情報:
https://forums.xilinx.com/t5/Video-and-Audio/Can-one-use-HSUL-12-S-HR-with-Artix-7-board/td-p/1190393

ということで、EBAZ4205 (VCCO_34, VCCO_35 どちらも 3.3V 供給)でも、カメラの CSI-2 信号を直結して受信することができます。

6. 設計ファイルのダウンロード

から、Vivado 2019.1 の設計ファイル Zybo-Z7-20-pcam-5c-2019.1.zip をダウンロードします。

zip を展開後、

Zybo-Z7-20-pcam-5c-2019.1

が、ハードウェア(Vivado)の設計ファイルのフォルダで、

sdk_appsrc

が、アプリケーション(Vitis)のフォルダです。

例では、デスクトップに ts というフォルダを作成して、その中に zip を展開しておきます。

7. Vivado プロジェクトの準備

ハードウェアフォルダの中にある、Zybo-Z7-20-pcam-5c.xpr を Vivado 2020.1 で開きます。

プロジェクトを保存した Vivado とバージョンが違うため、アップグレードするかを聞かれます。
Automatically upgrade to the current version を選択して OK します。
S1.png

少し待つと、IP のアップデートを聞かれるので、ここでは Ignore を選びます。
S2_2.png

7-1. ターゲットデバイスの変更

Flow Navigator から、PROJECT MANAGER - Settings をクリックして、プロジェクト設定を開きます。
General の下に Project device: の設定があるので、デバイスを

xc7z010clg400-1
に変更して OK を押します。
S4.png

変更を反映しておきます。
S10.png
S11.png

7-2. IP のアップグレード

Sources タブの system_i をダブルクリックして、Block Diagram を表示します。
S5.png

IP のアップグレードを要求されますので、Report IP Status を押します。
S12.png

Report が表示されたら、そのまま Upgrade Selected を押して、IP をアップグレードします。
S3.png

S13.png

IP のアップグレードが終わると、合成するか聞かれますが、Skip します。
S9.png

バージョン違いによるエラー回避のため、デザインを一度 tcl スクリプトで出力して、再生成してから合成を行いますので、ここは Skip でかまいません。

7-3. PS の外部 I/O ピン変更

右側にある ZYNQ7 Processing System をダブルクリックして、おなじみの PS 設定を開きます。
S6.png

PS の変更が必要になるのは、下記 3 箇所です。

  1. PS の外部 I/O ピン (ブロックデザインの ZYNQ7 Processing System 設定を変更)
  2. DDR メモリの bit 幅、サイズ (同上)
  3. PL の I/O ピン (制約ファイル .xdc を入れ替え。最後にやる)

Peripheral I/O Pins を選択して、いつもの GUI で MIO 割り当てピンを変更します。

・Quad SPI Flash から NAND Flash に変更
・Ethernet 0 を EMIO に変更
  同、MDIO も EMIO に変更
・USB 0 のチェックを外す
・SD0 を 40-45 ピンに移動
  同、Card Detect を 34 ピンに移動
・UART1 を 24/25pin に移動
・I2C0 は EMIO のまま
・GPIO EMIO はチェックしてあっても構いません
S7.png

7-4. DDR メモリの bit 幅とサイズの変更

同じく、PS 設定の DDR Configuration で、DDR メモリ設定を変更します。

・Memory Part: MT41K128M16JT-125
・Effective DRAM Bus Width: 16 Bit

DQS to Clock Delay と Board Delay は、Zybo Z7 基板の固有値が入っています。
EBAZ4205 の固有値は不明なため、PS 設定の初期値に戻しておきます。
(0.0 と 0.25 が 4 つづつ)
S8.png

終わったら、OK を押して PS の設定を終わります。

IP Status が Rerun を求めて来ますが、無視して進めます。

7-5. tcl スクリプト書き出し

バージョンの違う Vivado で作成されたプロジェクトを、そのままコンパイルすると、何かとエラーが出てきます。
主に IP 間接続のクロック周波数設定でエラーが出るのですが、これを解決するのは難しいです。

一旦デザインを tcl スクリプトで吐き出してから、新しいバージョンのプロジェクトとして再生成させます。

メニューバーから、File - Project - Write Tcl...
を選択します。
S14.png

Write all properties、Copy sources to new project、Recreate Block Designs using Tcl にチェックを入れます。
出力ディレクトリには、元の設計ファイルの展開先フォルダ(例では デスクトップ\ts)を指定して OK を押します。
S15.png

tcl 書き出しが終わったら、File - Close Project を選んで、プロジェクトを閉じます。
このプロジェクトは Don't Save で閉じて構いません。
S16.png

8. Vivado プロジェクトの再生成

.tcl スクリプトからプロジェクトを再生成しますが、その前に IP の変更を行います。

8-1. BayerToRGB の変更

前述の CMOS センサのベイヤー配列の違いを吸収するため、ベイヤーから RGB に画素変換する IP を修正します。

適当なテキストエディタで、プロジェクトの中にある AXI_BayerToRGB.vhd を開きます。
最後にある AXI 出力データの記述で、Blue と Red を入れ替えます。

(設計ファイルを展開したフォルダ)\Zybo-Z7-20-pcam-5c-2019.1\Zybo-Z7-20-pcam-5c-2019.1\vivado_proj\Zybo-Z7-20-pcam-5c.ipdefs\repo_0\local\ip\AXI_BayerToRGB\hdl\AXI_BayerToRGB.vhd

(変更前)
-- Assign AXI stream output interface signals.
(略)
m_axis_video_tdata <= "00" & std_logic_vector(sAXIMasterRed) &
std_logic_vector(sAXIMasterBlue) &
std_logic_vector(sAXIMasterGreen(kBayerWidth downto 1));

(変更後)
m_axis_video_tdata <= "00" & std_logic_vector(sAXIMasterBlue) &
std_logic_vector(sAXIMasterRed) &
std_logic_vector(sAXIMasterGreen(kBayerWidth downto 1));

8-2. Digilent 製 IP のアップグレード

MIPI_CSI_2_RX
MIPI_D_PHY_RX
rgb2dvi
の3つのIPを最新版に差し替えます。

最新版を、github からフォルダごと clone します。

\Zybo-Z7-20-pcam-5c-2019.1\vivado_proj\Zybo-Z7-20-pcam-5c.ipdefs\repo_0\vivado-library\ip
に、プロジェクトで使用している IP のフォルダがあります。

古い IP をフォルダごと削除して、
S24.png

新しいバージョンの IP をフォルダごとコピーします。
S25.png
S26.png

8-3. tcl 読み込みでプロジェクト再生成

Vivado のオープニング画面の下に、Tcl Console があります。
S17.png

Type a Tcl commmand here のところにコマンドを打ち込んでいきます。
・カレントフォルダを、先ほど tcl を書きだしたフォルダに移動します。
・source コマンドで、tcl ファイルを指定して読み込みます
S18.png

.tcl の書き出しフォルダの場所が悪いと、絶対パスで指定された一部のファイルが見つからずにエラーで失敗します。
.tcl を正しい場所に置いて、再度実行してください。
例では、デスクトップに ts というフォルダを作成して、そこに設計ファイルを展開しています。

再生成されたブロック図は、下記のようになりました。
S27.png

8-4. AXI アドレスの割り当て

Sources ペインの sysytem_i をダブルクリックして、ブロックデザインを開きます。

Address Editor のタブを開くと、下2つの IP のアドレスが Unassigned になっていますので、アドレスを割り当てます。
S19.png

/video_dynclk
/vtg
の順に、それぞれ右クリックして、Assign を選びます。
S20.png

全て、アドレスが割り当たりました。
S21.png

8-5. CSI-2 RX のピン配置の指定

PL の I/O ピン設定を、制約ファイル .xdc で指定します。

HDMI 出力ピンの割り当ては、前回の記事 1500円ZYNQ基板でZyboのHDMIデモを動かす で決めた配置を、そのまま流用します。

CSI-2 入力ピンは、新たに ZYNQ-PL の I/O ピンに割り当てて、EBAZ4205 の DATA2 コネクタから引き出します。
各入力ピンの割り当ては、何度かコンパイルして最適なところを選択しました。

下記に、ピン配置表を示します。
S22.png

8-6. 制約ファイルの登録

ピン配置表から、制約ファイル EBAZ4205_CSI-2_RX.xdc を作成しました。

EBAZ4205_CSI-2_RX.xdc

#EBAZ4205 HDMI TX
set_property -dict { PACKAGE_PIN F20   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_clk_n }]; #IO_L15N_T2_DQS_AD12N_35 Sch=hdmi_tx_clk_n
set_property -dict { PACKAGE_PIN F19   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_clk_p }]; #IO_L15P_T2_DQS_AD12P_35 Sch=hdmi_tx_clk_p
set_property -dict { PACKAGE_PIN D20   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_data_n[0]  }]; #IO_L4N_T0_35 Sch=hdmi_tx_n[0]
set_property -dict { PACKAGE_PIN D19   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_data_p[0]  }]; #IO_L4P_T0_35 Sch=hdmi_tx_p[0]
set_property -dict { PACKAGE_PIN B20   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_data_n[1]  }]; #IO_L1N_T0_AD0N_35 Sch=hdmi_tx_n[1]
set_property -dict { PACKAGE_PIN C20   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_data_p[1]  }]; #IO_L1P_T0_AD0P_35 Sch=hdmi_tx_p[1]
set_property -dict { PACKAGE_PIN A20   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_data_n[2]  }]; #IO_L2N_T0_AD8N_35 Sch=hdmi_tx_n[2]
set_property -dict { PACKAGE_PIN B19   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_data_p[2]  }]; #IO_L2P_T0_AD8P_35 Sch=hdmi_tx_p[2]

#set_property -dict { PACKAGE_PIN H18   IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_scl }]; # Sch=hdmi_tx_scl
#set_property -dict { PACKAGE_PIN E19   IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_sda }]; # Sch=hdmi_tx_sda


#EBAZ4205 MIPI (BANK35 は VCCO=3.3V でいい)
set_property PACKAGE_PIN K17 [get_ports {cam_gpio_tri_io[0]}]; # IO_L12P_T1_MRCC_35
set_property IOSTANDARD LVCMOS33 [get_ports {cam_gpio_tri_io[0]}]; #
set_property PULLUP true [get_ports {cam_gpio_tri_io[0]}]; #

set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS33} [get_ports cam_iic_scl_io]; # IO_L18N_T2_AD13N_35
set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS33} [get_ports cam_iic_sda_io]; # IO_L18P_T2_AD13P_35

set_property INTERNAL_VREF 0.6 [get_iobanks 35]; #

set_property -dict {PACKAGE_PIN M20 IOSTANDARD HSUL_12} [get_ports dphy_clk_lp_n]; #IO_L7N_T1_AD2N_35
set_property -dict {PACKAGE_PIN K18 IOSTANDARD HSUL_12} [get_ports dphy_clk_lp_p]; #IO_L12N_T1_MRCC_35

set_property -dict {PACKAGE_PIN M18 IOSTANDARD HSUL_12} [get_ports {dphy_data_lp_n[0]}]; #IO_L8N_T1_AD10N_35
set_property -dict {PACKAGE_PIN J20 IOSTANDARD HSUL_12} [get_ports {dphy_data_lp_p[0]}]; #IO_L17P_T2_AD5P_35
set_property -dict {PACKAGE_PIN J18 IOSTANDARD HSUL_12} [get_ports {dphy_data_lp_n[1]}]; #IO_L14P_T2_AD4P_SRCC_35
set_property -dict {PACKAGE_PIN H20 IOSTANDARD HSUL_12} [get_ports {dphy_data_lp_p[1]}]; #IO_L17N_T2_AD5N_35

set_property -dict {PACKAGE_PIN L17 IOSTANDARD LVDS_25} [get_ports dphy_hs_clock_clk_n]; #IO_L11N_T1_SRCC_35
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVDS_25} [get_ports dphy_hs_clock_clk_p]; #IO_L11P_T1_SRCC_35

set_property -dict {PACKAGE_PIN L20 IOSTANDARD LVDS_25} [get_ports {dphy_data_hs_n[0]}]; #IO_L9N_T1_DQS_AD3N_35
set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVDS_25} [get_ports {dphy_data_hs_p[0]}]; #IO_L9P_T1_DQS_AD3P_35
set_property -dict {PACKAGE_PIN J19 IOSTANDARD LVDS_25} [get_ports {dphy_data_hs_n[1]}]; #IO_L10N_T1_AD11N_35
set_property -dict {PACKAGE_PIN K19 IOSTANDARD LVDS_25} [get_ports {dphy_data_hs_p[1]}]; #IO_L10P_T1_AD11P_35

これを、Vivado に制約ファイルとして登録します。

プロジェクトには、制約ファイルが 3 つ登録されています。
このうち、外部 I/O ピンの制約は ZyboZ7_A.xdc で決められています。
ZyboZ7_A.xdc の登録を解除して、代わりに EBAZ4205_CSI-2_RX.xdc を登録しておきます。
S23.png

8-7. 合成とハードウェア情報のエクスポート

準備ができたら、Generate Bitstream で合成します。
合成が完了したら、File - Export - Export Hardware で Include bitstream としてハードウェア情報(system_wrapper.xsa)を出力します。

これで回路は完成しました。

ここから先は、後編の Vitis での作業になります。

9. 前編のまとめ

EBAZ4205 で、Zybo Z7 Pcam 5C Demo を実行する準備ができました。

後編では、CSI-2 入力 + HDMI 出力ケーブルを作成し、Vitis を使って実際に動作させてみます。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3