2023/07/02 Misskeyリンクの追加(内容に変更ありません)
2023/02/11 アクセスカウンタ・アクセス解析タグ入れ替え(内容に変更ありません)
2021/03/11 関連記事リンク追加
2020/09/13 HTMLタグ修正(内容に変更ありません)
2023/02/11 アクセスカウンタ・アクセス解析タグ入れ替え(内容に変更ありません)
2021/03/11 関連記事リンク追加
2020/09/13 HTMLタグ修正(内容に変更ありません)
目次
1. 概要2. パーツ
3. VGAタイミング
4. 回路
5. 製作
6. 実験
7. あとがき
8. 参考にさせていただいたサイト・情報
1. 概要
昔のマイコンはHD6845などのCRTCを用いて、RAMに対して表示するデータを持つアドレスを指示し、同期信号を出力することでテレビ受像機やディスプレイに対して映像を出力することができました。
74HC161を20個ほど手に入れたので、これを贅沢に使って、VGA規格に準拠した、表示アドレスと同期信号を出力する回路(簡易CRTC)を製作しました。
(注:VGAはCGA/EGAモードを含む、640x480x16/320x200x256等の表示モードの規格であり、厳密にはこの回路はVGAのどの表示モードにも対応していません。この回路は表示モードではなく、VGA規格に定められた「同期信号」を生成します。)
(以下、2021/03/11追記)
5年越しに、この回路を使用して、SRAMの内容をディスプレイに表示するための拡張回路を製作しました。
こちらです。
拡張のために、本記事中の回路図にも一部の変更(コネクタの追加)が生じていますが、本記事の回路図には反映していません。
拡張回路の製作記事の回路図を参照してください。
(追記終)
74HC161を20個ほど手に入れたので、これを贅沢に使って、VGA規格に準拠した、表示アドレスと同期信号を出力する回路(簡易CRTC)を製作しました。
(注:VGAはCGA/EGAモードを含む、640x480x16/320x200x256等の表示モードの規格であり、厳密にはこの回路はVGAのどの表示モードにも対応していません。この回路は表示モードではなく、VGA規格に定められた「同期信号」を生成します。)
(以下、2021/03/11追記)
5年越しに、この回路を使用して、SRAMの内容をディスプレイに表示するための拡張回路を製作しました。
こちらです。
拡張のために、本記事中の回路図にも一部の変更(コネクタの追加)が生じていますが、本記事の回路図には反映していません。
拡張回路の製作記事の回路図を参照してください。
(追記終)
2. パーツ
- ICパターンユニバーサル基板(サンハヤト CPU-131)
- ICソケット(8pin x1 14pin x3 16pin x10(←!))
- ピンヘッダ(たくさん(数えてません^^;))
- 0.1uF 積層セラミックコンデンサ x13(パスコン)
- 抵抗 10kΩx2
- 水晶発振器 25.0000MHz
- 74HC00 x2
- 74HC138 x1
- 74HC161 x9(←!)
今回は「ワイヤラッピング」を用いて配線しました。そのため、ラッピングポスト代わりにピンヘッダを大量に使っています。
ICパターン基板を用いることで半田付けはパーツの実装だけで済みます。
ICパターン基板を用いることで半田付けはパーツの実装だけで済みます。
3. VGAタイミング
VGAは、色信号がVGAの色信号は0V-0.7Vのアナログ信号、同期信号が0V-5VのTTLレベルデジタル信号(負論理)です。
VGA(Video Grid Array)のタイミングの規格は次のように定められています。
これだけならただ分周すればいいだけ(25.175MHz/800=31.469kHz 31.469kHz/525=59.94Hz)なのですが、そう簡単にはいきません。
水平同期、垂直同期共に、水平同期信号・垂直同期信号の前後にマージン(フロント・バックポーチ)が存在しています。
これはディスプレイの走査ビームが画面の右端まで行ったあと、次の走査を開始するために左端へ戻すための時間です。
このマージンを生成するためにはただ分周するだけでなく、それらのタイミングを加えて、定められた規格の時間を順次カウントする必要があります。
タイミングは次のようになっています。
(図では垂直同期、垂直フロント・バックポーチの期間に水平同期が無いように見えますが、この期間も実際には水平同期信号は出力されています。)
このように、同期信号を入れる前に少しだけ待って、同期信号を決められた時間だけ入れ、その後に、決められた時間を待ってから次のラインのデータを送ることで、画面を表示します。
同期信号と言っても簡単で、ただその時間(赤で示した部分)に、VGAのHSYNC(水平同期)、VSYNC(垂直同期)の信号をLにするだけです。
その区間(ブランク区間)では、VGAのRGB信号を0Vにします。
従って、生成が必要な信号は次の通りになります。
加えて、RAMに指示するためのアドレス線が出力されます。
(今回はRAM周辺の実装はしていません。RAMは垂直パックドピクセル方式を用いようとしたのですが、うっかりマルチプレクサを買い忘れてしまったので先送りです(_ _;))
VGA(Video Grid Array)のタイミングの規格は次のように定められています。
画素周波数 | 25.175MHz |
水平同期周波数 | 31.469kHz |
垂直同期周波数 | 59.94Hz |
これだけならただ分周すればいいだけ(25.175MHz/800=31.469kHz 31.469kHz/525=59.94Hz)なのですが、そう簡単にはいきません。
水平同期、垂直同期共に、水平同期信号・垂直同期信号の前後にマージン(フロント・バックポーチ)が存在しています。
これはディスプレイの走査ビームが画面の右端まで行ったあと、次の走査を開始するために左端へ戻すための時間です。
このマージンを生成するためにはただ分周するだけでなく、それらのタイミングを加えて、定められた規格の時間を順次カウントする必要があります。
タイミングは次のようになっています。
(図では垂直同期、垂直フロント・バックポーチの期間に水平同期が無いように見えますが、この期間も実際には水平同期信号は出力されています。)
このように、同期信号を入れる前に少しだけ待って、同期信号を決められた時間だけ入れ、その後に、決められた時間を待ってから次のラインのデータを送ることで、画面を表示します。
同期信号と言っても簡単で、ただその時間(赤で示した部分)に、VGAのHSYNC(水平同期)、VSYNC(垂直同期)の信号をLにするだけです。
その区間(ブランク区間)では、VGAのRGB信号を0Vにします。
従って、生成が必要な信号は次の通りになります。
水平同期信号 | 31.469kHz | 3.813us(96pixels相当の時間)だけL |
垂直同期信号 | 59.94Hz | 63.56us(2lines=1600pixels相当の時間)だけL |
ブランク信号 | ---- | フロントポーチ開始〜バックポーチ終了までアクティブ |
加えて、RAMに指示するためのアドレス線が出力されます。
(今回はRAM周辺の実装はしていません。RAMは垂直パックドピクセル方式を用いようとしたのですが、うっかりマルチプレクサを買い忘れてしまったので先送りです(_ _;))
4. 回路
回路はがたろう氏(@duo6750)が公開されている「RETROF-VGA」の記述を参考にして設計しました。(特にカウンタのプリセット周り)
発振器は25.175MHzというぴったりのものが入手できなかったので25.0000MHzのものを使用しています。175kHz分は誤差ということにします(^^;
水平同期周波数は25000/800=31.25kHz、垂直同期周波数は31.25/526=59.41Hzとなる計算です。(526の理由は後述)
本来VGAは640x480(全エリア800x525)ですが、ピクセルあたりの時間が40ns(25MHz)となり、RAMがついていきません。(アクセスタイムが55ns or 100nsのRAMしか持ってないのです)
そのため、74HC74でピクセル周波数とラインを2分周して320x240にしています。これでピクセルあたりの時間が80ns(12.5MHz)となり、55nsのRAMでギリギリついていきます。
さらに、RAMに対するアドレスを出力する際、320x240では、320が8bitを僅かに超えるため、RAMのアドレス管理が面倒になります。
そのため、さらに解像度を減らして256x192にしています。240の方は8bitでも管理できるのですが、アスペクト比が崩れるので道連れです。
(以上の理由により、以下、ピクセル・ラインの数値は半分の表記になっています。)
同期カウンタ74HC161を使って信号を作る時間をカウントしています。同期ロードを用いて、タイミングが生成しやすいように初期値を決定しています。
カウンタは担当する信号で4つの部分に分かれています。
HSYNC部では水平同期信号・水平ブランク信号(水平フロント・バックポーチ)を生成しています。
上の図ではバックポーチのみが表示エリアの前にありますが、フロントポーチから水平同期信号も表示エリアの前に持ってきています。順序があっていれば実質的には同じです。
フロントポーチ・水平同期信号・バックポーチのピクセル数はすべて8の倍数なので、1段目で8カウントし、2段目で、1,6,3回カウントしています。
そして、2段目のカウント出力のQB-QDを74HC138に通し、~Y3-~Y5(カウント値6-11に相当)負論理OR(=AND)を取ることで水平同期信号を生成しています。
また、ブランク区間でないときは2段目のCOがHになっている(カウント値が15になるとHSYNC部のカウンタが止まりブランク区間が終了する)ので、これを水平ブランク信号(Lでブランク)としています。
HLINE部ではピクセルのアドレスを出力しています。
前述のとおり、水平方向のピクセル数は256pxなので、256〜319ピクセルはフロントポーチに負論理ORで統合しています。256〜320では3段目のQAがLになっているので、これを用います。
VLINE部ではラインのアドレスを出力し、垂直ブランク信号を生成しています。
フロントポーチ・水平同期信号を前に持ってきているため、表示区間の終了を以って1ラインが終了します。したがって、HLINEが320をカウントした時点で74HC74にクロックを入れています。
実際には、320をカウントした次のクロック(321を数えるクロック)で74HC74にクロックが入るため、1クロック分ずれますが、この時はすでに水平フロントポーチで信号は出ていないので、影響ありません。
ここでは240をカウントしますが、やはり実際には192〜239はフロントポーチに統合しています。
VLINEのカウンタは、240をカウントした時点でカウントが停止し、バックポーチの終了を以ってカウンタがリセットされるため、192のカウント値がそのまま垂直ブランク信号となります。
ありがたいことに、192は2進数表記で11000000なのでQCとQDをANDするだけで垂直ブランク信号が作れます。
VSYNC部では、垂直同期信号・垂直フロント・バックポーチを生成しています。
こちらは、垂直バックポーチを後ろに持ってきています。やはり実質的には同じです。
1段目で6カウントし、最後の1カウント分を垂直同期信号としています。その後、1段目は16カウントしてバックポーチを作り出します。
元々の規格ではバックポーチは33ラインですが、ラインを2分周してカウントしているためという奇数はカウントできません。したがって、ここだけは規格からズレて34ライン分(16カウント+ロード1カウント)しています。
実画面上のライン数も1増えて、526になります。
以上のカウンタの塊によってすべての信号を作っています。
HLINEとVSYNCの最終段がすこし勿体ない使い方にも見えますが、同期ロード・イネーブル付きのFFを探すよりはこっちのほうが楽です。
発振器は25.175MHzというぴったりのものが入手できなかったので25.0000MHzのものを使用しています。175kHz分は誤差ということにします(^^;
水平同期周波数は25000/800=31.25kHz、垂直同期周波数は31.25/526=59.41Hzとなる計算です。(526の理由は後述)
本来VGAは640x480(全エリア800x525)ですが、ピクセルあたりの時間が40ns(25MHz)となり、RAMがついていきません。(アクセスタイムが55ns or 100nsのRAMしか持ってないのです)
そのため、74HC74でピクセル周波数とラインを2分周して320x240にしています。これでピクセルあたりの時間が80ns(12.5MHz)となり、55nsのRAMでギリギリついていきます。
さらに、RAMに対するアドレスを出力する際、320x240では、320が8bitを僅かに超えるため、RAMのアドレス管理が面倒になります。
そのため、さらに解像度を減らして256x192にしています。240の方は8bitでも管理できるのですが、アスペクト比が崩れるので道連れです。
(以上の理由により、以下、ピクセル・ラインの数値は半分の表記になっています。)
同期カウンタ74HC161を使って信号を作る時間をカウントしています。同期ロードを用いて、タイミングが生成しやすいように初期値を決定しています。
カウンタは担当する信号で4つの部分に分かれています。
HSYNC部では水平同期信号・水平ブランク信号(水平フロント・バックポーチ)を生成しています。
上の図ではバックポーチのみが表示エリアの前にありますが、フロントポーチから水平同期信号も表示エリアの前に持ってきています。順序があっていれば実質的には同じです。
フロントポーチ・水平同期信号・バックポーチのピクセル数はすべて8の倍数なので、1段目で8カウントし、2段目で、1,6,3回カウントしています。
そして、2段目のカウント出力のQB-QDを74HC138に通し、~Y3-~Y5(カウント値6-11に相当)負論理OR(=AND)を取ることで水平同期信号を生成しています。
また、ブランク区間でないときは2段目のCOがHになっている(カウント値が15になるとHSYNC部のカウンタが止まりブランク区間が終了する)ので、これを水平ブランク信号(Lでブランク)としています。
HLINE部ではピクセルのアドレスを出力しています。
前述のとおり、水平方向のピクセル数は256pxなので、256〜319ピクセルはフロントポーチに負論理ORで統合しています。256〜320では3段目のQAがLになっているので、これを用います。
VLINE部ではラインのアドレスを出力し、垂直ブランク信号を生成しています。
フロントポーチ・水平同期信号を前に持ってきているため、表示区間の終了を以って1ラインが終了します。したがって、HLINEが320をカウントした時点で74HC74にクロックを入れています。
実際には、320をカウントした次のクロック(321を数えるクロック)で74HC74にクロックが入るため、1クロック分ずれますが、この時はすでに水平フロントポーチで信号は出ていないので、影響ありません。
ここでは240をカウントしますが、やはり実際には192〜239はフロントポーチに統合しています。
VLINEのカウンタは、240をカウントした時点でカウントが停止し、バックポーチの終了を以ってカウンタがリセットされるため、192のカウント値がそのまま垂直ブランク信号となります。
ありがたいことに、192は2進数表記で11000000なのでQCとQDをANDするだけで垂直ブランク信号が作れます。
VSYNC部では、垂直同期信号・垂直フロント・バックポーチを生成しています。
こちらは、垂直バックポーチを後ろに持ってきています。やはり実質的には同じです。
1段目で6カウントし、最後の1カウント分を垂直同期信号としています。その後、1段目は16カウントしてバックポーチを作り出します。
元々の規格ではバックポーチは33ラインですが、ラインを2分周してカウントしているためという奇数はカウントできません。したがって、ここだけは規格からズレて34ライン分(16カウント+ロード1カウント)しています。
実画面上のライン数も1増えて、526になります。
以上のカウンタの塊によってすべての信号を作っています。
HLINEとVSYNCの最終段がすこし勿体ない使い方にも見えますが、同期ロード・イネーブル付きのFFを探すよりはこっちのほうが楽です。
5. 製作
製作にはサンハヤトのICパターン基板CPU-131を用いました。(これが一番高い)
ICソケットとパスコンをこのパターンに沿って実装し、ICの電源ラインのみをはんだ付けします。
そして、ICソケットに合わせてピンヘッダを実装します。今回は11.6mmと17mmのものを使用しました。
配線は0.26mm径(AWG30)のETFE線を用いました。ただし、今回ははんだ付けではなくワイヤラッピングで配線しました。
ピンヘッダにワイヤラッピングツールを用いてETFE線を巻き付けて配線します。巻き付けというと小学生の工作みたいに接触不良頻発が思い浮かびますが、ちゃんとした器具を使って操作すればこれでもしっかり導通します。
すべての配線が終わったら、テスターで導通・絶縁をチェックしてICをソケットにはめ込みます。
最終的に次のようになりました。
(左:表面 盛りソバ^^; 右:裏面 スッキリ)
信号線はなるべく分枝せず、一直線上にのるように配線します。
これもUEWだと途中にハンダゴテを当てて被覆を融かす必要がありますが、ワイヤラッピングだとただ順に巻き付けるだけなのですごくラクです。
ICソケットとパスコンをこのパターンに沿って実装し、ICの電源ラインのみをはんだ付けします。
そして、ICソケットに合わせてピンヘッダを実装します。今回は11.6mmと17mmのものを使用しました。
配線は0.26mm径(AWG30)のETFE線を用いました。ただし、今回ははんだ付けではなくワイヤラッピングで配線しました。
ピンヘッダにワイヤラッピングツールを用いてETFE線を巻き付けて配線します。巻き付けというと小学生の工作みたいに接触不良頻発が思い浮かびますが、ちゃんとした器具を使って操作すればこれでもしっかり導通します。
すべての配線が終わったら、テスターで導通・絶縁をチェックしてICをソケットにはめ込みます。
最終的に次のようになりました。
(左:表面 盛りソバ^^; 右:裏面 スッキリ)
信号線はなるべく分枝せず、一直線上にのるように配線します。
これもUEWだと途中にハンダゴテを当てて被覆を融かす必要がありますが、ワイヤラッピングだとただ順に巻き付けるだけなのですごくラクです。
6. 実験
まずは、信号がちゃんと出ているか検証です。
オシロスコープとかいう超高価な器具は持っていないので、九工大のArduino簡易オシロでチェックです。
(左:水平同期信号 右:垂直同期信号)
計算通りの周波数で大丈夫そうなので、ディスプレイに接続して実験です。
前述のとおりRAM周辺やマルチプレクサがないので、せっかく作ったブランク信号はパスです。
水平同期信号(HSYNC)と垂直同期信号(VSYNC)をディスプレイのVGA端子の13・14ピンに接続し、適当なピクセルアドレスとラインアドレスのビットを470Ωの抵抗を介してそれぞれ2・3ピン(GreenとBlue)に接続します。
D-Subミニ15pinのソケットを持っていないのでケーブルに直接ワイヤラッピングで接続します(^^;
当然GNDも接続しますが、面倒なのでフレームにつなぎました。(^^;;;;
使用したディスプレイはacerのV173です。
(クリックで拡大)
静止画なので分かりませんが、実際にはブレもなくしっかり表示されています。ブランク信号を省略していますが一応フロントポーチとバックポーチの時間は、接続したピクセルアドレス・ラインアドレスのビットがLになっているので同等のようです。
オシロスコープとかいう超高価な器具は持っていないので、九工大のArduino簡易オシロでチェックです。
(左:水平同期信号 右:垂直同期信号)
計算通りの周波数で大丈夫そうなので、ディスプレイに接続して実験です。
前述のとおりRAM周辺やマルチプレクサがないので、せっかく作ったブランク信号はパスです。
水平同期信号(HSYNC)と垂直同期信号(VSYNC)をディスプレイのVGA端子の13・14ピンに接続し、適当なピクセルアドレスとラインアドレスのビットを470Ωの抵抗を介してそれぞれ2・3ピン(GreenとBlue)に接続します。
D-Subミニ15pinのソケットを持っていないのでケーブルに直接ワイヤラッピングで接続します(^^;
当然GNDも接続しますが、面倒なのでフレームにつなぎました。(^^;;;;
使用したディスプレイはacerのV173です。
(クリックで拡大)
静止画なので分かりませんが、実際にはブレもなくしっかり表示されています。ブランク信号を省略していますが一応フロントポーチとバックポーチの時間は、接続したピクセルアドレス・ラインアドレスのビットがLになっているので同等のようです。
7. あとがき
今回はワイヤラッピングに初挑戦しました。ワイヤラッピングは熱源を使用しないので、中断・再開がはんだ付けよりも簡単で、火事に気を払う必要もないため、空いた時間や片手間でサクサクと配線ができました。
配線量が多い回路だったのでピッタリだったとおもいます。
むしろ、この17mmピンヘッダのはんだ付けが大変でした。実は17mmピンヘッダは中華から買ったものだったのですが、はんだが全然乗らず(国内で買った11.6mmはスッと乗る)、フラックスを大量に塗ってなんとかはんだ付けできました。
ワイヤラッピングの仕方を工夫することで11.6mmでも足りるようにして11.6mmを使った方がよかったと思います。
今回の回路を設計する際に大いに参考にさせていただいた、がたろう氏のVGA回路はTTLを用いていたため、パッと見の回路図は配線が少なく見えたのですが、自分が製作した回路はCMOSを用いたため、入力ピンをすべて処理しなければならず、意外と配線量が増えました。
それにしても、どの部品よりも高いのが(もしかしたら合計より高いかも?)基板だなんて・・・(_ _;)
8. 参考にさせていただいたサイト・情報
上へ
戻る