VHDL上のテキストVGAモジュール

この記事では、VHDLで記述されたVGAテキストモジュールを紹介します。 このモジュールは、ボードのデバッグ時に役立ち、比較的小さなスペースしか占有しません。



一般的な特徴



モジュールは、50 MHzのクロック周波数で動作します。

60Hzの周波数で640x480の解像度の画像を生成します。

文字サイズは8x16ピクセルです。 画面には80x25文字があります。

32色のパレット。



FPGAで占有されるリソース:







実装





モジュールのインターフェイスには、クロックジェネレーターの入力(clk)、VGAコネクターへの出力(r、g、b、vsync、hsync)およびプロセッサーバスへの出力(addr、data、iowr、dout)が含まれます。 私が使用したボードには、3色(各色に1つ)の8ビットDACがあるため、モジュールからの8ビットラインは色付きです。 最も重要な色を使用して、DACのないボード用の作業バージョンを取得します。







エンティティ vga_text は

ポート ( clk : STD_LOGIC ;

iowr : STD_LOGIC ;

addr : STD_LOGIC_VECTOR ( 31 downto 0 ) ;

データ: STD_LOGIC_VECTOR ( 31 downto 0 ) ;

dout : out std_logic_vector ( 31 downto 0 ) ;

r : STD_LOGIC_VECTOR ( 7 downto 0 ) ;

g : STD_LOGIC_VECTOR ( 7 downto 0 ) ;

b : STD_LOGIC_VECTOR ( 7 downto 0 ) ;

vga_blank : STD_LOGIC ;

vsync : STD_LOGIC ;

hsync : out STD_LOGIC ) ;

vga_textを終了します。




モニターには3つの同期信号と3つのカラー信号が必要です。 同期信号を生成するには、VCounterおよびHCounterカウンターが使用されます。 同期信号は、図に示されている瞬間に発行されます。







カウンターコード:

アーキテクチャ vga_textの動作は



シグナル VCounter : 整数 範囲 0 から 520 := 0 ;

シグナル HCounter : 整数 範囲 0 から 800 := 0 ;

signal div : std_logic := ' 0 ' ;



始める



プロセス ( clk )

始める

rising_edge ( clk )の 場合

div <= not ( div ) ;

div = ' 1 'の場合

HCounter = 799の 場合

HCounter <= 0 ;

VCounter = 520の 場合

VCounter <= 0 ;

他に

VCounter <= VCounter + 1 ;

終了する 場合 ;

他に

HCounter <= HCounter + 1 ;

終了する 場合 ;

終了する 場合 ;

終了する 場合 ;

終了 プロセス ;



ビヘイビア;


同期信号の生成:

VSync <= ' 0 ' VCounter < 2 else ' 1 'の場合;

hsync <= ' 0 ' HCounter < 96 else ' 1 'の場合;

vga_blank <= ' 1 ' when ( ( HCounter > 143 ) and ( HCounter < 784 ) and

( VCounter > 30 ) および ( VCounter < 511 ) ) else ' 0 ' ;


1文字のサイズは8x16ピクセルです。 文字配列には、それぞれ128ビットの256個のセルがあります。 各ビットは、現在の位置にポイントがあるかどうかを担当します。 メモリセル内のポイントの位置:









FPGAには、1024x18ビット(18432ビット)のブロックメモリ構成があり、これに焦点を合わせます。 CADは、このようなメモリブロックを使用して、選択したほぼすべての構成を自動的に実装します。 したがって、文字メモリには256x128ビット= 32768ビットのメモリが必要です。これには2つのメモリブロック(BRAM)が必要です。

シンボルメモリは設計中に初期化され、動作中に変更できます。



もう1つの必要なメモリは、画面(可視領域)メモリです。 このメモリでは、シンボル番号、シンボルの色、および背景色をエンコードします。 カラーメモリを保存するには、パレットで数値をエンコードします。 18ビットのセルを持つメモリの構成に基づいて、シンボル番号に8ビット、シンボル色に5ビット、背景色に5ビットを割り当てます。 パレットの下では、32個のセルにそれぞれ24ビットが割り当てられています(色ごとに8ビット)。









文字の解像度とサイズに基づいて、80x30文字が画面に収まります。 ただし、これにはメモリ内で2,400セル(3メモリブロック)が必要です。 最初から、このモジュールの最小サイズのタスクが設定されていたため、5つのボトムラインがカットされました。 その結果、表示される文字は80x25になり、2000個のメモリセル(2個のメモリブロック)を占有します。



文字メモリはコアジェネレータで生成されます。 モジュールへのメモリ接続は次のとおりです。

