FPGA/マイコンでVGA出力をするために
2017/02/04
この資料は、VGA信号をマイコンやFPGAから出力するときに用いるタイミングチャートを記載したものになります。
他の説明記事とは若干異なるので、これだけを読んでもあまり面白くはないと思います…
昨今の液晶工作事情?
マイコンやFPGA/CPLDなんかがかなり自由に扱えるようになってくると、一度は「グラフィック液晶表示」に興味を持つものです。(持つよね?)
最近の液晶工作では、LCDドライバの載った液晶をマイコンからSPI通信で叩いたり、LCDドライバそのものを内蔵したマイコンでグラフィック液晶を叩いたり・・・というのが流行りのようです。 したがって、ドライバが搭載された液晶への信号の流し込み方は、液晶の型番で検索すれば大抵先人が道しるべを立ててくれているので簡単に理解できることが多いです。
しかし、表示用のRAMすらも内蔵していない液晶を叩くのは結構難易度が高いためか、手を出してる人も限られてきますので、初心者にわかりやすい説明が非常に少なくなっています。なんとか資料にたどり着いても「フロントポーチってなんぞや?」「水平表示期間ってなんや?」という疑問が多く湧き、結局どういう信号を液晶に流し込んだら画面が表示されるのかわかりにくくなっていることが多いような気がします。(というか、自分が初心者の頃そうでした
そこで、今回は、PCの液晶接続なんかにも用いられるVGA信号(アナログRGB信号)のタイミングを詳しく解説していくことにしましょう。(640×480ピクセル、60Hzで表示させることを前提とします。)
ちなみに、予め断っておきますが、自分はアナログRGB信号の厳密な規格を存じ上げません(おい)。 FPGAをもちいて下記のタイミングチャートに従い実装を行った結果、手元のディスプレイでは問題なく画面表示ができたことを確認していますが、すべてのデバイスで正しい表示結果が得られるかは確認していませんのであしからず…
VGA信号(アナログRGB信号)
(VGA信号と呼ぶのが正しいのかどうか存じ上げませんが、液晶工作をやっている人の間ではこれで通じるようなので、本稿では「VGA信号」で統一していこうと思います。)
VGA端子はご存知の方も多いでしょうが、下図のような、15ピンからなる台形型の端子を指します。(メスソケットを正面から見たもの)
PCなどにも搭載されているので、大半の人が見たことはあると思います。
今回対象とするのは、この形の端子を持った液晶ディスプレイ(おそらく趣味で扱える液晶の中では非常に大型なものになるのではないでしょうか?)です。
つまり、PC用のディスプレイをマイコンやFPGAから制御するにはどうすれば良いのか、ということにフォーカスを当てて解説していくわけですね。
必要な端子数
マイコンやFPGAからVGA信号を出力し、液晶ディスプレイを表示するには、次の5つの信号を端子に接続しなければなりません。
1番ピン・・・アナログ信号(赤色), 0~0.7Vでピクセルごとの赤色の強さを入力
2番ピン・・・アナログ信号(緑色), 0~0.7Vでピクセルごとの緑色の強さを入力
3番ピン・・・アナログ信号(青色), 0~0.7Vでピクセルごとの青色の強さを入力
13番ピン・・・水平同期信号(HSYNC), ディジタル信号。0V/5VでHIGH/LOWを表す
14番ピン・・・垂直同期信号(VSYNC), 同上
合計5端子。ただし、ご覧のとおり、1~3番のアナログ色強度は、0~0.7Vのアナログ信号を与えることになりますので、マイコンやFPGAなどから扱う際には少々工夫が必要です。(すべての色について、0か1かの2段階8色表示でよければ、そう難しくもありませんが。)
VGA信号のタイミングチャート
水平同期信号
基本的に液晶ディスプレイは、一番左上の点から、1クロック(=25MHz, 40nsec)ごとに1ドットずつ右にずれながら描画していきます。
したがって、FPGA/マイコンは40ナノ秒ごとに、描画する色をR,G,B端子に出力すればよいことになります。(各ピクセルのR,G,Bの強さを0~0.7Vで表す。)
その調子で1番上の行の右端まで来たとき、液晶に「水平同期信号」を入力してやると、改行されて上から2ドット目の行の描画に移ることになります。水平同期信号は、アクティブ・ローの信号なので、改行したいタイミングが来たら決められた時間だけ出力をLOWにします。ポイントはここからです。
液晶ディスプレイに水平同期信号を入れるタイミングや、描画のためのRGB信号を入力するタイミングは厳密に決まっているのです。
下のタイミングチャートをご覧ください。
上の図中のすべての数字の単位は[clk]となります。VGAで640ドット×480ドットを表示する場合、クロック周波数は25MHzですから、1clk=40ナノ秒になります。
図中の「1ライン表示期間640clk」と書かれている期間以外はRGB信号を入力しても無視されます。逆にいうと、この640clkの間に、40ナノ秒あたり1ピクセルずつRGB信号を入力していく必要があります。すると、640クロックで640ドットが入力されますので、RGB信号の出力は終了となります。 その後は「改行」のために、16クロック待機した後(図中の640~656)、96クロックの間水平同期信号をLOWにします(図中の656~752)。 その後は 8クロック 48クロック待機したのち、2行目の描画が始まります(図中右端の0)。 ※コメントにてosawa様よりご指摘を頂きました.水平同期信号のレベルをHighに戻した後の待機時間は800-752=48[clk]です.お詫びして訂正いたします.
したがって、上の図の通り、1行の描画にかかる時間は最終的に800clk=32マイクロ秒となります。(実際にRGB信号を入力しているのは480clk=19.2マイクロ秒ですが)
ちなみに、上の図の通りのタイミングでRGB信号とHSYNCを入力すると、画面の1番上の行の描画内容は次のようになります。(見やすいように縦に引き伸ばしました)
上のタイミングチャートと見比べてみましょう。
垂直同期信号
垂直同期信号は、液晶ディスプレイの一番右端まで描画が終わった後に、表示位置を一番左上に戻すために入力される信号です。
水平同期信号を基準として、垂直同期信号の入力タイミングを表すと、下の図のようになります。(HSYNCは先ほどの図よりかなり横に縮められて見えます。)
流石に縦480行分をすべて書くととんでもないことになりますので、一部省略線を入れさせていただきました。
上の図の横軸の数字の単位はすべてHSYNC信号の回数になります。 左端の(490~492)の位置を見ると、VSYNCがLOWになっている幅は2となっており、じっさいHSYNC信号が2回立ち下がっていることが確認できます。 同様に、その隣の(492~0)の位置も省略されていますが実際は33回HSYNC信号は下がっています。
(どうも、HSYNC信号の立ち下がりの瞬間にVSYNC信号は変化させるのが良い模様。実際この通りに作ったら動いたので、大きくは間違っていないと思われます。)そして、実際にRGB信号が出力されるのは中央の480HSYNCのみなわけですね。(それ以外のHSYNC信号のタイミングではRGB信号が変化していないことに注目。)
以上、かなり適当な説明になってしまいましたが、この資料がこれからVGA出力を試みようと思う人の手助けになれば幸いです。
質問、コメント等あればお気軽にコメント欄へどうぞ。