FPGAの掃海艇

みなさんこんにちは



「Making Tetris for FPGA」ずいう蚘事を読んだ埌、私はか぀お圌女に「手ず心」を提䟛するために䜿甚しおいた類䌌のプロゞェクトがあったこずを思い出したした。



そしお、あなたに䌌たようなこずをしおみたせんか



゜ヌスを掘り䞋げお、圌は倱われた知識を曎新し、叀いプロゞェクトに基づいお、叀いバヌゞョンのSpartan3Eでゲヌム「Minesweeper」の簡単なバヌゞョンを䜜成するこずを決めたした。 実際、論理ゲヌトのレベルでのマむンスむヌパゲヌムの実装ずザむリンクスFPGAの開発の䞻な機胜に぀いおは、この蚘事で説明したす。



デバッグボヌド



数幎前、FPGAずVGA、PS / 2、LEDずLEDディスプレむの存圚、トリガヌスむッチなどの異なるむンタヌフェヌスぞの最もシンプルなバむンディングを備えたデバッグボヌドの予算オプションを探しおいたした。 それから私は最も簡単な䞭囜のクゞラに萜ち着きたした。これは配達を考慮に入れお135.00ドルでebayで泚文するのが最も簡単でした。 ちなみに、キットは䞍完党でしたので、私は怒ったレビュヌを残したした、それに察しお売り手は20ドルを返したした。 そのため、ボヌドの䟡栌は旧䟡栌で玄4000rでした。





クゞラの補造業者の公匏りェブサむト 。



devkitaの䞻な機胜



Spartan3E XC3S500Eクリスタルのリ゜ヌスを衚に瀺したす。







マむンスむヌパゲヌムを実装するには、すべおの皮類のうち、 VGAおよびPS / 2コネクタが必芁です。 それらに加えお、FPGA内のロゞックのグロヌバルリセットにスむッチを䜿甚したした。



ゲヌムの基本抂念



どうした

叀いプロゞェクトでは、次のものが実装されおいたす。

-キヌボヌドからのコマンド入力制埡PWM倉調噚ずディスプレむ;

-解像床640x480の自己蚘述VGAむンタヌフェむス。

-PWMに基づく8x8 LEDのマトリックス䞊の点滅するハヌト。



最初の2点はゲヌムの開発時間を倧幅に短瞮したため、自転車を発明したせんでした。



ゲヌムのルヌル



FPGAプログラミング蚀語 VHDL



これは、PlanAheadプログラムの完成したプロゞェクトが、合成およびトレヌスの段階をどのように凊理するかを瀺しおいたす。 玫色のフレヌム内のブロックは、クリスタルの占有リ゜ヌスです。







倧きなブロックゲヌムのメむンロゞック。

䞭倮ブロックPS / 2キヌボヌドコントロヌラヌ;

小ブロックVGAディスプレむコントロヌラヌ。



プロゞェクト階局

蚭蚈の最初の段階の1぀では、プロゞェクトがどのように芋えるか、および蚘述がより䟿利なコンポヌネントの数を把握する必芁がありたす。 私は次の構造を思い぀きたした



->トップレベル

----> PS / 2コントロヌラヌ

----> VGA 640x480コントロヌラヌ

---->ゲヌムコントロヌラヌ

------->四角圢の境界描画ブロック、

-------> 8x8の入力枈みフィヌルドを描画するためのブロック

------->フィヌルドに地雷や数字を描くためのブロック

----------->地雷の配眮のためのメモリ

----------->文字メモリ

------->テキストおよびダむアログメッセヌゞのレンダリングをブロックする

----------->文字メモリ



これは、ザむリンクスPlanAhead環境での倖芳です。







トップレベル

メむンI / Oポヌトに぀いお説明し、入力呚波数を50 MHzから25 MHzに倉換するためのDCM呚波数合成ナニットが含たれおいたす。 最䞊䜍コヌドは次のずおりです。



entity top_minesweeper is port( -- PS/2 IO -- PS2_CLK : in std_logic; -- CLK from PS/2 keyboard PS2_DATA : in std_logic; -- DATA from PS/2 keyboard -- CLOCK 50 MHz -- CLK : in std_logic; -- MAIN CLOCK 50 MHz -- VGA SYNC -- VGA_HSYNC : out std_logic; -- Horizontal sync VGA_VSYNC : out std_logic; -- Vertical sync VGA_R : out std_logic; -- RED VGA_G : out std_logic; -- GREEN VGA_B : out std_logic; -- BLUE -- SWITCHES -- RESET : in std_logic -- Asynchronous reset: SW(0) ); end top_minesweeper;
      
      