シグナル SAddrA : std_logic_vector ( 7 downto 0 ) ;

signal SAddrRead、SAddrWrite : 0 から 255の 整数 範囲 。

信号 SDataA、SDinA : std_logic_vector ( 127 downto 0 ) ;

信号 SWeA : std_logic ;

-...

コンポーネント vga640_symbols

ポート (

addr : IN std_logic_VECTOR ( 7 downto 0 ) ;

clk : std_logicで ;

din : IN std_logic_VECTOR ( 127 downto 0 ) ;

dout : OUT std_logic_VECTOR ( 127 downto 0 ) ;

we : IN std_logic ) ;

終了 コンポーネント 。

-...

始める

-...

vga640_symbols_0 : vga640_symbols

ポート マップ (

addr => SAddrA、

clk => clk、

din => NewSymbol、

dout => SDataA、

we => SWeA

) ;

SWeA <= ' 1 ' when ( isLowLevel = ' 1 ' ) and ( conv_integer ( addr ) = 337 and iowr = ' 1 ' ) else ' 0 ' ;

SAddrA <= conv_std_logic_vector ( SAddrWrite、 8 ) when ( isLowLevel = ' 1 ' ) および ( conv_integer ( addr ) = 337 and iowr = ' 1 ' ) else conv_std_logic_vector ( SAddrRead、 8 ) ;




画面メモリは、定型コードを記述することで作成されます(ただし、文字メモリの場合と同じことができます)。

タイプ TScreen は std_logic_vector ( 17 downto 0 )の配列( 0〜1999 ) です。

シグナル画面: TScreen ;

信号 scrAddrA、scrAddrB : 0 から 1999の 整数 範囲 ;

シグナル scrDataA、scrDataB、scrDinB : std_logic_vector ( 17 downto 0 ) ;

信号 scrWeB : std_logic ;

-...

始める

-...

プロセス ( clk )

始める

rising_edge ( clk )の 場合

scrWeB = ' 1 'の場合

スクリーン( scrAddrB ) <= scrDinB ;

終了する 場合 ;

scrDataA <= Screen ( scrAddrA ) ;

scrDataB <= Screen ( scrAddrB ) ;

終了する 場合 ;

終了 プロセス ;



scrDinB <= scrDinBLowLevel isLowLevel = ' 1 'の場合else scrDinBNormal ;

scrWeb <= scrWeBLowLevel isLowLevel = ' 1 'の場合、またはscrWebNormal ;

isrLevel = ' 1 'の場合は scrAddrB <= scrAddrBLowLevel 、そうでない場合は scrAddrBNormal 。



scrDinBLowLevel <= data ( 17 downto 0 ) ;

scrWeBLowLevel <= ' 1 ' when ( conv_integer ( addr ) = 300 または conv_integer ( addr ) = 309 ) および iowr = ' 1 ' else ' 0 ' ;



scrAddrBNormal <= GotoY * 80 + GotoX ;

scrDiNBNormal <= BgColor&Color&data ( 7 downto 0 ) ;

scrWebNormal <= ' 1 ' conv_integer ( addr ) = 306 および iowr = ' 1 ' else ' 0 'の場合;




また、パレットのカラーテーブルを設定する必要があります。これは次のとおりです。

タイプ TColor は 、 std_logic_vector ( 23 downto 0 )の配列( 0〜31 ) です。

信号 PalleteColor : TColor :=

(

0 => x "000000" 、

1 => x "0000FF" 、

2 => x "00FF00" 、

3 => x "00FFFF" 、

4 => x "FF0000" 、

5 => x "FF00FF" 、

6 => x "FFFF00" 、

7 => x "FFFFFF" 、

その他 => x "FFFFFF"

) ;

シグナル PalleteAddr : 整数 範囲 0〜31 。




必要なすべてのメモリが形成され、画面に表示するピクセルの準備の実装を開始できます。

現在のFPGAデザインの傾向は、完全同期デザインを意味します。 これらのトレンドから逸脱することはなく、次のピクセルを準備するためのパイプラインを実装します。 入力には、画面上の現在の位置を決定するHCountカウンターとVCountカウンターがあり、出力には、表示されるピクセルの色があります。



コンベアステージ:

  1. 画面の表示部分の位置を決定するscrX、scrY信号の計算。
  2. 必要なシンボルを使用して画面メモリ内のセルを定義する信号の計算

    textX = scrX / 8

    textY = scrY / 16

    文字に必要なピクセルを決定する信号の計算

    SymbolX = scrX mod 8-1

    SymbolY = scrY mod 16

    modは除算の残りです。
  3. 信号X、Yのアドレスの計算。
  4. 現在のキャラクターを取得します。
  5. 現在のピクセルと色の構成を取得します。


