LoginSignup
5
7

More than 3 years have passed since last update.

1500円ZYNQ基板でZyboのHDMIデモを動かす

Last updated at Posted at 2021-05-07

はじめに

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

当初、Vivado/Vitis 2020.1 で 2018.2 版を試してみましたが、うまくいきませんでした。

原因を探したところ、治すよりも先に 2020.1 版が仮リリースされていました。
こちらでやっていきたいと思います。
2020.2 でも、そのまま使えるようです。

Zybo Z7 HDMI Demo (2020.1)

使用環境

  1. Windows10 Pro (20H2)
  2. Vivado 2020.1 (Windows 版)
  3. Vitis 2020.1 (同上)
  4. EBAZ4205
  5. HDMI Source (信号発生器 ASTRODESIGN VG-870) - HDMI Sink の EDID が読めなくても、強制的に RGB で信号を出せるもの
  6. HDMI Monitor (波形モニタ Leader LV5382)

参考資料

Zybo Z7 HDMI Input/Output Demo
github/Digilent/Zybo-Z7-10-HDMI

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

から、設計ファイルをダウンロードします。

Zybo-Z7-10-HDMI-2020.1-1-hw.xpr.zip

が、ハードウェア(Vivado)で、

Zybo-Z7-10-HDMI-2020.1-1-sw.ide.zip

が、アプリケーション(Vitis)です。

2. ハードウェアの設定

ハードウェア設計ファイル Zybo-Z7-10-HDMI-2020.1-1-hw.xpr.zip を解凍すると、Vivado のプロジェクトが出てきます。

hw.xpr を Vivado で開きます。
10.png

プロジェクトを EBAZ4205 に対応させるため、ハードウェア設定を変更します。

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

  1. PS の外部 I/O ピン (ブロックデザインの ZYNQ7 Processing System 設定を変更)
  2. DDR メモリの型番、bit 幅、タイミング (同上)
  3. PL の HDMI I/O ピン (制約ファイル .xdc を入れ替え)

1. PS の外部 I/O ピンの変更

design_1_i をダブルクリックして、Block Diagram を表示します。
11.png

真ん中列の下にある ZYNQ7 Processing System をダブルクリックして、おなじみの PS 設定を開きます。
12.png

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 のまま)

13.png

2. DDR メモリの変更

同じく、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 つづつ)
14.png

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

3. PL の HDMI I/O ピンの変更

HDMI の入力と出力は、ZYNQ-PL の I/O ピンに直接割り当てて、EBAZ4205 の拡張コネクタ(DATA1, DATA2, DATA3)から引き出します。
PL の I/O ピン設定は、制約ファイル .xdc で指定します。

HDMI 出力については、以前の記事 1500円ZYNQ基板でFPGAプログラミング大全Xilinx編(第2版)の実習 2-3 HDMIでパターン表示 で先に実現していますので、そちらも参照してみてください。

今回は、内部制約の都合で HDMI 出力ピンを以前の記事から変えています。

制約ファイル EBAZ4205-Master.xdc を示します。

EBAZ4205-Master.xdc
## This file is a general .xdc for the EBAZ4205

set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_nets design_1_i/dvi2rgb_0/U0/TMDS_ClockingX/CLK_IN_hdmi_clk];

#HDMI RX
set_property -dict { PACKAGE_PIN H20   IOSTANDARD LVCMOS33 } [get_ports { hdmi_in_ddc_scl_io }]; #IO_L17N_T2_AD5N_35 Sch=hdmi_rx_scl
set_property -dict { PACKAGE_PIN J20   IOSTANDARD LVCMOS33 } [get_ports { hdmi_in_ddc_sda_io }]; #IO_L17P_T2_AD5P_35 Sch=hdmi_rx_sda

set_property -dict { PACKAGE_PIN K18   IOSTANDARD TMDS_33  } [get_ports { hdmi_in_clk_n }]; #IO_L12N_T1_MRCC_35 Sch=hdmi_rx_clk_n
set_property -dict { PACKAGE_PIN K17   IOSTANDARD TMDS_33  } [get_ports { hdmi_in_clk_p }]; #IO_L12P_T1_MRCC_35 Sch=hdmi_rx_clk_p
set_property -dict { PACKAGE_PIN U20   IOSTANDARD TMDS_33  } [get_ports { hdmi_in_data_n[0] }]; #IO_L15N_T2_DQS_34 Sch=hdmi_rx_n[0]
set_property -dict { PACKAGE_PIN T20   IOSTANDARD TMDS_33  } [get_ports { hdmi_in_data_p[0] }]; #IO_L15P_T2_DQS_34 Sch=hdmi_rx_p[0]
set_property -dict { PACKAGE_PIN P20   IOSTANDARD TMDS_33  } [get_ports { hdmi_in_data_n[1] }]; #IO_L14N_T2_SRCC_34 Sch=hdmi_rx_n[1]
set_property -dict { PACKAGE_PIN N20   IOSTANDARD TMDS_33  } [get_ports { hdmi_in_data_p[1] }]; #IO_L14P_T2_SRCC_34 Sch=hdmi_rx_p[1]
set_property -dict { PACKAGE_PIN P18   IOSTANDARD TMDS_33  } [get_ports { hdmi_in_data_n[2] }]; #IO_L23N_T3_34 Sch=hdmi_rx_n[2]
set_property -dict { PACKAGE_PIN N17   IOSTANDARD TMDS_33  } [get_ports { hdmi_in_data_p[2] }]; #IO_L23P_T3_34 Sch=hdmi_rx_p[2]