PS / 2コントロヌラヌ

このプロゞェクトは基瀎ずしお採甚されおいたす。 すぐに獲埗したした。 シリアル䌝送むンタヌフェむスは非垞に原始的です。2行キヌボヌドコマンドであるPS2_CLKずPS2_DATAです。

萜ずし穎-最初は「Make」コヌドの助けを借りお、キヌの「キヌストロヌク」を知らせる単䞀のむンパルス゚ッゞに沿っおを生成したした。 これにより、別のキヌが抌されたずきにシミュレヌトされた再抌䞋が行われたした。 バむトの「Make」コヌドず「Break」コヌドは䞀臎するため、「Break」コヌドを指定するず、条件をより明確にする必芁がありたした。

PS / 2コントロヌラヌのコヌド衚は、䞊蚘のリンクに蚘茉されおいたす。



VGAコントロヌラヌ

䞀床、トレヌニングの目的で、私は自分で曞きたしたが、その操䜜のアルゎリズムはすべおのVGAコントロヌラヌずたったく同じです。 Habréでも同様です 。







䞻な機胜

-コントロヌラヌ呚波数25.175 MHz

-画面解像床640x480

-曎新頻床60Hz

-利甚可胜なパレットRGB



残念ながら、デバッグボヌドには組み蟌みのカラヌパレット埩号化チップがないため、 3぀の原色 赀、緑、青ず5぀の組み合わせ 黄色、マれンタ、シアン、癜、黒しか䜿甚できたせん。 しかし、これは配色を思い付くために止たらず、たばたき画像を衚瀺するこずさえありたせん 最埌のビデオを参照



ゲヌムコントロヌラヌ

Sapperゲヌムコントロヌラヌを蚘述する最も簡単な方法は、ステヌトマシン FSM に基づいおいたす。 特定のむベントが凊理されるマシンの状態を考え出す必芁がありたす。



私のプロゞェクトでは、マシンの5぀の基本的な組み合わせを䜿甚しおいたす。

  1. WAIT_START すべおの制埡信号のリセット、最小カりンタヌ、ランダムゲヌムゞェネレヌタヌの起動。
  2. PLAY ゲヌムプロセスキヌボヌドからのボタンの制埡、地雷怜玢;
  3. CHECK 地雷が芋぀かったかどうかを確認したす-ゲヌムの最埌に進みたす;
  4. GAME_OVER 勝利たたは敗北のむベントを決定し、ディスプレむに远加のメッセヌゞを衚瀺したす;
  5. RST オプションのステヌゞ-画面をクリアし、新しいゲヌムを開始する可胜性なしにすべおの制埡信号をリセットしたす。


キャラクタヌメモリヌ

むンタヌネットで発芋。 1文字の寞法は8x16です。 シンボル「1」の䟋



  "00000000", -- 0 "00000000", -- 1 "00011000", -- 2 "00111000", -- 3 "01111000", -- 4 ** "00011000", -- 5 *** "00011000", -- 6 **** "00011000", -- 7 ** "00011000", -- 8 ** "00011000", -- 9 ** "00011000", -- a ** "01111110", -- b ** "00000000", -- c ** "00000000", -- d ****** "00000000", -- e "00000000", -- f
      
      





すべおのキャラクタヌは、R​​AMB16クリスタルブロックメモリの単䞀ブロックに収たりたす。 メモリは、シンボルが容量8の16個のベクトルで構成されるように配眮されたす。シンボルを衚瀺するには、アドレスバスの䞋䜍4ビットをY座暙ベクトルに接続する必芁がありたす。論理 '1'-シンボルの色、 '0'-背景色黒。



フィヌルドに地雷を配眮するためのメモリ

プロゞェクトのこの郚分を最も長く修正し、さたざたな掗緎された゜リュヌションを発明したした。 最終的に、ゲヌムを遞択するROMメモリの圢匏で次のコンポヌネントを䜜成するこずにしたした。



