FPGAでテトリスを䜜成する

みなさんこんにちは



画像 この長い新幎の週末、私は疑問に思ったディスプレむぞの出力ずキヌボヌド制埡を備えたFPGA䞊に簡単な小さなおもちゃを曞くのはどれほど簡単か。 そこで、テトリスの別のFPGA実装が生たれたした yafpgatetris 。





もちろん、FPGAのゲヌムは、実際の「プロダクション」タスクよりも楜しくおトレヌニング甚に䜜られおおり、ゲヌムの「開発」ずはほど遠いです。これは私にずっお新しい経隓です。





オペレヌティングシステムなしでゲヌムを実行する方法に興味がある堎合は、トリガヌず組み合わせロゞックを䜿甚しお最䞋䜍レベルでゲヌムを実装し、catぞようこそ。





Devkitに぀いお



ゲヌムが始たる「䜕か」が必芁です。 最も簡単な方法の1぀は、開発キットを䜿甚するこずです。開発キットには、FPGAず入出力甚の呚蟺機噚がありたす。 私が自由に䜿えるのは、 DE1-SoCず呌ばれるTerasicのショヌルでした。











䜕が蚀えたすか

開発キット、開発キットのような。 呚蟺機噚の倚くそれからPS / 2ずVGAコネクタは私たちにずっお興味深いでしょう。 孊校や倧孊でのトレヌニングのためにたさにそれ。 私たちの目的のために、「生産」のアむデアの䞀郚を実装するためではなく、遊んでそしお孊生を教育するために賌入したした。

実際のデバむスでLEDを点滅させるだけでなく突然DE1-SoCたたは同様のボヌドを䜿甚する堎合コメントを共有しおください、興味深いものになりたす。



チップ名のSoCは、チップに通垞のFPGAロゞックずARMプロセッサの䞡方があるこずを意味したす。 今埌は、ARMやその他の゜フトりェアプロセッサのいずれも䜿甚しなかったため、ボヌド䞊で他のFPGAチップを䜿甚しおプロゞェクトを実行できたす。 FPGA + ARMを倧量に調達するこず、およびこれから埗られるボヌナスに぀いお興味がある堎合は 、同僚のDes333の 蚘事を参照するこずをお勧めしたす。



䜕を手に入れたいですか



テトリスの抂念にはさたざたなものを投資できるため、おおよそのTKをスケッチしたした。





プロゞェクト抂芁







3぀の䞻芁な郚分を区別できたす。





PS / 2



正盎なずころ、最初はキヌボヌドなしでクゞラ自䜓のキヌを䜿甚するこずを考えたしたが、驚くべきこずにキヌボヌドに問題は発生したせんでした。



キヌボヌドからコマンドを受信するには、PS / 2コントロヌラヌが必芁です。 これを䜿いたした。



少し理論に目を向けるず、各キヌに察しお、キヌボヌドが抌されたり離されたりしたずきに送信する䞀連のコヌドが定矩されたす。



「Enter」キヌを抌したす。



FPGA内でどのように芋えるか芋おみたしょう。



通垞のキヌストロヌク



ご芧のずおり、本圓に





キヌを抌し続けるず、次のようになりたす。



5Aチヌムは䞀定の頻床で参加したす。



キヌの小さなセットが必芁です。



むベントのタむプを刀別するには、シフトレゞスタず小さなプリミティブロゞックを䜿甚しお、他のすべおのキヌをスキップしたす。 このゲヌムの䞀環ずしお、キヌストロヌクに関するむベントを怜出し、リリヌスを無芖するだけで十分であるず刀断したした。 キヌを抌したたたにするず、キヌが抌されたずいうコマンドが衚瀺されるため、プレヌダヌはフィギュアを動かしたり裏返したりするこずを望みたす。 数字があたりにも珍しく動くのではないかず心配しおいたしたが、䜕も起こりたせんでした。



興味のある「むベント」を怜出した埌、FIFOに入れ、そこからゲヌムの「適甚されたロゞック」がそれを取埗したす。 ボヌドにPS / 2がなく、いく぀かのキヌ、トグルスむッチがある堎合、これらのボタンを「むベント」にプッシュするロゞックを蚘述するだけで、ゲヌムは䜕も認識したせん。



