VGAモジュールの作成
KITEプロセッサのに接続するVGAモジュールを作成します。
VGAモジュールの仕様
- 画面は1280dot x 720lineのHDとする.
- キャラクタを表示するものとし、表示文字数は80x22文字(1,760文字)とする。
- キャラクタの構成は16dot x 32lineとするが,文字フォントはメモリ節約のため16dot x 16lineを使用する。したがって,描画の際には2ラスタ分同じラスタを表示し32lineになるようにする.
- したがって、文字表示画面 dot 構成は 1280dot x 702line となり,残り16ラインは無表示とする。
画面構成、文字構成、KITEにおけるメモリマップの対応を以下に示す。
VGAモジュールのブロック図
VGAモジュールは、主に以下のブロックからなる。
- Video RAM:画面に表示する文字のJIS8ビットコードを保持しておくメモリ。表示文字数は80x22文字であるので、8ビットで1,7600ワードを記憶できる必要がある。メモリ容量としては2進数値できりの良い2,048バイトを準備する.
- Character ROM:キャラクタの文字情報を記憶しておくメモリ。
JIS8ビットコードの場合256文字であるので,1文字の構成が16ドット×32ラインの場合,
16ビット8,192ワード必要となる。今回はメモリ節約のために1文字は16dot×32lineとし,
2ライン分同じラインを重複表示させることとする.
- Shift Register:Char.ROM から読み出した文字のドットデータをドット
クロックに応じてシフトし、シリアルに出力する。
- VGA Controller:Video Memory, Char. ROM, Shift Register の制御および同期
信号の生成を行うモジュールである。内部構成としては、ほとんどがタイ
ミング調整用のカウンタである。
VGA画像表示の考え方
VGAモニタへの画像表示は、通常のテレビと同様にラスタスキャンで表示を行っ
ている。
- 画面の表示は第1ライン(ラスタという)を左から右に向かって逐次的に表示
している。水平のドット構成は1280ドットであるが、実際には表示されてい
ない部分がある。1280x720構成の一般的VGAでは、実際には
1600dot×752line程度で構成される。水平部分の表示されていない期間中に水平同期
信号がモニタに送られており、このタイミングにより次のラスタを表示す
るためのタイミングをモニタは知ることができるようになっている。
同様に、垂直方向についても、表示されていない期間において垂直同期信号が出力される。
- 図に示すように、水平方向および垂直方向のタイミングを取るために、以下のようなカウンタを用意する必要がある。
- CNT : 水平文字ドットカウンタ:0〜15までをカウントする。
- HCNT : 水平文字カウンタ:0〜99までをカウントする。
- RCNT : ラスタカウンタ:文字毎のラスタを0〜15までカウントする
- VCNT : 垂直文字カウンタ:0〜46までをカウントする。
このようにカウンタを用意することにより,実際には16×16ドットのフォント
を使用している場合,80文字×45行の文字の総計3,600文字をHD画面上に表示
することができる.しかしながら,KITE-1プロセッサのメモリ空間が狭く
キャラクタ表示用に2048文字分の領域しか確保できないため,
表示文字は1文字あたり32ラインとし,1文字あたりVCNTは2カウント分使用
している.
この4個のカウンタは以下の様に動作する。
- 1ドットは75MHzの1周期の時間である。水平文字ドットカウンタ(CNT)は
75MHz毎にカウントアップする。
- 水平文字カウンタ(HCNT)は16ドット毎にカウントアップする。つまり、水平
文字ドットカウンタが4'b1111から4'b0000になるときにカウントアップする。
また、99までカウントするので、99の次は0となるようにする。
- ラスタカウンタ(RCNT)は水平文字カウンタ(HCNT)が99から0になる際にカウ
ントアップする。15までカウントするので15の次は0となる。
- 垂直文字カウンタ(VCNT)はラスタカウンタ(RCNT)が15から0になる際にカウ
ントアップする。46までをカウントするので45の次は0となる。
- 水平同期信号は、87文字目から88文字目の間で出力される。
- 垂直同期信号は、46行目で出力される。
これらのカウンタ等を実現するために、以下のような定義をしておくと良いであ
ろう。
`define HMAX 100 // H total Char.
`define HSIZ 80 // H Size
`define HSP 87 // H Sync. Pos.
`define HSL 2 // H Sync. Len.
`define HCR 16 // H dots per Char.
`define VMAX 47 // V total Char.
`define VSIZ 45 // V Size
`define VSP 46 // V Sync. Pos.
`define VSL 1 // V Sync. Len.
`define VCR 16 // V lines per Char.
module vram ( CLK, DCLK, RST, ADDR, DATAI, DATAO, MREQ, RW, ACK, R, G, B, HS, VS, DE );
input ...;
output ...;
...
endmodule
また、カウンタの宣言は以下のとおりとなる。
reg [3:0] CNT;
reg [7:0] HCNT; // H Counter 0-99
reg [6:0] VCNT; // V Counter 0-45
reg [3:0] RCNT; // R Counter 0-15
VideoRAMとChar.ROMのアクセス方法
VGAモニタへの画像表示は、通常のテレビと同様にラスタスキャンで表示を行っている。
- クロックは75MHzが供給されている。
- 図に示すように1文字の横は4.6875MHzとなる。
75MHzをシフトクロック(1ドット分の表示クロック)、
75MHzを16分周した4.6875MHzでデューティ比1/16のクロックをパイプラインレジスタ用のタイミングクロックとする。
出力信号
DVIビデオのR, G, Bの各出力は8ビットで256階調である。
しかし、今回の設計は単色であるので、光らせる場合はR,G,Bともに(FF)、
光らせない場合は(00)を出力する。
HS, VSの同期信号は負論理であるので注意する。
DEは文字を表示させる期間に1とする。
なお、パイプライン動作しているため、
HCNTの値が0~79のときにDEを1にするのではないことに注意する。
サンプルソース
※以下のソースは、第1テーマのビデオコントローラにおいて、プロセッサと
のインタフェース部分以外はほぼ同じ動作をするので、
ここのコードを参考にして構わない。
`define HMAX 100 // H total Char.
`define HSIZ 80 // H Size
`define HSP 87 // H Sync. Pos.
`define HSL 2 // H Sync. Len.
`define HCR 16 // H dots per Char.
`define VMAX 47 // V total Char.
`define VSIZ 45 // V Size
`define VSP 46 // V Sync. Pos.
`define VSL 1 // V Sync. Len.
`define VCR 16 // V lines per Char.
module vram (CLK, DCLK, RST, ADDR, DATAI, DATAO, MREQ, RW, ACK, pDATA, HS, VS, DE);
input CLK, // Processor Clock (75MHz)
DCLK, // Video Clock (75MHz)
RST; // Reset
input [11:0] ADDR; // Video Memory Address
input [ 7:0] DATAI; // Data Input
input MREQ, // Memory Request
RW; // Read/Write
output [ 7:0] DATAO; // Data Output
output ACK; // Acknowledge
output [23:0] pDATA; // RGB Data
output HS, VS, DE; // Sync. & Data Enable
reg [ 7:0] DATAO;
// Memory
reg [..:0] VRAM [0:....]; // 8-bit, 2048word memory
reg [..:0] CGROM[0:....]; // 16-bit, 4096 word ROM
// Counter
reg [..:0] CNT; // Character Counter (16-dot)
reg [..:0] HCNT; // H Counter 0-99
reg [..:0] VCNT; // V Counter 0-46
reg [..:0] RCNT; // R Counter 0-15
wire CEP; // Character End Pulse
// Internal Signals
wire [..:0] VADR; // VideoRAM Address (2048-word)
wire [..:0] CGADR; // CG-ROM Address (4096-word)
wire [..:0] CGDATA; // CG-ROM Font Data Size (16-bit)
// Pipeline Register
reg [..:0] CADR; // Character Code from VRAM (8-bit)
reg [..:0] SR; // Shift Register (16-bit)
// Memory Initialize
initial
begin
$readmemh( "VRAM20.mif", VRAM );
$readmemh( "18x18ja.mif", CGROM );
end
// Video-RAM Write & Read
always @( posedge CLK )
begin
if( ( ADDR[...] == 1'b1 ) && MREQ && ( RW == ... ) )
VRAM[ ...[...:...] ] <= ...;
... <= VRAM[ ...[...:...]];
end
// Video-RAM Acknowledge for Write & Read
assign ACK = ( ( ADDR[...] == 1'b1 ) && ... );
// Counter for Character End Pulse
always @( posedge DCLK )
if( RST ) ... <= ... else
... <= .......;
assign ... = ...; // Character End Pulse
always @( posedge DCLK )
begin
if( ... ) begin ...<=...; ...<=...; ...<=...; end // Reset
if( ... )
begin
if( ... == ... )
begin
... <= ...;
if( ... == ... )
begin
... <= ...;
if( ... == ... ) ... <= ...;
else ... <= ...;
end
else
... <= ......;
end
else
... <= ......;
end
end
// Internal Memory Address
// ・VCNTは文字表示用に 0〜45 まで使用するが、文字フォントは
// 16ドットx16ラインである.16ドットx32ラインの表示にするため
// にはVCNTを1/2の値にしてVADDRを生成する必要がある。
assign VADR = ...[...:...] * 11'd... + ...;
always @( ... )
if( ... )
CADR <= ...[...];
// Generate CG-ROM address from character data in video memory and VCNT, RCNT
// ・CGROMは表示文字コード順に16ワード毎にフォントデータ格納されて
// いる.CGADRは文字コードの下位に16ワード分4ビットのアドレスを付
// 加し、対応する文字フォントの1ライン分のフォントイメージを読み出す.
// この4ビットのアドレスはRCNTを用いるが、表示文字を16ドットx32ラインの
// 表示にするため2ライン分フォントのラインを重複表示させる必要がある.
// したがって,RCNTは1/2にして使用する必要がある.この時1ビット分の
// アドレスが足りなくなるが、これは次のカウンタであるVCNTの最下位ビット
// 用いる必要がある.
assign CGADR = { ..., ...[...], ...[...:...] };
assign CGDATA = ...[ ... ];
// Shift Register
always @( posedge DCLK )
begin
if ( ... ) SR <= ...; else
if ( ... ) SR <= ...; else
SR <= { ..., ... };
end
// RGB pixel Data & Data Enable
assign pDATA = ( ...[...] ) ? 24'hffffff : 24'h000000;
assign DE = ( ( 1 < ... && ... < ... + ... ) && ( ... < ... ) );
//Sync
assign HS = ~( HCNT >= ... && HCNT < (... + ...) );
assign VS = ~( VCNT >= ... && VCNT < (... + ...) );
endmodule
最後に、kite_top階層からは以下の様に呼び出すことになる。
//
// Memory & Video RAM
//
vram mem1 ( .CLK (CLK75),
.DCLK(CLK75),
.RST(RST),
.ADDR(ADR),
.DATAI(DATAO[7:0]),
.DATAO(VRAM_DATAO),
.MREQ(MREQ),
.RW(RW),
.ACK(VRAM_ACK),
.pDATA(pDATA),
.HS(HS),
.VS(VS),
.DE(DE)
);
次は、 DVIエンコーダモジュール を追加します。
| Back |