プロセス ( clk )

始める

rising_edge ( clk )の 場合

div = ' 1 'の場合

-1

scrX <= conv_std_logic_vector ( HCounter-139、10 ) ;

scrY <= conv_std_logic_vector ( VCounter-70、10 ) ;



-2

textX <= conv_integer ( scrX ( 9 downto 3 ) ) ;

textY <= conv_integer ( scrY ( 9 downto 4 ) ) ;

SymbolX <= scrX ( 2 downto 0 ) -1 ;

SymbolY <= scrY ( 3 downto 0 ) ;



-3

scrAddrA <= textY * 80 + textX ;

SymbolPoint <= conv_integer ( SymbolY ) * 8 + 7 -conv_integer ( SymbolX ) ;



-4

SAddrRead <= conv_integer ( scrDataA ( 7 downto 0 ) ) ;

scrData <= scrDataA ;



-5

( VCounter > 69 ) および ( VCounter < 470 )の 場合

SDataA ( SymbolPoint ) = ' 1 'の場合

curColor <= PalleteColor ( conv_integer ( scrData ( 12 downto 8 ) ) ) ;

他に

curColor <= PalleteColor ( conv_integer ( scrData ( 17 downto 13 ) ) )) ;

終了する 場合 ;

他に

curColor <= x "000000" ;

終了する 場合 ;

終了する 場合 ;

終了する 場合 ;

終了 プロセス 。



b <= curColor ( 23 downto 16 ) when ( vga_blank = ' 1 ' ) else "00000000" ;

g <= curColor ( 15 downto 8 ) when ( vga_blank = ' 1 ' ) else "00000000" ;

r <= curColor ( 7 downto 0 ) when ( vga_blank = ' 1 ' ) else "00000000" ;




インターフェイスを備えたバスを介してモジュールを操作します





バスは、同じFPGAに実装されたフォートプロセッサによって制御されます。 OUTPORTコマンドで、Addr、Data行が設定され、Iowr行が「1」行に上昇します。 INPORTコマンドで、プロセッサはAddr行を設定し、Dout行からデータを収集します。

バスの使用例:

プロセス ( clk )

始める

rising_edge ( clk )の 場合

-カーソルを位置Xに設定(GOTOX)

conv_integer ( addr ) = 302 および iowr = ' 1 'の場合

conv_integer ( data ) > 79の 場合

GotoX <= 0 ;

他に

GotoX <= conv_integer (データ) ;

終了する 場合 ;

終了する 場合 ;



-カーソルを位置Yに設定(GOTOY)

conv_integer ( addr ) = 303 および iowr = ' 1 'の場合

conv_integer ( data ) > 24の 場合

GotoY <= 0 ;

他に

GotoY <= conv_integer (データ) ;

終了する 場合 ;

終了する 場合 ;

終了する 場合 ;

終了 プロセス 。




同様に、モジュールを操作するためのコマンドのほとんどが実装されています。



モジュールの完全なリストはこちらから入手できます。

モジュールリスト

文字メモリを初期化するには



UPD:

基本機能

300-画面メモリへの書き込み/読み取り

301-画面メモリに書き込むためのアドレス



302-キャリッジのX座標を設定します(GotoX)

303-キャリッジ座標の設定(GotoY)

304-文字色の設定(SetColor)

305-背景色の設定(SetBgColor)

306-文字出力とキャリッジ移動(EMIT)

307-切り替えモード

1-低レベルモード。 ダイレクトメモリ操作に使用可能な300、301の機能

0-通常モード。 機能306は、特定の色の文字を特定の位置に設定し、キャリッジを移動するために使用できます。

308-CR

309-VGA_SetData(A ++)



カーソルオプション

310-カーソルパラメータを設定します。

0ビット-カーソルの下のバー

1ビット-黒い四角

2ビット-フリッカー

3ビット-垂直ストリップ

311-カーソルパラメータのビット番号0の設定

...

314-カーソルパラメータのビット番号3の設定



320-カーソルの色の設定

321-カーソルの点滅時間の設定

322-カーソルの書き込み時間の設定



パレットを操作する

330-カラーパレットのアドレスの設定

331-設定されたアドレスでの記録色



シンボルテーブルを使用する

335-文字テーブルでのアドレスの設定

337-指定されたアドレスでNewSymbolを記録する

340-NewSymbol信号の下位32ビットの設定(NewSymbol(31:0))

341-NewSymbolの次の32ビットの設定(63:32)

342-NewSymbol(95:64)

343-NewSymbol(127:96)



ご清聴ありがとうございました。



All Articles