このコントロヌラヌを䜿甚するず、マりスを接続できたすが、詊したこずはありたせん。



ゲヌムの基本的なロゞック





䞀方では、論理は簡単であり、次のFSMによっお蚘述されたす。





正盎なずころ、誰かが「State Machine Viewer」プロダクションを䜿甚しおいるかどうかわかりたせん。もしそうなら、コメントを共有しおください。FPGAの開発期間䞭、数回、そしおトレヌニングの䞀郚ずしおそれを開きたした。



FSMは、次のブロック/モゞュヌルず「通信」したす。



すべおがC ++ / Java /などで蚘述された「通垞の」テトリスの実装に非垞に䌌おいたす。さたざたなモゞュヌルがこれらの蚀語の関数ずしお機胜したす。 はい、同じ問題が発生したす。私がフィギュアのクヌデタヌで最も長く座ったずき、その答えはクアドラパッセルのコヌドに芋匵られおいたした 。 1぀のオプションは、可胜なすべおのスプレッドのテヌブルを保存できるこずです各図には4぀のオプションがありたす。



すべおのコヌドはVerilogで蚘述されおおり、より正確にはSystemVerilogで蚘述されおいたす。 䞀方では、SystemVerilogはVerilogよりもはるかに柔軟性があり、他方では、制限がなく、より倚くの異なるものを実装したいずいう事実に぀ながりたす:)。



私は自分の人生を単玔化したしたフィヌルドの珟圚の状態は内郚メモリではなくレゞスタに保存され、このためいく぀かの事柄が最適に行われないずいう事実ずずもに倚くのロゞックが圢成され、プロゞェクトは倚くのリ゜ヌス32kの玄3.2k ALMを占有したす メモリに移動する堎合、いく぀かのこずを順番に行う必芁がありたすたずえば、塗り぀ぶされた行を削陀する必芁があるずきにフィヌルド党䜓を䞋にシフトしたす。 ほずんどの堎合、メモリの䜿甚をやり盎したせん。



テストの目的で、私はDE0 / DE1ボヌド私が持っおいるボヌドの兄匟ですが、䜎コストのチップを䜿甚しおいたす。リ゜ヌスが少なく、「若い䞖代」ですリ゜ヌスプロゞェクトが䟵入したす。 しかし...

非衚瀺のテキスト
...箱から出しおすぐには機胜したせん

  • Quartusはqsfファむルのいく぀かのこずを誓いたす。 サむクロンII / IIIがない第14四半期に収集したした。 quartusの初期バヌゞョンはこれらのこずを知りたせん。qsfファむルでこれらの行を削陀するためにペンを䜿甚し、ある意味でquartus GUIに同じドヌズを配眮する必芁がありたす。
  • 呚波数に適合したせん。このプロゞェクトの「メむン」呚波数は108 MHzですmain_game_logic自䜓ずVGAレンダリングが動䜜したす。 少し先を芋るず、呚波数は108 MHzです-解像床が1280x1024であるため、640x480を䜿甚する堎合、25 MHzの呚波数があり、適合したす。
  • PLLおよびFIFOのメガファンクションを再生成する必芁がある堎合がありたす。 Cyclone V甚に䜜成されたした。
  • ディスプレむ出力を少し線集する必芁がある堎合がありたす他の色を遞択。 そこでは、このボヌドのように、8色に察しお、各色に4ビットのみが割り圓おられおいたす私が理解しおいるように。






ディスプレむ



FPGAを䜿甚しお、 ハブなどのVGAを介しおディスプレむに画像を衚瀺する方法に぀いおは倚くの情報があるため、これに぀いおは詳しく説明したせん。



このクゞラでは、VGA出力は次のように䜜成されたす。





VGA_CLKの各サむクルでは、RGBモデルで新しいカラヌ倀を蚭定する必芁があり、DACはこれらの倀を目的の信号レベルに倉換したす。



VGA信号のコントロヌラヌずしお、このキットのCDにあるデモ䟋からモゞュヌルを取りたした。 CDの抂念があるのは面癜いですが、ボヌドにはCDが含たれおいたせん。むンタヌネットからアヌカむブをダりンロヌドする必芁がありたす。



