Graphic Controlerの再設計
引き続き、従来設計ではVerilogで設計していたものを勉強の目的からBSVに置き換えます。Graphic ControllerはVRAMへアドレスを出力し、VRAMデータを読み出し、また水平同期、垂直同期、表示期間等のタイミング信号を作成するモジュールです。
ついでにSVGAのタイミング変更をします。SVGAタイミング(魚拓)によれば、SVGA Signal 800 x 600 @ 75 Hz timingは以下のとおり。
 | Screen refresh rate | 75 Hz | 
 | Vertical refresh | 46.875 kHz | 
 | Pixel freq. | 49.5 MHz | 
ここで、Screen refresh rateは垂直同期信号周波数で、フレームのライン数(625)から自動的に決まります。Vertical refreshは水平同期信号周波数で、ラインのピクセル数(1056)から自動的に決まります。従ってここで重要なのはPixel freq.のピクセルクロック周波数のみです。
- Horizontal timing (line)
 | Scanline part | Pixels | Time [µs] | 
| Visible area | 800 | 16.161616161616 | 
| Front porch | 16 | 0.32323232323232 | 
| Sync pulse | 80 | 1.6161616161616 | 
| Back porch | 160 | 3.2323232323232 | 
| Whole line | 1056 | 21.333333333333 | 
ラインの総ピクセル数は他を合計すれば自動的に決まります。
- Vertical timing (frame)
 | Frame part | Lines | Time [ms] | 
| Visible area | 600 | 12.8 | 
| Front porch | 1 | 0.021333333333333 | 
| Sync pulse | 3 | 0.064 | 
| Back porch | 21 | 0.448 | 
| Whole frame | 625 | 13.333333333333 | 
フレームの総ライン数は他を合計すれば自動的に決まります。
Verilogによる設計(過去記事)では、水平カウンタ、垂直カウンタを別々に設け、水平のタイミングデコーダと垂直のタイミングデコーダにより同期信号等を作成していました。また、自機が破壊された場合に全画面を赤色表示にするモジュールを図414.2のように、後段に接続していました。また、VRAMデータ4bitのうちRGBを表す3bitを取り出すために、xisliceモジュールを用いていました。
 図414.2 従来のグラフィックコントローラ階層図
図414.2 従来のグラフィックコントローラ階層図
今回BSVで再設計するにあたり、3個に分かれていたモジュール構成を1個にまとめます。
アルゴリズム説明
Graphics.bsvの中心部分:
     y <= 0;
     while (y < `VL) seq
//       for (y <= 0; y < `VL; y <= y+1) seq
        x <= 0;
//          for (x <= 0; x < `HL; x <= x+1) action  --- "for statement" consumes two cycles, so we like to use "while"
        while (x < `HL) action
           if (((`HD+`HFP) while
        y <= y + 1;
     endseq // for -> while
このように、y方向とx方向の2次元方向にドットクロックを数えます。コメントされている行のように、本来for文を2重で回したいのですが、資料事例で学ぶ BSVからの引用の図509.1に示すように、Stmt文内のfor文は2サイクルかかることに注意します。
 図509.1 for文とwhile文
図509.1 for文とwhile文
一方、while文は初期化に1サイクルかかるものの、インナーループでのチェックとアクションを1サイクルで実行できます。
for文のインナーループが2サイクルになるということは、2倍の周波数でFSMを駆動しなければならないことになります。現行では49.5MHzなので2倍では99MHzとなり、FPGAの上限に近くなってしまいます。
念のため99MHzで動作するfor文を用いたケースを合成し、正常動作を確認しましたが、タイミングクロージャや発熱等を考えると、回路はなるべく低速で回した方が望ましいです。
一方whileループであればインナーループが1サイクルで良いため、一旦for文で書いてから等価なwhile文に書き換えます。
 前のブログ
次のブログ
前のブログ
次のブログ