【音声も送れる!】FPGAからHDMI信号を出力する
FPGAからHDMI信号(音声付きDVI信号)を出力してみた件
Terasic DE0(Intel CycloneIII EP3C16F484搭載)からHDMI信号(音声付きDVI信号)を出力させてみましたので、Quartus Primeのプロジェクトごと公開します。
出力ドライバとしてPure-LVDSではなく、フィッティング制約の少ない擬似LVDS(LVDS_E_3R)を使用しているので、多くのデザインにフィットさせることができるでしょう。
.jpg)
なお、この記事ではSammer Puriさんが作られGithubで公開されているライブラリを含め、以下のページを参考にさせて頂きました。ありがとうありがとう。
| URL | |
|---|---|
| hdl-util/hdmi Sammer Puriさんのライブラリ |
hdl-util/hdmi |
| 廉価FPGAでHDMI(DVI)出力 sa89aさんのサイト |
http://sa89a.net/mp.cgi/ele/fpga_hdmi.htm |
| ついに、Kintex-7で安定したHDMI 1080p出力に成功! なひたふさんのブログ |
http://nahitafu.cocolog-nifty.com/nahitafu/2020/11/post-fc5a2f.html |
仕様など
今回使用した評価ボード、出力信号の仕様などは以下の通りです。
※PLLとシリアライザにIntel固有IPを利用しているため、Intel以外のFPGAに移植する際はこれらを置き換える必要があります。
| 仕様 | |
|---|---|
| 評価ボード | Terasic DE0 (Intel EP3C16F484C6) |
| ツール | QuartusII Web Edition Version 13.1 |
| 画像 | 解像度: 720×480p リフレッシュレート: 59.94Hz 画素クロック: 27MHz |
| 音声 | 解像度: 16bit サンプリングレート: 48KHz チャンネル数: 2(ステレオ) |
| 出力ドライバ | LVDS_E_3R ただしVCCIO=3.3V シリアライザとしてaltlvds_txを使用 |
論理合成結果は以下のようになりました。
Family : Cyclone III
Device : EP3C16F484C6
Timing Models : Final
Total logic elements : 1,120 / 15,408 ( 7 % )
Total combinational functions : 1,064 / 15,408 ( 7 % )
Dedicated logic registers : 416 / 15,408 ( 3 % )
Total registers : 416
Total pins : 18 / 347 ( 5 % )
Total virtual pins : 0
Total memory bits : 0 / 516,096 ( 0 % )
Embedded Multiplier 9-bit elements : 0 / 112 ( 0 % )
Total PLLs : 1 / 4 ( 25 % )
プロジェクト一式はGithubで公開していますのでこちらをどうぞ。
[22.05.03追記] CycloneV(DE0CV)のプロジェクトを追加しました。
| hdmi_demo_tmct | https://github.com/tmct-web/hdmi_demo_tmct |
|---|
再現にあたっての注意
このページを読んで、自分もチャレンジしてみたくなったぞ!! という方のために、注意した方がいいなー…と感じたことを書いておきます。
- ライブラリはSystemVerilogで書かれている
Sammerさんが公開されているライブラリはSystemVerilogで記述されています。
Verilogのニュータイプみたいな言語ですが、VHDLしか使ったことがない人や、「あれ?Verilogって検証用の言語じゃないの??」って思った人には厳しいかもしれません。 - わりと高度な電気的知識が必要
FPGAから出力される信号は720×480pのHDMI信号です。
この信号はピクセルクロックで27MHz・データラインの帯域は最大135MHzにもなり、おそらくDIYでは最高難易度の部類に入ります。
このような帯域の信号を扱う場合、信号の這い回しやGNDの取り方など些細なことまで気を遣わないとマトモに映らないでしょう。 - 必要以上にケーブルを長くしない
映ることがわかるまではケーブル長は50cmくらいまでにしておきましょう。
「ちゃんと繋いだし何も問題ないはずなのに映らない」という状況になってしまうと、非常に高価な計測器を使わない限り原因がわからず詰みます。 - HDMIケーブルの加工は器用さが要求される
HDMIケーブルは5mmほどの太さの中に19本の信号線とシールドが詰め込まれていて、中の線はかなり細いです。
被覆を剥いた芯線は0.1mmくらい。非常に細い線をチマチマとはんだ付けする器用さが要求されます。 - HDMIケーブルはそれなりの物を用意しましょう
SammerさんもGithubのページに書かれている通り、1本100円とかの安いケーブルは使わない方が良いです。
ちょん切って使うので勿体無いのですが、それなりのケーブルを準備しましょう。
私はダ○ソーで「4K対応プレミアムケーブル」とやらを買ってみましたが、各差動ペアのシールドがまったく接続されていませんでした。結局Amazon BasicsのHDMIケーブルを買い直した…(こっちはちゃんと全ピン接続されていた。)
ハードウェアの結線
DE0からの出力は以下のようにできるだけ差動出力が隣になるようアサインしています。
| 信号名 | FPGA Pin |
GPIO 0 Pin |
HDMI-Connector Pin |
Remarks |
|---|---|---|---|---|
| O_TMDS_DATA[2]+ | AA16 | 4 | 1:(TMDS)Data2+ | |
| O_TMDS_DATA[2]- | AB16 | 2 | 3:(TMDS)Data2- | |
| O_TMDS_DATA[1]+ | AA15 | 5 | 4:(TMDS)Data1+ | |
| O_TMDS_DATA[1]- | AB15 | 6 | 6:(TMDS)Data1- | |
| O_TMDS_DATA[0]+ | AA14 | 7 | 7:(TMDS)Data0+ | |
| O_TMDS_DATA[0]- | AB14 | 8 | 9:(TMDS)Data0- | |
| O_TMDS_CLK+ | AA13 | 10 | 10:(TMDS)Clock+ | |
| O_TMDS_CLK- | AB13 | 9 | 12:(TMDS)Clock- | |
| O_AUDIO | V8 | 36 | - | - |
| O_AUDIO_CLK | W6 | 38 | - | 音声サンプリングクロック出力 |
| O_VIDEO_CLK | U7 | 40 | - | 画素クロック出力 |
| O_PLL_LOCKED | J1 | - | - | PLLロック出力 LEDG0に接続されています |
| I_AUDIO_PITCH[3] | G4 | - | - | 音声テストパターン周波数選択 SW3に接続されています |
| I_AUDIO_PITCH[2] | H6 | - | - | 音声テストパターン周波数選択 SW2に接続されています |
| I_AUDIO_PITCH[1] | H5 | - | - | 音声テストパターン周波数選択 SW1に接続されています |
| I_AUDIO_PITCH[0] | J6 | - | - | 音声テストパターン周波数選択 SW0に接続されています |
| I_CLK | G21 | - | - | 50MHzが入力されます 以下はPLLで生成されます: - シリアライザの動作クロック - 画素クロック - 音声サンプリングクロック |
| I_RESET_N | H2 | - | - | BUTTON0に接続されています 押下=リセット |
実際の結線は以下の通り。
DE0に載っているCycloneIIIのI/OセルはHDMIの物理層であるTMDSに対応していないため、LVDS_E_3Rと抵抗・カップリングコンデンサでTMDSドライバをエミュレートしています。抵抗値はsa89aさんのサイトを参考にしていますが、できれば220〜330Ωが良いです。
(※あと今回はVCCIO=3.3Vなのでカップリングコンデンサは無くてもいいです。)
.gif)
HDMIコネクタのピンアサインは以下を参考にどうぞ。
| HDMIピンアサイン | https://ss1.xrea.com/tmct.s1009.xrea.com/ref/ta-xx-7e3m01.html#hdmi |
|---|
+5V,HPD,SCL,SDA,CEC は画像信号ではありませんが、TVやモニタによってはこれらが正しく接続されていないと映像が映らないことがあります。
私がやってみた範囲では、安い中華モニターでは映像信号だけで映りましたがREGZAは全部きちんと繋がないと映りませんでした。
くれぐれも以下のことに気を付けながら配線しましょう。
- 各差動信号の+と-はできるだけツイストする
- ケーブルをばらした部分はできるだけ短くする
- GNDとシールドはしっかり配線する
- 画像信号以外も省略せず配線する
私はユニバーサル基板にピンヘッダをはんだ付けして接続しました。
.jpg)
FPGA論理
論理はGithubからダウンロードしてください。Quartus Prime(QuartusII)のプロジェクトファイルも入っています。
[22.05.03追記] CycloneV(DE0CV)のプロジェクトを追加しました。
| hdmi_demo_tmct | https://github.com/tmct-web/hdmi_demo_tmct |
|---|
ファイル配置は以下の通り。
ボード・FPGAデバイスに固有のものはすべて /boards/terasic_de0/ の下に配置しています。(プロジェクトファイル自体もボード・FPGAデバイスに強く依存するため、このフォルダの下に配置しています。)
| Path | Details |
|---|---|
| /board/terasic_de0/ | Terasic DE0向けのQuartusIIのプロジェクトファイルが含まれる |
| /board/terasic_de0/ip/pll/ | CycloneIII altpll |
| /board/terasic_de0/ip/serializer/ | CycloneIII altlvds_tx |
| /board/terasic_de0/output_files/ | 論理合成出力フォルダ |
| /board/terasic_de0/rtl/ | DE0固有rtl altlvds_txのラッパー(MSB first→LSB first変換含む) |
| /board/terasic_de0/sdc/ | タイミング制約設定 |
| /rtl/ | SammerさんのHDMIライブラリなど - hdmi_test_top.sv … トップレベルエントリ(画像・音声テストパターン生成器含む) - hdmi.sv … HDMIライブラリ本体 ※serializer.svは未使用 |
動作させる
モニタを接続してDE0に論理を転送するとただちに動作を始め、LEDG0が点灯してPLLロックを示します。
モニタにはカラフルなテストパターンが左上にスクロールしていくような画面が表示されるはず。sa89aさんのテストパターンに寄せてみた。
(下の写真はちょっと古いです。Githubに貼ってあるものは画面の四隅に白い枠線が表示されます。)
.jpg)
スイッチやLEDなどのアサインは以下の通り。
| Assign | Details |
|---|---|
| LEDG0 | PLLロック状態 PLLがロックすると点灯します。 |
| BUTTON0 | リセット 押下するとリセット、離すと解除されます。 |
| SW0〜3 | 音声テストパターン周波数変更 いずれかのスイッチをONするとテスト音が出力され、スイッチのパターンを変えると周波数が変わります。 テスト音声の波形は音量小さめののこぎり波です。 |
小難しいこと
映ったぜヒャッホー!!で世は満足な方はここでさようなら。ここから先は小難しいことを書いていきます。
HDMIの物理層
HDMIの物理層はDVIとほぼ同じで、TMDS(Transition Minimized Differential Signaling)という方式が採用されています。
他の多くのWebサイトで言われている通り、CML(Current Mode Logic)に似ているような似てないような絶妙な回路です。
.gif)
送信側(TMDSドライバ)から出力される信号は以下のように規格で決められています。
.gif)
擬似TMDSドライバの実装
これらをどうにかFPGA側に実装すれば良いのですが、先にも書いた通りCycloneIIIのI/OセルはTMDS出力に対応していません。
そこで普通のLVCMOSドライバで差動出力を擬似的に再現するLVDS_E_3Rと抵抗でTMDS出力をエミュレートします。
.gif)
TMDSドライバ側の信号レベルを満足するためには VCCIO=3.3Vの場合 R=220〜330Ω でカップリングコンデンサは不要です。
LVDS_E_3RをCycloneIIIの仕様通りVCCIO=2.5Vで使用する場合はさらにカップリングコンデンサを付けてください。ただしこの場合は送信側のシングルエンド信号要件を満たさなくなるので、映る・映らないはあくまでも受信側の性能に依存することになります。
…が、受信側の要件は差動ラインの電位差が150mV〜1.2Vと幅広く設定されており普通は問題なく映ります。
ただしその場合もシングルエンド信号の最大電圧が4Vを超えてはなりません。(※モニタやTVが破損します)
LVDSを使えばいいじゃない??
FPGAのI/OセルにはLVDS出力(LVDS_E_3Rのような紛い物ではなく本物のLVDSドライバ)があります。
結論から言うと、LVDSとTMDSは仕様が合わないため送信側に要求される仕様を満たしません。
LVDSはCurrent Source=3.5mAに制限されますが、これでは信号振幅が約180mVしか出せないのです。この記事やsa89aさんのサイトでわざわざLVDS_E_3Rを使っているのはそのためです。
受信側要件はギリギリ満たすため多くのモニタでは映る可能性が高いものの、ケーブルをちょっと長くすると映らなくなるなど非常に不安定になるでしょう。
ライセンス的にどうなのか?
Sammerさんのライブラリを使用することでHDMIと互換性のある信号を出力することは可能ですが、あくまでも出力される信号は「音声パケット付きDVI信号」です。
信号仕様はHDMIとDVIは互換性があるのでHDMIモニタでもたまたま映る、というだけ。
HDMIモニタに接続したとき、映る・映らないはモニタ側の性能に強く依存します。
製品化して出荷する場合、互換信号を出力すること自体はライセンスに縛られるものではありませんが、HDMI対応を謳うことはできませんし、HDMI仕様のコネクタを付けることもできません。 大腕振ってHDMI対応を謳うためにはライセンス認証を受けてロイヤリティを支払う必要があります。
このライブラリの機能以外に、少なくとも以下の対応が必要になるでしょう。
- EDIDなどその他の必須機能の実装
- HDMIコンプライアンステストへの合格
- HDMIライセンス料金(ロイヤリティ)の支払い
勝手に製品にHDMIロゴを刻印したり「HDMI対応です!」と謳うことはHDMIのライセンスに違反するだけでなく、他組織の登録商標を勝手に使って商売していることになります。制裁・罰則があるとすると、まずはそこでしょう。
どうせ何もないだろう、とたかを括って製品を出荷していたら秘密裏に調査されていて突然警告通知が来た、ということもあるようです。
くれぐれもライセンス違反には注意して利用しましょう。
.gif)