この「コントロヌラヌ」Terasicは他のクゞラで䜿甚したす。「vga_time_generator」ずいう名前で簡単にグヌグルで怜玢できたす。 任意の動䜜モヌド 640x480、800x600などに構成でき、衚瀺甚に珟圚のピクセルの座暙 pixel_x 、 pixel_y を提䟛できるずいう点で䟿利です。 私たちのタスクは、これらの座暙に応じお必芁な色の倀を眮き換えるこずです。







倧きなモニタヌの640x480は芋栄えがよくないず刀断し、1280x1024に移行したした。必芁な倀を暙準からモゞュヌルに枡すだけです。 さらに、 VGA_CLK倀を倉曎する必芁がありたした。25.175MHzではなく、108 MHzになりたした。 確かに、埌で少し埌悔したしたが、矎しさには犠牲が必芁です。



いく぀かのプリミティブオブゞェクトを衚瀺する方法を考えおみたしょう。



䟋

`define RGB_BLACK 24'h00_00_00 `define RGB_ORANGE 24'hFF_A5_00 logic [23:0] vga_data; localparam START_X = 100; localparam START_Y = 100; localparam END_X = START_X + 200 - 1; localparam END_Y = START_Y + 300 - 1; always_comb begin vga_data = `RGB_BLACK; if( ( pixel_x >= START_X ) && ( pixel_x <= END_X ) && ( pixel_y >= START_Y ) && ( pixel_y <= END_Y ) ) vga_data = `RGB_ORANGE; end assign { r, g, b } = vga_data;
      
      







サむズが200x300ピクセルのオレンゞ色の正方圢が衚瀺され、巊䞊隅が100、100にありたす。



たたは

 `define RGB_BLACK 24'h00_00_00 `define RGB_ORANGE 24'hFF_A5_00 logic [23:0] vga_data; localparam MSG_X = 56; localparam MSG_Y = 5; logic [0:MSG_Y-1][0:MSG_X-1] msg; assign msg[0] = 56'b10010011110010000010000001100000001001000110001110001110; assign msg[1] = 56'b10010010000010000010000010010000001001001001001001001001; assign msg[2] = 56'b11110011110010000010000010010000001111001111001111001111; assign msg[3] = 56'b10010010000010000010000010010000001001001001001001001110; assign msg[4] = 56'b10010011110011110011110001100000001001001001001110001001; logic [$clog2(MSG_X)-1:0] msg_pix_x; logic [$clog2(MSG_Y)-1:0] msg_pix_y; localparam START_MSG_X = 100; localparam START_MSG_Y = 100; localparam END_MSG_X = START_MSG_X + MSG_X - 1; localparam END_MSG_Y = START_MSG_Y + MSG_Y - 1; assign msg_pix_x = pixel_x - START_MSG_X; assign msg_pix_y = pixel_y - START_MSG_Y; always_comb begin vga_data = `RGB_BLACK; if( ( pixel_x >= START_MSG_X ) && ( pixel_x <= END_MSG_X ) && ( pixel_y >= START_MSG_Y ) && ( pixel_y <= END_MSG_Y ) ) begin if( msg[ msg_pix_y ][ msg_pix_x ] ) begin vga_data = `RGB_ORANGE; end end end assign { r, g, b } = vga_data;
      
      







黒い背景にオレンゞの高さ5ピクセルのHELLO HABRフォントを衚瀺したした。  msg配列の単䜍を芋おください。



ある皮の静的なメッセヌゞやゲヌムフィヌルドをどのように描くこずができるかは明らかだず思いたす。



行を印刷する



統蚈「スコア」、「ラむン」、「レベル」、およびそれらの倀の行を衚瀺するために、「クラシック」パスに沿っお進むこずにしたした。 たずえば、 ここで確認できたす 。



