← Ana Sayfaya Dön
Verilog HDL FPGA / DE1-SoC VGA Grafik Sonlu Durum Makinesi

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.

Tasarım ve Implementasyon
DE1-SoC üzerinde 640×480 @ 60 Hz çözünürlükte çalışan oyun.

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.

Giriş Bölgesi Oyun Mantığı (60 Hz) Çıkış Bölgesi Keypad / KEY P1 tuşları, P2 pad keypad_scanner satır tarama input_debouncer 20 ms + 2-FF sync Kenar algılama press / held / release match_controller menü / raunt FSM game_logic_fsm karakter durumları hit_detection kombinasyonel çakışma vga_renderer piksel rengi vga_driver 640×480 @ 60 Hz seven_seg_ctrl HEX0..HEX5 LED mantığı raunt / yanıp sönme Saat birimi: 50 MHz alanı 25 MHz piksel saati + 60 Hz / tek-adım frame tick Kesik çizgiler: paylaşılan saat / frame tick her bloğu besler
Şekil 1. Sistem blok diyagramı — giriş, mantık ve çıkış bölgeleri.

Modül Ayrıştırması

Modül Görevi
input_debouncer20 ms sayaç debounce + 2-FF senkronizatör
keypad_scannerPlayer 2 için 4×4 matris satır tarama
game_logic_fsmKarakter durum makinesi ve fizik
hit_detectionKombinasyonel hitbox/hurtbox çakışması
match_controllerRaunt/maç denetleyici FSM
vga_rendererTarama konumuna göre piksel rengi üretimi
vga_driver640×480 @ 60 Hz zamanlama üreteci
seven_seg_controllerHEX 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.

hareket atak stun (zorunlu) IDLE hazır MOVE FORWARD +3 px/kare MOVE BACKWARD -2 px/kare · blok ATTACK BASIC 5 / 2 / 17 kare ATTACK SPECIAL 14 / 2 / 31 · ileri HITSTUN 17 kare BLOCKSTUN 15 kare GUARD BREAK 35 kare ileri bas geri bas bas iptal / şarj hit blok blok, 0 pts süre bitti → IDLE reset / raunt başlangıcı
Şekil 2. Karakter durum diyagramı — her oyuncu bu makinenin bir kopyasını çalıştırır.

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
Basic5217171535
Special14231KO1934

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_controller27PASS
match_controller24PASS
hit_detection17PASS
attack timing path19PASS
game_logic_fsm39PASS
Toplam (döngülerle)163ALL PASS
$ python3 testbench.py
Active frame 5: hitbox=True ............ PASS
Charge release → ATTACK_SPECIAL ....... PASS
Guard break phase=35 .................. PASS
Left edge: x<2 → IDLE ................. PASS
Total 163 tests ran: 163 passed, 0 failed -- ALL PASSED

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.

Menü ekranı — oyuncular taraf seçer.
Basit Atak — atak fazına göre renk değişimi
Special Atak — atak fazına göre renk değişimi.
Oyun-sonu ekranı — kazananı gösterir.
Şekil 3. Donanım: keypad bağlantısı, yedi-segment skor göstergesi ("P1-3-0") ve raunt LED'leri.

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.