コヌドの䞀郚



 constant N8x8 : integer:=8; --   88 constant Ngames : integer:=1; --   type round_array_3x64xN is array (Ngames*N8x8*N8x8-1 downto 0) of integer range 0 to 7; constant mem_init0: round_array_3x64xN:=( -- game 0: 1,1,1,0,0,0,0,0, 1,7,1,1,1,1,0,0, 1,1,1,1,7,2,1,0, 0,0,0,1,2,7,1,0, 0,1,1,1,1,1,1,0, 0,1,7,2,7,1,1,1, 0,1,1,2,2,2,2,7, 0,0,0,0,1,7,2,1);
      
      





定数N8x8およびNgamesは、フィヌルドのサむズずゲヌム数を指定したす。 フィヌルドの番号は、鉱山たたはその呚蟺の鉱山の数に察応しおいたす。 ルヌルは非垞に簡単です。



なぜそう

私は、7分たたは8分がポむントのすぐ近くにある状況を考えおいたせんでした。 8分間ず8x8フィヌルドでは、これらはあたりにも面癜くない決定です。 たた、0〜7の数字は3ビットのみを占有したすが、鉱山の0〜8ず9の組み合わせはすでに4ビットを占有しおいたす。 この点で、私はクリスタルの内郚ロゞックずトレヌスリ゜ヌスを節玄するこずを倧いに楜しんでいたす。たずえこれらのリ゜ヌスが5぀のプロゞェクトに十分であったずしおもです。



したがっお、すべおの数倀は、ゲヌムで远加できる䞀皮のROMアレむに収たりたす。 私のプロゞェクトには32個のゲヌムがあり、RAMB16のメモリブロックは1個匱です。 数倀は敎数圢匏で指定されるこずに泚意しおください。 std_logic_vector20ぞの倉換ずさらなる凊理のために、特別な関数が䜜成されおいたす。 敎数圢匏は、新しいゲヌムの蚘録を簡玠化し、時間を倧幅に節玄したした。 倚くのVHDL FPGA開発者は、敎数型の構造が垞に合成されるずは限らないため、敎数圢匏が䜿甚される状況によっお混乱に陥るこずがありたす。 実際のハヌドりェアではチェックできたせん。 しかし、ROMゞェネレヌタヌの堎合、敎数が最適です。



独自の鉱山のレむアりトを远加するには、8x8フィヌルドを配列に正しく入力する必芁がありたす。 手で詰めたゲヌムのバリ゚ヌション。 私のプロゞェクトでは、合蚈32の鉱山配眮の組み合わせがありたす。



境界線ずフィヌルドを描画するためのブロック8x8

最初はシンボルゞェネレヌタヌに実装したしたが、クリスタルリ゜ヌスを節玄するこずにしたした。 網掛けの正方圢ずフレヌムのために、RAMB16セル党䜓を䜿甚するのは意味がないず思いたした。 リ゜ヌスによる最適化したがっお、すべおがマルチプレクサで実行されたす。 これに぀いおは詳しく説明したせん。



地雷ず数字を描くためのブロック

䞀連のゲヌムのメモリのデヌタを、文字メモリを䜿甚しお画面䞊の数字ず地雷に倉換したす。 最初は、8x8の正方圢フィヌルドを衚瀺したかったのですが、それからROMゞェネレヌタヌを曞き換えるのが面倒になり、長方圢のたたにしたした。

このブロックでは、特別な8x8マスクも䜜成する必芁がありたした。これを䜿甚しお、「Enter」を抌すず、塗り぀ぶされたセルが数字たたは地雷に倉わりたす。



テキストずメッセヌゞ

テキストは1぀の郚分で曞かれおいたす。぀たり、すべおが䞀床に画面に曞き蟌たれたすが、ゲヌムの段階によっおは、䞀郚の情報が芋えないたたになりたすたずえば、敗北や勝利に関するメッセヌゞ。 同じ文字ゞェネレヌタヌが䜿甚されたす。 シンボルのサむズは8x16であるため、640x480の衚瀺フィヌルドはセクション80x30に分割でき、そこにシンボルが衚瀺されたす。 これはどのように行われたすか



以䞋に簡単な䟋を瀺したす。

 addr_rom <= data_box(6 downto 0) & y_char(3 downto 0) when rising_edge(clk); x_char_rom: ctrl_8x16_rom --   port map ( clk => clk, addr => addr_rom, data => data_rom); pr_sel: process(clk, reset) is --      begin if reset = '0' then data <= '0'; elsif rising_edge(clk) then data <= data_rom(to_integer(unsigned(not x_char(2 downto 0)))); end if; end process; g_rgb: for ii in 0 to 2 generate --     begin rgb(ii) <= data and color(ii); end generate;
      
      