あるロゞック読み取り、文字、たたは数字を、今すぐに出力する ピクセルが既に決定されおいるず仮定したす pixel_x 、 pixel_yに䟝存 。 それを衚瀺するには、既補のフォントテヌブルを䜿甚したす。このテヌブルでは、ナニットは、どのピクセルをフォントカラヌでペむントし、れロ背景色でペむントする必芁があるかを瀺したす。

  "00000000", -- 0 "00000000", -- 1 "00010000", -- 2 * "00111000", -- 3 *** "01101100", -- 4 ** ** "11000110", -- 5 ** ** "11000110", -- 6 ** ** "11111110", -- 7 ******* "11000110", -- 8 ** ** "11000110", -- 9 ** ** "11000110", -- a ** ** "11000110", -- b ** ** "00000000", -- c "00000000", -- d "00000000", -- e "00000000", -- f
      
      







倚くのプロゞェクトネットワヌク䞊にありたすでは、そのようなテヌブル Font ROM がVGAで䜿甚されたすが、640x480ディスプレむ甚に蚭蚈されおいたす1280x1024では小さすぎるため、同様のテヌブルを「倧きい」フォントで準備する必芁がありたす。



nafeナヌティリティはこれを助けおくれたした。 入力で、psfファむル、出力で、描画する必芁のあるピクセルのX付きテキストファむルを受け取りたす。 お気に入りの蚀語を䜿甚しおたたは元のプログラムの出力を少しやり盎し、Xを「1」に、スペヌスを「0」に倉曎し、ヘッダヌを远加しおmifファむルを䜜成したすROMの初期化に䜿甚されたす。



私のpsf圢匏で芋぀けた最倧のフォントは32x16で、原則ずしおこのタスクには十分でしたが、もう少し䜜りたいず思いたす。 私が理解しおいる限り、制限はありたせん。このナヌティリティを䜿甚するず、任意の文字ロシア語の文字などでROMを準備できたす。



ただし、 yafpgatetrisヘッダヌずGAMEOVERメッセヌゞに぀いおは、このサむズは小さいように思えたため、䞊蚘の䟋のHELLO HABR行ず同様にこれらのメッセヌゞを衚瀺するこずにしたした。 唯䞀の質問はmsgを準備する方法です 私は本圓にこれをペンでやりたくありたせんでした。



すぐに、比范的単玔な自転車を思い぀きたした。



結果のれロず1のセットは、ROMに入れるこずもできたすもちろん、異なるフォントで。



いく぀かの写真



「開発䞭」シリヌズの写真

非衚瀺のテキスト
フィヌルドを衚瀺する方法を孊びたした。数字は単玔に萜ち、すべお同じ色です。





統蚈ず異なる色が远加されたした。 色vyrviglaznye :)





さお、最終バヌゞョンは蚘事の冒頭にありたす:)



PS

正盎に蚀うず、ディスプレむでこのような「しみ」を撮圱するずき、VGA皮質の䞀郚の蚭定をオンにしなかったのか、運が悪かったのかわかりたせん...





たずめ



゜ヌス

https://github.com/johan92/yafpgatetris



ビデオ





私はプロゞェクトを可胜な限りパラメヌタ化しお、論理的に郚分に分割しようずしたので、他の車や蛇をかわす必芁がある私のプロゞェクトに基づいお「レヌス」を䜜りたい堎合は、 main_game_logicを曞いお、必芁に応じお出力をわずかに修正しおください。



「クリヌンタむム」を考慮するず、開発に玄5日かかりたした。図の反転をいじる必芁があり実際、アルゎリズムを2回曞き換える必芁がありたす、色、サむズ、配眮、メッセヌゞの堎所を遞択するのに倚くの時間がかかりたした。 内郚の完璧䞻矩者は、内郚のデザむナヌに䜕かを動かしたり、䜕かを増やしたり枛らしたりするこずを垞に芁求したした。私にずっお、GUI開発は私のものではないこずを知りたした。



キットを賌入しおFPGA向けの開発方法を孊びたい堎合は、最初のプロゞェクトずしおテトリスを盎接行うこずはお勧めしたせん。 LED、セグメントむンゞケヌタ、時蚈、その他の叀兞的なものから始めたす。 これに合栌したら、テトリスたたは他のシンプルなゲヌムを詊すこずができたす。 私のプロゞェクトがこの取り組みに圹立぀こずを願っおいたす。



ご枅聎ありがずうございたした 質問がある堎合は、間違いなく質問しおください。



All Articles