FPGA Tabanlı Gerçek Zamanlı 2 Kişilik Dövüş Oyunu
Footsies'ten ilham alan, tamamen donanımda gerçeklenen, 60 Hz VGA çıkışlı, kare-doğru (frame-accurate) bir dövüş oyunu.
Bir Bakışta Proje
Bu proje, bir mikroişlemci ya da yazılım kullanmadan, tamamen senkron donanım olarak tasarlanmış iki kişilik bir dövüş oyunudur. Giriş alımından çarpışma çözümüne ve video çıkışına kadar her alt sistem Verilog ile yazılıp FPGA üzerinde eş zamanlı çalışmaktadır. Oyun mantığı VGA tazeleme hızıyla (60 Hz) senkronize edildiği için her karakter durumu ekranın her bir karesinde tam olarak bir kez güncellenir; bu da oyunu deterministik bir makineye dönüştürür.
1. Proje Kapsamı ve Mühendislik Yaklaşımı
Projenin amacı, dijital tasarım ilkelerini eksiksiz ve etkileşimli bir sistem kurarak pekiştirmektir. Oyun, yandan görünüşlü iki boyutlu bir dövüş deneyimidir: her oyuncu kendi karakterini hareket ettirir, normal ve özel atak yapar ve amaç üç raunt kazanmaktır. Savunma mekaniği örtüktür — geriye doğru yürümek bloklamak demektir. Bu sade tasarım, türü dijital açıdan ilginç kılan zamanlamaya duyarlı etkileşimlere (kare verisi, hitbox'lar, durum geçişleri) odaklanmamızı sağladı.
Donanım mimarisi asimetrik girişler kullanır: Player 1 kart üzerindeki tuşları, Player 2 ise harici bir 4×4 keypad'i kullanır. Tüm sistem tek bir 50 MHz saat alanında çalışır; bu saatten hem 25 MHz piksel saati hem de oyun mantığını ilerleten 60 Hz "frame tick" sinyali türetilir.
2. Sistem Mimarisi
Sistem, kod yazımını ve hata ayıklamayı kolaylaştırmak için birbiriyle haberleşen alt modüllere ayrılmıştır. Tek bir üst-seviye modül (fighting_game) bu blokları örnekler, saatleri üretir ve fiziksel girişleri mantıksal karakter kanallarına yönlendirir.
Modül Ayrıştırması
| Modül | Görevi |
|---|---|
| input_debouncer | 20 ms sayaç debounce + 2-FF senkronizatör |
| keypad_scanner | Player 2 için 4×4 matris satır tarama |
| game_logic_fsm | Karakter durum makinesi ve fizik |
| hit_detection | Kombinasyonel hitbox/hurtbox çakışması |
| match_controller | Raunt/maç denetleyici FSM |
| vga_renderer | Tarama konumuna göre piksel rengi üretimi |
| vga_driver | 640×480 @ 60 Hz zamanlama üreteci |
| seven_seg_controller | HEX gösterge kod çözücü |
| fighting_game | Üst modül; alt modülleri örnekler ve birleştirir |
3. Giriş Koşullandırma
Her oyuncunun tam üç tuşu vardır: sola git, sağa git ve atak. FPGA'in yalnızca dört tuşu olduğundan, iki oyuncu ve bir debug tuşu için harici bir 4×4 keypad GPIO pinlerine bağlanmıştır.
Metastabilite ve Bouncing'e Karşı İki Aşamalı Koruma
İnsan girişi sistem saatiyle karşılaştığında flip-flop çıkışı belirsiz (metastabil) olabilir. Bunu önlemek için iki aşamalı D flip-flop senkronizatör kullanılır. Senkronizasyondan sonra sayaç tabanlı bir debouncer, bir tuşu kabul etmeden önce 20 ms boyunca sabit kalmasını bekler. Böylece tek bir basış, tek bir temiz mantıksal sinyale dönüşür.
Player 2'nin keypad'i satır tarama (row scanning) algoritmasıyla okunur: her satır sırayla aşağı çekilir, basılan tuşun sütunu da düşerek hangi tuşa basıldığı tespit edilir.
Önemli bir tasarım kararı: atak, tuşun basılma kenarında tetiklenir, basılı tutulduğunda değil. Tuşu basılı tutmak sürekli atak yaptırmaz; bunun yerine özel atağı şarj eder. Yeterince (30 kare) şarj olunca tuş bırakıldığında özel atak tetiklenir.
4. Çekirdek Oyun Mantığı
Her karakter, game_logic_fsm içinde iki kez örneklenen sekiz durumlu bir durum makinesiyle tanımlanır. Karakter aynı anda yalnızca bir durumda olabilir. İleri hareket karede 3 piksel, geri hareket 2 piksel ilerletir; karakterler birbirini geçemez ve ekrandan çıkamaz. Hasara yol açan durumlar (hitstun, blockstun, guard break) en yüksek önceliğe sahiptir ve oyuncunun isteğe bağlı komutlarını ezer.
Ataklar bağlayıcıdır (committal): başladıktan sonra startup, active ve recovery fazlarının hepsinden geçmek zorundadır; aradaki tuşlar etkisizdir. Bunu bozabilen tek şey darbe almaktır. Özel atak iki yoldan tetiklenir: tuşu şarj edip bırakarak, ya da isabet eden bir normal atağı recovery fazında iptal ederek.
Uygulanan Kare Verisi
| Hamle | Startup | Active | Recovery | Hitstun | Blockstun | Guard Break |
|---|---|---|---|---|---|---|
| Basic | 5 | 2 | 17 | 17 | 15 | 35 |
| Special | 14 | 2 | 31 | KO | 19 | 34 |
5. Çarpışma Değerlendirme ve Görsel Çıkış
hit_detection tamamen kombinasyonel bir bloktur. Her karakter için vurulabilir bir hurtbox, atağın active fazında ise bir hitbox oluşturulur. Hitbox rakibin hurtbox'ıyla çakışırsa atak bağlanmış sayılır ve sonuç — rakibin blok durumuna ve block point sayısına göre — hit, block ya da guard break olarak çözülür. Blok ayrı bir tuşa bağlı olmadığından, geriye yürüyen ve block point'i olan bir hedef başarılı blok olarak değerlendirilir.
Görsel boru hattı iki bloğa ayrılır: vga_driver 25 MHz piksel saatiyle 640×480 @ 60 Hz zamanlamasını ve hsync/vsync sinyallerini üretir; vga_renderer ise mevcut (x, y) koordinatına ve oyun durumuna göre her piksel için 8-bit (3-3-2 RGB) rengi belirler. Nesneler çakıştığında bir öncelik sırası uygulanır.
6. Karşılaşılan Zorluklar
Saat Alanı Yönetimi
DE1-SoC 50 MHz saat sağlar; VGA 25 MHz, oyun mantığı ise 60 Hz frame tick gerektirir. Erken denemelerde debug adımı için kullanılan kapılı (gated) saatler glitch'e yol açtı. Çözüm, tek bir 50 MHz saat alanı + bir çevrim genişliğinde frame-tick "enable" sinyali kullanmak oldu. Bu, tüm oyunu temiz senkron bir makineye dönüştürdü ve zamanlama hatalarını ortadan kaldırdı.
İkinci büyük zorluk VGA renderer kodlamasıydı: karakterler, zemin, arka plan, block point'ler ve raunt göstergelerinin tümünün piksel piksel hesaplanması gerekti. Karışıklığı önlemek için tüm giriş/çıkışları önceden tanımlayıp işi küçük parçalara böldük. Son olarak debug mod anahtarı (SW[1]) bir gürültü problemi yarattı; bunu da debouncing filtreleri ve çok aşamalı flip-flop'larla çözdük.
7. Sonuçlar ve Doğrulama
Sistem iki seviyede doğrulandı: oyun mantığı için modül seviyesinde fonksiyonel bir testbench, ve DE1-SoC üzerinde donanım doğrulaması. Oyun mantığı deterministik ve kare başına ilerlediği için, video zamanlamasından bağımsız olarak test edilebildi. Python'da yazılan kare-doğru bir model, beş bloğu toplam 163 kontrol (assertion) ile sınadı; hepsi başarıyla geçti.
| Test Edilen Modül | Kontrol Sayısı | Sonuç |
|---|---|---|
| seven_seg_controller | 27 | PASS |
| match_controller | 24 | PASS |
| hit_detection | 17 | PASS |
| attack timing path | 19 | PASS |
| game_logic_fsm | 39 | PASS |
| Toplam (döngülerle) | 163 | ALL PASS |
8. Donanım ve Oynanış Galerisi
DE1-SoC üzerinde menü, geri sayım, dövüş ve oyun-sonu ekranları; çizgili arka plan, iki karakter, raunt ve block-point göstergeleriyle birlikte. Yedi-segment "P1 VS P2" gösterir ve LED'ler kazanılan raunda göre yanar; maç sonunda hepsi birlikte yanıp söner.
9. Sonuç
Bu projede, girişten video çıkışına kadar tüm alt sistemler tek bir senkron donanım tasarımında başarıyla entegre edildi. En zorlu kısım, oyunun bağımsız parçalarını ayırıp tekrar birbirine bağlamaktı. Proje bize saat alanı yönetimi, senkronizasyon pratikleri ve kare-doğru test etmenin değeri konusunda çok şey öğretti. Gerçek zamanlı etkileşimli bir oyunun FPGA üzerinde başarıyla çalıştırılması, algoritmik durum makinelerinin fiziksel donanıma doğrudan modellenmesini ve dijital tasarımın temel ilkelerini pekiştirdi.