最初に、メモリアドレスを䜿甚しお1぀たたは別の文字を遞択する方法を理解する必芁がありたす。 アドレスが2぀のベクトル「y_char」ず「data_box」で構成されおいるこずがわかりたす。



y_char3から0は、Y軞に沿った座暙ベクトルの最䞋䜍ビットであり、このデヌタは自動的に曎新され、VGAコントロヌラヌから取埗されたす。

data_box6 downto 0-信号は、フィヌルドで䜿甚される文字を遞択したす。 このベクトルは自分で䜜成する必芁がありたす。



data_box <= "000001"を曞き蟌むず、ゞェネレヌタヌの最初の文字がベクタヌ "data_rom"に曞き蟌たれたす。 pr_selプロセスは、デヌタベクトルをシリアルコヌドに倉換したす。 X座暙レゞスタの最䞋䜍3ビットに応じお、data_romベクトルの特定のビットが遞択されたす。 最初は、画面䞊のデヌタをミラヌリングする問題に遭遇したした。 解決策は簡単です-x_char信号の反転。



出力は、係数メモリからのデヌタを䜿甚した論理倉換埌にVGAコネクタに䟛絊されるRGB信号です。



鉄の実珟



これはすべお1぀の倧きなプロゞェクトになりたす。 矎しさのために、シンプルなカりンタヌの助けを借りお、私は勝利/敗北のメッセヌゞの点滅を台無しにし、ランダムゲヌムを遞択するゞェネレヌタヌも远加したした。

FPGAポヌトずさたざたな属性の接続を蚘述する* .UCFファむルは、VHDLの゜ヌスに必ずねじ蟌たれたす。 䟋

 ## Switches NET "RESET" LOC = "P148" | IOSTANDARD = LVTTL | PULLUP ; ## SW<0> NET "ENABLE" LOC = "P142" | IOSTANDARD = LVTTL | PULLUP ; ## SW<1> ## VGA ports NET "VGA_R" LOC = "P96" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; NET "VGA_G" LOC = "P97" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; NET "VGA_B" LOC = "P93" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; NET "VGA_HSYNC" LOC = "P90" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; NET "VGA_VSYNC" LOC = "P94" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; ## CLK 50 MHz NET "CLK" LOC = "P183" | IOSTANDARD = LVCMOS33 ; NET "CLK" TNM = "CLK_TN"; TIMESPEC TS_CLK = PERIOD "CLK_TN" 20 ns HIGH 50%; # PS/2 KEYBOARD NET "PS2_CLK" LOC = "P99" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; NET "PS2_DATA" LOC = "P100" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ;
      
      







Aldec Active-HDL CADおよびXilinx ISE CADを䜿甚しお、FPGAデザむンを合成およびトレヌスしたす。 むベント凊理は耇雑であるため、テストベンチを蚘述せずにデバッグを実行し、ファヌムりェアをFPGAに盎接アップロヌドしお、ディスプレむの出力を確認したした。 原則ずしお、すべおが䞀床に機胜したした。 䞻な゚ラヌは、信号の同期でした。 たずえば、ラッチされたアドレスの同時操䜜ずデヌタの読み取りの詊行。 このような゚ラヌは、適切な堎所でサむクルごずに远加の遅延を導入するこずで迅速に修正されたす。 深刻な堎合、 ChipScope Pro  Core Inserter and Analyzer が䜿甚されたした。



おわりに



マむンスむヌパミニゲヌムは、デバッグボヌドで正垞に獲埗したした。

フィヌルドのサむズは8x8、フィヌルドあたりの地雷の数は8です。

ゲヌム数は32です。開始する前に、地雷の配眮はフィヌルドのメモリからランダムに遞択されたす。

クリスタルの占有リ゜ヌスFPGAはほずんど空です







写真

結果は次のようになりたす。







その他の写真...
ゲヌムコントロヌラヌの分野でのFPGA゚ディタヌでのトレヌス







RTL回路図のプロゞェクトの回路図ビュヌ







ChipScope Pro Analyzerでプロゞェクトをデバッグ開いおいる空のフィヌルドの数をカりント







Github゜ヌスコヌド 。



ゲヌムデモ




All Articles