#はじめに
1500円 ZYNQ 基板(EBAZ4205)を使って、
FPGAプログラミング大全Xilinx編(第2版)の課題2-3
「PC用ディスプレイにパターンを表示 (HDMI出力) 」
を学習したいと思います。
#DVI や HDMI で使われる TMDS 信号の説明
PC とモニタをデジタル接続する規格として、DVI が普及しました。
DVI 規格では、ディスプレイカードの高精細ビデオ信号をデジタル信号で出力します。
高速なデジタル信号を長いケーブルで伝えるため、TMDS 信号という形式で出力されています。
HDMI は、民生用のデジタルビデオ信号規格として、DVI が元になっているため、やはり TMDS で伝送されます。
DVI 規格書
http://www.cs.unc.edu/Research/stc/FAQs/Video/dvi_spec-V1_0.pdf
TMDS 信号の物理層は DVI 規格書に書かれています。
Transmitter 側は電流ソースの差動出力となっています。
Receiver 側では差動入力をそれぞれ AVCC=3.3V に RT=50Ω で終端して、受信します。
#Xilinx の TMDS_33 規格の説明
ZYNQ-7000 を含む Xilinx 7 シリーズ FPGA では、I/O ピンの出力モードを "TMDS_33" に設定すると、TMDS 信号を直接入出力できます。
具体的な使い方は、DS187 (Zynq-7000 SoC DC 特性および AC スイッチ特性)を見る事になっています。
しかし、肝心な回路図とかは無く、表の一部に TMDS_33 の項目が見えるだけで、さっぱりわかりません。
UG471 (7 シリーズ FPGA SelectI/O リソース ユーザーガイド)を見ても、「遠端に 3.3V への 50Ω抵抗」と、一言書かれているだけです。
TMDS_33 は、Xilinx の 2 世代前のFPGA Spartan-3A で最初に搭載された I/O 規格です。
そこで Spartan-3A の資料を探してみると、UG331 に TMDS_33 の具体的な解説と図がありました。
TMDS_33 出力
VCCO = 3.3V を供給する (Bank0 または Bank2)
TMDS_33 に設定した差動ペアの出力端子から正・負の信号を出力し、HDMI ケーブルを駆動する。
TMDS_33 入力
VCCAUX= 3.3V を供給する (Bank はどれでもよい)
正・負どちらの信号線も、3.3V 電源に対して50Ωで終端してから、TMDS_33 に設定した>差動ペアの入力端子で受信する。
#HDMI 出力の搭載方法
TMDS_33 規格を使って、FPGA の I/O ピンからそのまま HDMI コネクタへ接続して、出力端子にできそうなことがわかりました。
(デバイスの静電気保護とかは、とりあえず考えない)
元の信号名は TMDS ですが、Xilinx では TMDS_33 と表記することで、その BANK の I/O 電源ピン(VCCO)への供給電圧を示しています。
(例えば、LVDS_25 は、VCCO に 2.5V を供給すると使える LVDS I/O 規格です。)
EBAZ4205 では、ZYNQ の PL の I/O ピンである VCCO_34 と VCCO_35 どちらも、3.3V が供給されているので、TMDS_33 で使えます。
ZYNQ では TMDS_33 に設定できるピンに BANK の縛りはなく、PL の I/O ピンはどれでも使用できるようです。
(7 シリーズは、Spartan6 よりも I/O バッファの構造が進化しているため)
#EBAZ4205 の出力ピンの調査
TMDS_33 出力の説明で、"差動ペアの出力端子" から出力すると書きました。
ZYNQ に限らず、たいていの FPGA では、差動出力でペアにできるピンは、あらかじめ決められています。(差動入力も同様)
最もよく使われる LVCMOS_33 だとペアの縛りがないので、任意のピンから任意の信号を出力できます。
しかし、差動出力はペアになれるピンが決まっているため、2本セットで引き出さないといけません。
EBAZ4205 では、DATA1, DATA2, DATA3 の 3 つのコネクタが、拡張コネクタとして利用できます。
このコネクタに接続されている ZYNQ の I/O ピンのうち、ペアにできるピンを使って、TMDS の 正・負 信号を出力しないといけません。
XC7Z010-1CLG400 のピン番号とピン名の割り当ては、xc7z010clg400pkg.txt に記載されています。
https://www.xilinx.com/support/packagefiles/z7packages/xc7z010clg400pkg.txt
信号名で、ほぼ同じ名前で 正(P)、負(N) の違いがあるピンが、差動ペアになれるピンです。
BGA パッケージ上で、必ず隣のピンに割り当てられています。
(例)
U20 IO_L15P_T2_DQS_34 (差動信号の正側)
V20 IO_L15N_T2_DQS_34 (差動信号の負側)
EBAZ4205 の回路図では、FPGA の回路シンボルにピン名が記載されていません。
xc7z010clg400pkg.txt を使い、ピン番号からピン名を拾って、ペアにできるピンを探します。
DATA1, DATA2, DATA3 コネクタに割り当てられているピン番号と、ピン名を表にしてみました。
#配線長について
基板で高速差動信号を扱う場合、正(P)、負(N)の配線長をできるだけ揃えないといけないのですが、EBAZ4205 基板の配線長はわかりません。
課題 2-3 では、VGA のピクセルレート 25.175MHz の 10倍で 251.75MHz 程度が、差動信号として出力されます。
この程度の速度であれば、5mm 程度の配線長差なら、まあ問題なく映るはずです。
(雑な計算だと、250 MHz では配線長差が±1.9mmぐらいでスキュー5%に収まる)
#DATA1 コネクタから HDMI 出力を検討
今回は、DATA1 コネクタから HDMI 出力を出したいと思います。
先ほどの表を差動ペア同志で並べ直して、HDMI で必要な信号を割り当ててみました。
#EBAZ4205 回路の確認と基板の改造
回路図によると、FPGA の I/O ピンと DATA1 コネクタの間には、22Ωのダンピング抵抗が挿入されています。
TMDS_33 で使う場合、直列に抵抗が入っていると邪魔なので、取り外して 0Ω に交換します。
必要なところだけ交換するため、表を作成しました。
回路図で R2473A の抵抗は、実際の基板シルクでは R2475 になっていました。
交換する抵抗は、枠で囲ったものです。1005 サイズなので小さいです。
#HDMI 出力の接続図
HDMI 出力コネクタには、aitendo から、HDMI コネクタ with 基板(245円)を調達しました。
https://www.aitendo.com/product/6363
この基板に合わせて、DATA1 コネクタに挿し込むソケットとの接続図を描きました。
コネクタは HDMI ですが、中身は DVI での出力です。
DVI では、DDC で映す信号規格をやり取りしなくても、映りそうなビデオ信号を出せば映してもらるため、SCL/SDA は接続しない事にします。
+5V Power は HDMI SINK 側(受信側)で接続検出に使われるため、電源から供給されている +5V をそのまま接続して供給します。
(DATA1 の電源逆流防止の D21 を外して、直結に変更する必要がある)
#配線作業
DATA1 コネクタに接続できる 2.0mm ピッチのソケットを発注したのですが、先方手違いで 2.54mm ピッチの普通のソケットが来てしまいました。
仕方ないので、とりあえず直結で接続します。
図の番号通りに配線したらこんな感じです。
(2.0mm ソケットが来たら、コネクタ結合式になおします)
#関連ファイルのダウンロード
ソースファイル一式を、FPGAプログラミング大全Xilinx編(第2版) サポートサイトから取ってきます。
https://www.shuwasystem.co.jp/support/7980html/6326.html
XilinxFPGA_SE.zip を解凍して、\Zybo_Z7-10\dai2-3sho\blink フォルダをデスクトップに展開します。
HDMI 出力には Cora_Z7-10 より Zybo_Z7-10 の方がわかりやすいため、こちらを使います。
#制約ファイル(pattern.xdc)の変更
Zybo Z7-10 と EBAZ4205 で、FPGA のピンと、LED やスイッチの接続が違っているため、制約ファイル(pattern.xdc)を変更します。
ポート名に対する FPGA ピンの割り当てを、上の表に合わせて修正します。
変更点は、下記の通りです。
クロック入力
Zybo Z7-10:K17 (SYSCLK 125MHz) → EBAZ4205:N18 (33.333MHz)
Zybo Z7-10:クロック周期 8ns → EBAZ4205:クロック周期 30ns
Zybo Z7-10:クロックH期間 0-4ns(前半波) → EBAZ4205:クロックH期間 0-15ns(前半波)スイッチ入力(RESET)
Zybo Z7-10:Y16 (BTN[3]) → EBAZ4205:V13 (端側)HDMI出力
Zybo Z7-10:HDMI_CLK_N H17 → D20 EBAZ4205
Zybo Z7-10:HDMI_CLK_P H16 → D19 EBAZ4205
Zybo Z7-10:HDMI_N[0] D20 → B20 EBAZ4205
Zybo Z7-10:HDMI_P[0] D19 → C20 EBAZ4205
Zybo Z7-10:HDMI_N[1] B20 → A20 EBAZ4205
Zybo Z7-10:HDMI_P[1] C20 → B19 EBAZ4205
Zybo Z7-10:HDMI_N[2] A20 → H17 EBAZ4205
Zybo Z7-10:HDMI_P[2] B19 → H16 EBAZ4205
# EBAZ4205 constraints file
# chapter: 2
# project: pattern
#Clock signal
set_property -dict { PACKAGE_PIN N18 IOSTANDARD LVCMOS33 } [get_ports { CLK }];
create_clock -add -name sys_clk_pin -period 30.00 -waveform {0 15} [get_ports { CLK }];
#set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_nets CLK_IBUF];
#Reset
set_property -dict { PACKAGE_PIN V13 IOSTANDARD LVCMOS33 } [get_ports { RST }]; # BTN[3]
#HDMI TX
set_property -dict { PACKAGE_PIN D20 IOSTANDARD TMDS_33 } [get_ports { HDMI_CLK_N }];
set_property -dict { PACKAGE_PIN D19 IOSTANDARD TMDS_33 } [get_ports { HDMI_CLK_P }];
set_property -dict { PACKAGE_PIN B20 IOSTANDARD TMDS_33 } [get_ports { HDMI_N[0] }];
set_property -dict { PACKAGE_PIN C20 IOSTANDARD TMDS_33 } [get_ports { HDMI_P[0] }];
set_property -dict { PACKAGE_PIN A20 IOSTANDARD TMDS_33 } [get_ports { HDMI_N[1] }];
set_property -dict { PACKAGE_PIN B19 IOSTANDARD TMDS_33 } [get_ports { HDMI_P[1] }];
set_property -dict { PACKAGE_PIN H17 IOSTANDARD TMDS_33 } [get_ports { HDMI_N[2] }];
set_property -dict { PACKAGE_PIN H16 IOSTANDARD TMDS_33 } [get_ports { HDMI_P[2] }];
set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_nets CLK_IBUF];
のところは、実験環境の Vivado 2018.3 ではコンパイル時にエラーになってしまうため、コメントアウトして通るようにしました。
大全の指定環境である Vivado 2020.1 では、そのままでコンパイルが通るはずです。
#MMCM接続部(pckgen.v)の変更
クロック周波数が 125 MHz → 33.333 MHz になるため、MMCM の周波数設定パラメータ 下記 3 点を変更します。
乗数 M(2.000-64.000) 36.0 → 27.0
CLKIN1 周期 8.0ns → 30.0ns
除数 D(1-106) 5 → 1
CLKOUT 分周数 Q = 35.75 のまま
MMCM 生成周波数は下記となります。
fVCO = fCLKIN x M / D = 33.333 MHz x 27 / 1 = 899.991 MHz
fCLKOUT = fVCO / Q = 899.991 / 35.75 = 25.17457 MHz
/* Copyright(C) 2020 Cobac.Net All Rights Reserved. */
/* chapter: 第2章 */
/* project: pattern */
/* outline: ピクセルクロック生成 */
/* 125MHz入力、25.175MHz出力 */
/* modifyed by KAN573 */
/* 33.333MH入力、25.175MHz出力 */
module pckgen (
input SYSCLK,
output PCK
);
wire CLKFBOUT, iPCK, locked;
BUFG iBUFG (.I(iPCK), .O(PCK));
MMCME2_BASE #(
.BANDWIDTH("OPTIMIZED"), // Jitter programming (OPTIMIZED, HIGH, LOW)
.CLKFBOUT_MULT_F(27.0), // 乗数M(2.000-64.000) 36 → 27 へ変更 by KAN573
.CLKFBOUT_PHASE(0.0), // 位相(-360.000-360.000)
.CLKIN1_PERIOD(30.0), // CLKINの周期 8.0 → 30.0 へ変更 by KAN573
// CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
.CLKOUT1_DIVIDE(1),
.CLKOUT2_DIVIDE(1),
.CLKOUT3_DIVIDE(1),
.CLKOUT4_DIVIDE(1),
.CLKOUT5_DIVIDE(1),
.CLKOUT6_DIVIDE(1),
.CLKOUT0_DIVIDE_F(35.75), // 除数Q(1.000-128.000)
// CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).
.CLKOUT0_DUTY_CYCLE(0.5), // デューティ比
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT5_DUTY_CYCLE(0.5),
.CLKOUT6_DUTY_CYCLE(0.5),
// CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
.CLKOUT0_PHASE(0.0),
.CLKOUT1_PHASE(0.0),
.CLKOUT2_PHASE(0.0),
.CLKOUT3_PHASE(0.0),
.CLKOUT4_PHASE(0.0),
.CLKOUT5_PHASE(0.0),
.CLKOUT6_PHASE(0.0),
.CLKOUT4_CASCADE("FALSE"), // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
.DIVCLK_DIVIDE(1), // 除数D(1-106) 5 → 1 へ変更 by KAN573
.REF_JITTER1(0.0), // Reference input jitter in UI (0.000-0.999).
.STARTUP_WAIT("FALSE") // Delays DONE until MMCM is locked (FALSE, TRUE)
)
(以下略)
#コンパイル
オリジナルと同じですので、大全の手順通りでよいです。
#動作確認
Vivado からダウンロードが完了すると、HDMI 出力に接続したモニタにパターンが表示されます。
同じ .xdc と pckgen.v を適用することで、課題 2-4-2 「グラデーション表示」も動作します。
#まとめ
FPGA プログラミング大全 Xilinx 編 第2版
「課題 2-3 PC用ディスプレイにパターンを表示」について、EBAZ4205 で学習することができました。