set_property -dict { PACKAGE_PIN J18   IOSTANDARD LVCMOS33 } [get_ports { hdmi_in_hpd_tri_o }]; #IO_L14P_T2_AD4P_SRCC_35 Sch=hdmi_rx_hpd



#HDMI TX
set_property -dict { PACKAGE_PIN F20   IOSTANDARD TMDS_33  } [get_ports { hdmi_out_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_out_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_out_data_n[0]  }]; #IO_L4N_T0_35 Sch=hdmi_tx_n[0]
set_property -dict { PACKAGE_PIN D19   IOSTANDARD TMDS_33  } [get_ports { hdmi_out_data_p[0]  }]; #IO_L4P_T0_35 Sch=hdmi_tx_p[0]
set_property -dict { PACKAGE_PIN B20   IOSTANDARD TMDS_33  } [get_ports { hdmi_out_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_out_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_out_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_out_data_p[2]  }]; #IO_L2P_T0_AD8P_35 Sch=hdmi_tx_p[2]

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

4. コンパイルとハードウェア情報のエクスポート

準備ができたら、Generate Bitstream で一式コンパイルして、Export Hardware でハードウェア情報(design_1_wrapper.xsa)を出力します。

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

5. HDMI 入力の差動ピン配置について

HDMI 入力は、最初に適当な差動ピンに割り当ててコンパイルしてみたところ、配置できずにエラーとなりました。
これは、XC7Z010 の内部リソースの配置による制限でした。

HDMI のクロック信号処理には、CMT(Clock Managemnt Tiles) が使われます。

XC7Z010 には、CMT が 2 つ搭載されています。
CMT には MMCM と PLL が搭載されていて、どちらかの機能を使います。

HDMI 入力(DVI2RGB)と、HDMI 出力(RGB2DVI)で、MMCM が 1 つづつ使用されます。

デモ回路をコンパイルしてみると、
上側 CMT の MMCM 11 に HDMI 出力の機能が、
下側 CMT の MMCM 10 に HDMI 入力の機能が、
それぞれ割り当てられます。

(UG865 図1-1)
15.png

CMT には、すぐ隣のファブリックしか駆動できない制約があります。
関連する I/O ピン(HDMI のクロック以外の信号ピン 3 対)も、そのファブリックに接続できるピンに割り当てないといけません。

つまり、
上側のファブリックから接続可能な BANK 35 の差動 I/O ピンに HDMI OUT を、
下側のファブリックから接続可能な BANK 34 の差動 I/O ピンに HDMI IN を、
それぞれ割り当てる必要があります。


EBAZ4205 の DATA1,DATA2,DATA3 に出ている I/O ピンは、下記の通りです。
全体の 2/3 が BANK 35、1/3 が BANK 34 から接続されています。
16.png

差動 I/O ペアとして使えるピンを寄せてみると、このようになります。
BANK 35 側で 14 対、BANK 34 側で 3 対の差動ペア信号(対)が使用できます。
17.png

ただし、BANK 35 側の 14 対のうち、4 対はコネクタを跨いで配置されていて、差動で使うには少し都合が悪いです。
高速差動信号は、対の信号線間の距離を、できるだけ離さずに配線しないといけません。


HDMI 信号は、クロック 1対 + 信号 3対の、合計 4 対の差動信号線で構成されています。

BANK 35 側は、HDMI OUT の 4 対がそのまま出せますが、
BANK 34 側は、3 対しかないので、HDMI IN には 1 対不足します。

そこで、HDMI IN 側のクロックだけ、BANK 35 側の対を借りて接続します。

実は、クロック信号入力は、クロック専用入力の MRCC ピン(対)へ入れれば、上下 BANK を跨いだ MMCM に接続できます。
このおかげで、I/O ピンの限られている EBAZ4205 に、HDMI IN と HDMI OUT の両方を実装することができました。

Vivado で何度かコンパイルして、配置状態を見ながら決定した HDMI IN/OUT の信号割り当ては、下のようになりました。
18.png

3. HDMI 入出力コネクタの作成

前回と同様、aitendo の HDMI コネクタ with 基板 と、
19.png

★2.0★2列ピンソケット [PS20DV] 2x10 を使って作成します。
20.png

ピン配置結果を元に、配線図を作成しました。
21.png

最初はストレートで作成したのですが、640x480/60p までしか映りませんでした。
22.jpg

差動ペア線の片側の線を外して、+-をツイストしたところ、多少不安定ながらも 1080/60p まで映るようになりました。
23.jpg

4. ダンピング抵抗の 22Ω → 0Ω 交換と、TMDS 終端抵抗の追加

以前の記事 でも書きましたが、ZYNQ の I/O ピンを TMDS_33 に設定して、直接 HDMI の TMDS 信号を入出力します。
5.png

TMDS_33 で使用するため、DATA1~DATA3 コネクタへの途中にある 22Ω のダンピング抵抗を 0Ωに交換します。
今回は、使う信号線だけ交換するのではなく、まとめて全部 0Ω に交換してしまいます。

また、TMDS_33 の受信側には、正負それぞれ 50Ω で 3.3V への終端抵抗を設置します。
これは HDMI IN の信号線のみに設置するので、抵抗の番号を調べています。
24.png

作業後の基板はこのようになりました。
U23 の端子に 3.3V が来ていたので、そこから 50Ω を吊っています。
6.jpg

あと、DATA1 コネクタから接続する HDMI OUT の +5V Power 端子に電源を出力するため、逆流防止ダイオード D21 にジャンパを追加します。
25.png

26.jpg

5. ソフトウェアの設定

アプリケーション Zybo-Z7-10-HDMI-2020.1-1-sw.ide.zip の中から、Zybo-Z7-10-HDMI フォルダだけを、デスクトップに解凍しておきます。
このフォルダに、design_1_wrapper.xsa をコピーします。
30.png

Vitis を起動したら、File - Switch Workspace... - Other... で Zybo-Z7-10-HDMI フォルダをワークスペースに指定して、Launch します。
31.png

Create Platform Project で、EBAZ-HDMI としてプロジェクトを作成し、design_1_wrapper.xsa を指定して Finish。

次に File - New - Application Project... で EBAZ-HDMI を platform に選択し、EBAZ-HDMI-app という名前で Next。
standalone_domain で Next して、Empty Applicaion (C++じゃない方)を選び Finish。

EBAZ-HDMI-app_system の src フォルダで右クリックして、Inport Sources... を選びます。
32.png

Import Sources で、src と Overwrite existing resources without warning にチェックを入れて Finish。
33.png

これで、アプリケーションプロジェクトをビルドします。
34.png

ビルドが終わったら、準備完了です。

6. 動作テスト

基板に電源を入れて、Vivado/Vitis から認識できるようにしておきます。
TeraTerm を起動してから、デバッグに入ります。

Debug Configuraion で、Single Applicaion Debug をダブルクリックして、
35.png

開いた画面で Debug ボタンを押して、デバッグを起動します。
36.png

Resume を押す前に、HDMI 信号発生器からテスト信号を出して、基板へ入力しておきます。
HDMI 入力に信号が入っていないと、アプリケーションがエラーを出して停止します。
(これで半日も悩んだ)

1.jpg

HDMI モニタも接続しておきます。
2.jpg

Resume を押すと、TeraTerm にデモのメニュー画面が表示され、動き出します。
38.png

操作は、数字キーを入力します。
1. 出力解像度の変更
2. 表示するフレームバッファ番号の変更 (1,2,3 から選択)
3. 表示中のフレームバッファにグラデーションパターンを描画
4. 表示中のフレームバッファにカラーバーを描画
5. HDMI IN 入力信号のフレームバッファへの書込みの START/STOP (トグルする)
6. HDMI IN から書き込むフレームバッファ番号の変更 (1,2,3 から選択)
7. HDMI IN から 1 フレームをフレームバッファに取り込み、色を反転
8. HDMI IN から 1 フレームを、フレームバッファの表示サイズにリサイズして取り込み
9. 終了

HDMI 出力解像度は、下記から選択できます。
1 - 640x480@60Hz
2 - 800x600@60Hz
3 - 1280x720@60Hz
4 - 1280x1024@60Hz
5 - 1600x900@60Hz
6 - 1920x1080@60Hz
q - Quit (don't change resolution)

HDMI 入力解像度は、自動判別します。
1440x288/50p とかの普通使われない解像度も受け付けてくれます。

フレームレートも、50/60 以外でも受け付けてくれます。
720x480/240p も映りました。
(出力側は 60p しか出さないので、1 枚出すまでに 3 回書き換えてる?)

例では、1920x1080/60p 出力のグラデーションに、1280x720/60p の HDMI 入力を取り込んで重ねています。
3.jpg
4.png

HDMI IN は、連続的にフレームバッファに取り込めるので、動画で PinP として映ります。

7. デバッグ用エラー表示の追加

何らかの原因で、プログラムがハングしてしまうことがあります。
何も表示しないで固まってしまうので、調べるのが大変です。

このような時は、プラットフォームプロジェクトの、
/ps7_cortexa9_0/standalone_domain/bsp/ps7_cortexa9_0/libsrc/standalone_v7_2/xdebug.h に、

#define DEBUG
#undef NDEBUG

を追加します。
39.png

ソース中に xdbg_printf( ) で埋め込まれたデバッグメッセージが表示されるようになり、原因推定に役立ちます。

下記は HDMI IN に信号が入っていない時に、停止して表示されるエラーです。
理由は分かりませんが、HDMI IN に信号(おそらくクロック)が入っていないと、エラーが出て止まります。
40.png

まとめ

EBAZ4205 で、Zybo Z7 HDMI Input/Output Demo を動かすことができました。

5
7
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
5
7