🎮 PROJECT 1: SPACE FORCE X — DISASTER STRIKES
Introduction
Space Force X: Disaster Strikes is an interactive space defense game implemented on the Basys3 FPGA development board. Players control a defensive tank positioned at the bottom of a VGA display screen to protect against waves of descending alien invaders. This intermediate-level project introduces students to complete embedded system design including Finite State Machines, real-time collision detection, synchronous hardware design patterns, and VGA display interfacing. Every pixel rendered, every collision detected, and every game state transition is a direct result of hardware logic circuits working in concert at the clock cycle level.
Project Overview
Space Force X simulates a classic top-down space defense scenario that mirrors real-world systems like air defense networks and threat detection systems. The gameplay takes place on a 640×480 pixel VGA display where time is measured in clock cycles. A player-controlled tank occupies the bottom 30 pixels of the screen. Above it, an enemy formation of aliens descends in organized rows. The objective is straightforward but demanding: destroy all alien invaders before any reach the tank’s position at Y=450 pixels. Success advances the player to progressively harder levels with increased speed and density.
The beauty of this project lies in its architectural elegance. Rather than using a high-level programming language running on a processor, Space Force X employs dedicated hardware circuits for each function. The tank position is stored in a hardware register. Alien positions are managed by arrays of flip-flops. Collision detection happens combinatorially in the same nanosecond across all entities. The rendering happens in parallel, with every pixel decision made instantly based on current entity coordinates. This parallel processing capability demonstrates why FPGAs excel at real-time systems where responsiveness cannot be delayed by software execution times.
The game implements a Mealy Finite State Machine with six distinct states: START_SCREEN (awaiting player input), PLAYING_LEVEL_1 (active gameplay on level one), PLAYING_LEVEL_2 (faster difficulty), LEVEL_ADVANCE (brief transition state), PAUSE_STATE (game frozen), and GAME_OVER (end screen). Each state has precisely defined entry conditions and exit conditions. State transitions happen synchronously on clock edges, ensuring deterministic behavior essential for reliable embedded systems. This FSM design teaches professional hardware architecture patterns used in aerospace, automotive, and industrial control applications.
What Project Does
The game begins with a START_SCREEN displaying “SPACE FORCE X” and waiting for keyboard input. The moment a player presses any key, the FSM transitions to PLAYING_LEVEL_1. The screen now displays a formation of 24 aliens arranged in 3 rows of 8, positioned at the top of the screen. Simultaneously, the tank appears at the bottom center, ready to defend. The player controls movement using arrow keys: A moves the tank left (decrements the tank_x register by 4 pixels per clock cycle), D moves right (increments tank_x by 4), and W fires a bullet upward. The tank cannot move beyond screen boundaries (X must remain between 0 and 600).
As the game progresses, aliens move downward at a constant rate controlled by a movement counter. Every 8 clock cycles, all alien Y-coordinates decrement by 2 pixels, creating the illusion of smooth descent. When the player presses W, a new bullet object is created at the current tank X position and begins moving upward at 5 pixels per cycle. The collision detection module runs combinatorially every cycle, comparing every bullet’s position against every alien’s position. The moment a bullet’s X-coordinate matches an alien’s X-coordinate (within a 10-pixel tolerance) AND the bullet’s Y-coordinate falls within the alien’s Y range (20 pixels tall), a collision is instantly detected. The alien is removed from the playfield, the bullet is destroyed, and the score increments by 100 points. Visual feedback occurs immediately—some implementations flash the hit location or change colors briefly.
The game continues until one of two end conditions occurs: (1) All aliens are destroyed, triggering LEVEL_ADVANCE—a brief 2-second pause displaying “LEVEL COMPLETE” before advancing to PLAYING_LEVEL_2 where aliens move 2× faster; or (2) Any alien reaches Y=450 (the tank position), triggering an immediate loss of life. The player begins with 3 lives. Each alien reaching the bottom costs one life. When lives reach 0, the game transitions to GAME_OVER, displaying the final score and waiting for the player to press the reset button (U) to return to START_SCREEN. The pause button (P) can freeze the game at any time, maintaining all entity positions and FSM state until pressed again.
Hardware Requirements
| Component | Specification | Where to Buy | Approx Price |
|---|---|---|---|
| FPGA Board | Basys3 (Artix-7 XC7A35T) | Digilent.com, Amazon, RS Components | $99-120 USD |
| VGA Monitor | Any 640×480+ display with VGA input | Local electronics, eBay, used market | $30-80 USD (used) |
| VGA Cable | 15-pin D-sub VGA cable, minimum 2m | Local computer shops, Amazon | $5-15 USD |
| PS/2 Keyboard | Standard PS/2 connection (purple connector) | Computer shops, eBay, local hardware stores | $10-25 USD |
| USB Power Cable | Micro-USB to USB-A (included with board) | Included; any USB power supply | Included / $5-10 |
| Development Tools | Vivado Design Suite (free WebPACK edition) | xilinx.com (free download) | Free |
Total Estimated Cost: $150-250 USD. The FPGA board is reusable for all 8 projects, so it’s a one-time investment. Monitors and keyboards may already be available.
Input Specification
Type of Controls
| Input | Action | Hardware Response |
|---|---|---|
| A Key (Hold) | Move tank left | tank_x ← tank_x – 4 (each cycle) |
| D Key (Hold) | Move tank right | tank_x ← tank_x + 4 (each cycle) |
| W Key (Press) | Fire bullet | Create bullet at (tank_x, 420) |
| U Button (Press) | Reset game | FSM → START_SCREEN, clear all |
| P Button (Press) | Pause/Resume | FSM → PAUSE_STATE / resume |
Control Details
Keyboard Input Processing: The PS/2 keyboard continuously transmits scan codes to the FPGA’s PS/2 interface module. The module converts these scan codes (which represent physical key positions) into ASCII values. The input handler monitors the ASCII values and sets digital flags: key_left, key_right, key_fire, key_pause, and key_reset. These flags persist as long as keys are held down, allowing smooth continuous movement.
Debouncing: Mechanical switches bounce—they make and break contact multiple times within a few milliseconds. Without debouncing, a single button press would register as multiple rapid presses. The debounce circuit uses a simple counter: after detecting an input transition, it waits 20ms (2,000,000 clock cycles at 100 MHz) before accepting another change. If the input returns to its original state within 20ms, it’s considered noise and ignored. Only changes that persist for 20ms are considered valid inputs.
Multi-key Handling: The FPGA can detect multiple simultaneous key presses. A player can hold A to move left while pressing W to fire, and both actions execute immediately. This simultaneous input handling is one of the advantages of parallel hardware logic versus sequential software execution.
FSM Diagram
FSM State Transition Diagram
FSM Transitions (Detailed List)
- START_SCREEN → PLAYING_LEVEL_1: Triggered when key_left OR key_right OR key_fire is high. Entry actions: Initialize alien array (24 aliens in 3×8 formation at Y=40,90,140), set tank_x=300 (center), set score=0, set lives=3, clear bullet array.
- PLAYING_LEVEL_1 → LEVEL_ADVANCE: Triggered when aliens_cleared signal is asserted (all aliens destroyed). Entry actions: Display “LEVEL CLEARED!” on screen, start 2-second timer, disable input processing.
- LEVEL_ADVANCE → PLAYING_LEVEL_2: Triggered when advance_timer reaches 2 seconds. Entry actions: Initialize level 2 aliens (same 3×8 formation but at Y=30,80,130), set alien_speed=5 pixels/cycle, set bullet_speed=6 pixels/cycle.
- PLAYING_LEVEL_1 → GAME_OVER: Triggered when (aliens_reached_bottom==TRUE) OR (lives==0). Entry actions: Display “GAME OVER” and final score, disable input except reset button.
- PLAYING_LEVEL_2 → GAME_OVER: Triggered when (aliens_reached_bottom==TRUE) OR (lives==0). Entry actions: Display “YOU WIN!” if all aliens cleared, OR “GAME OVER” if aliens reached bottom.
- PLAYING_LEVEL_1 ↔ PAUSE_STATE: Triggered when P_button pressed in PLAYING_LEVEL_1, player transitions to PAUSE_STATE. Triggered when P_button pressed in PAUSE_STATE, return to previous PLAYING state. During pause: game logic stops executing, display freezes at current frame, all entity positions held.
- Any State → START_SCREEN: Triggered when U_button pressed. Clears all entities, resets counters, resets lives and score.
FSM Implementation (Verilog Code)
// ===== FSM Parameter Definition =====
parameter START_SCREEN = 3'b000;
parameter PLAYING_LEVEL_1 = 3'b001;
parameter PLAYING_LEVEL_2 = 3'b010;
parameter LEVEL_ADVANCE = 3'b011;
parameter GAME_OVER = 3'b100;
parameter PAUSE_STATE = 3'b101;
// ===== State Registers =====
reg [2:0] current_state, next_state;
reg [31:0] state_timer;
reg level_advance_done;
// ===== Sequential Logic - State Updates =====
always @(posedge clk) begin
if (reset_button || power_on_reset)
current_state <= START_SCREEN;
else
current_state <= next_state;
end
// ===== Combinational Logic - Next State Determination =====
always @(*) begin
case (current_state)
START_SCREEN: begin
if (key_left || key_right || key_fire)
next_state = PLAYING_LEVEL_1;
else
next_state = START_SCREEN;
end
PLAYING_LEVEL_1: begin
if (aliens_cleared)
next_state = LEVEL_ADVANCE;
else if (aliens_reached_bottom || lives == 0)
next_state = GAME_OVER;
else if (pause_button)
next_state = PAUSE_STATE;
else
next_state = PLAYING_LEVEL_1;
end
LEVEL_ADVANCE: begin
if (state_timer > 200000000) // 2 seconds @ 100MHz
next_state = PLAYING_LEVEL_2;
else
next_state = LEVEL_ADVANCE;
end
PLAYING_LEVEL_2: begin
if (aliens_cleared)
next_state = GAME_OVER; // Win condition
else if (aliens_reached_bottom || lives == 0)
next_state = GAME_OVER; // Lose condition
else if (pause_button)
next_state = PAUSE_STATE;
else
next_state = PLAYING_LEVEL_2;
end
PAUSE_STATE: begin
if (pause_button)
next_state = (prev_state == PLAYING_LEVEL_1) ? PLAYING_LEVEL_1 : PLAYING_LEVEL_2;
else
next_state = PAUSE_STATE;
end
GAME_OVER: begin
if (reset_button)
next_state = START_SCREEN;
else
next_state = GAME_OVER;
end
default: next_state = START_SCREEN;
endcase
end
// ===== State Timer Management =====
always @(posedge clk) begin
if (current_state != LEVEL_ADVANCE)
state_timer <= 32'd0;
else
state_timer <= state_timer + 1'b1;
end
Output Specification
VGA Display Details
| Parameter | Specification |
|---|---|
| Resolution | 640×480 pixels @ 60 Hz refresh rate (pixel clock ~25 MHz) |
| Color Depth | 12-bit RGB (4 bits Red, 4 bits Green, 4 bits Blue) |
| Sync Signals | Horizontal sync (Hsync): 31.5 kHz, Vertical sync (Vsync): 60 Hz |
| Game Area | Y=30 to Y=470 (440 pixels playable height) |
| Top HUD Bar | Y=0 to Y=29: Score (left), Level (center), Lives (right) |
Display Information Breakdown
Color Palette: Tank = RGB (0000_1111_1111) Blue, Aliens = RGB (1111_0000_1111) Pink/Magenta, Bullets = RGB (1111_1111_1111) White, Background = RGB (0000_0000_0000) Black
Sensor Integration
Space Force X uses digital keyboard input only—no analog sensors are integrated. The PS/2 keyboard interface is fully digital, receiving scan codes as serial data over a synchronous clock line. Future enhancements could integrate analog joystick input through ADC (Analog-to-Digital Converter) modules, but the baseline project uses only the keyboard for simplicity and to focus on core game logic.
Game Flow Diagram
Logic Components & Concepts
Implementation Details
Space Force X requires multiple hardware modules working in concert. Each module has a specific responsibility and communicates with others through well-defined interfaces. This modular approach mirrors professional embedded system design.
Building Blocks
1. Input Handler Module — Receives PS/2 scan codes, converts to ASCII, maintains key press registers. Output: key_left, key_right, key_fire, key_pause, key_reset signals.
2. Game Logic Module — Processes movement, updates entity coordinates, manages game state. Combines: tank position updater, alien position updater, bullet position updater, scoring counter.
3. Collision Detection Module — Compares bullet and alien positions every cycle, determines hits. Output: collision_detected, alien_to_remove, bullet_to_remove signals.
4. Display Render Module — For each pixel (X,Y), determines correct color. Reads current entity positions from game logic, outputs 12-bit RGB color.
5. VGA Timing Module — Generates horizontal and vertical sync signals, coordinates pixel clock with display refresh. Synchronizes display rendering to VGA standard.
Connecting Modules Together
Working of Main Modules
Input Handler Module Operation: The PS/2 keyboard port sends data serially: one start bit, 8 data bits (the scan code), one parity bit, and one stop bit, all synchronized to a keyboard clock line. The input handler captures these bits into a shift register. When a complete byte is received (verified by parity check), it’s converted to ASCII. The ASCII value is latched into registers for key_left, key_right, key_fire, etc. These registers persist until a key-release code is received, allowing continuous key sensing.
Game Logic Module Operation: Every clock cycle, the game logic checks the current FSM state. In PLAYING states, it reads the input registers (key_left, key_right, key_fire). If key_left is asserted and tank_x > 0, it decrements tank_x by 4. If key_right is asserted and tank_x < 600, it increments tank_x by 4. If key_fire is asserted and no bullet currently exists, it creates a new bullet at the current tank_x position. Alien positions are decremented every 8 clock cycles (using a modulo-8 counter). Score is incremented by the collision detection module's collision_increment signal.
Collision Detection Module Operation: This module is purely combinational—it needs no clock or state. Every clock cycle, it simultaneously compares every bullet position against every alien position. The logic is: for each bullet-alien pair, if (bullet_x within ±10 of alien_x) AND (bullet_y >= alien_y AND bullet_y <= alien_y+20), then collision = true. When a collision is found, the module sets collision_detected=1 and outputs the IDs of the bullet and alien to remove. The game logic module then removes these entities in the next clock cycle.
Obstacle & Collision Detection
Collision Algorithm: The collision detection uses a distance-based approach for circular objects (aliens) and rectangular boundary checking for the tank. For each bullet (modeled as a 2D point), the algorithm checks every alien (modeled as a circle with radius 10 pixels). The collision condition is:
collision = (|bullet_x - alien_x| < 10) AND (bullet_y >= alien_y) AND (bullet_y <= alien_y + 20)
Boundary Detection: The tank cannot move beyond X=0 or X=600 (leaving a 40-pixel margin from the 640-pixel width). This is enforced by the game logic: before updating tank_x, it checks boundaries.
if (key_left AND tank_x > 0) then tank_x <= tank_x - 4
if (key_right AND tank_x < 600) then tank_x <= tank_x + 4
Alien Reach Detection: After each alien position update, the game logic checks if any alien has reached Y >= 450. If so, the aliens_reached_bottom signal is asserted, triggering the FSM transition to GAME_OVER.
Working of Main Idea with Pseudocode
Core Game Loop Pseudocode:
// ===== MAIN GAME LOOP (executes every clock cycle) =====
if (current_state == PLAYING_LEVEL_1 OR current_state == PLAYING_LEVEL_2) then
// ===== INPUT PROCESSING =====
if (key_left AND tank_x > 0) then
tank_x <= tank_x - 4
else if (key_right AND tank_x < 600) then
tank_x <= tank_x + 4
end if
if (key_fire AND bullet_count < MAX_BULLETS) then
create_bullet(tank_x, 420)
bullet_count <= bullet_count + 1
end if
// ===== POSITION UPDATES =====
for each active_bullet do
bullet.y <= bullet.y - BULLET_SPEED
if (bullet.y < 0) then
destroy_bullet()
end if
end for
// Alien movement (every 8 cycles)
alien_move_counter <= alien_move_counter + 1
if (alien_move_counter == 8) then
for each active_alien do
alien.y <= alien.y + ALIEN_SPEED
end for
alien_move_counter <= 0
end if
// ===== COLLISION DETECTION (Combinational) =====
for each bullet in bullets do
for each alien in aliens do
if (collision_detected(bullet, alien)) then
mark_bullet_for_removal(bullet)
mark_alien_for_removal(alien)
score <= score + 100
end if
end for
end for
// Remove marked entities
remove_all_marked_bullets()
remove_all_marked_aliens()
// ===== WIN/LOSE CONDITION CHECKS =====
if (aliens_cleared) then
FSM_state <= LEVEL_ADVANCE
end if
if (aliens_reached_bottom) then
lives <= lives - 1
if (lives == 0) then
FSM_state <= GAME_OVER
else
reset_level()
end if
end if
end if
Rendering Display and Logic Implementation
Display Rendering Pipeline: The VGA module generates pixel coordinates (pixel_x, pixel_y) as it scans the display. For each coordinate, the render module determines the correct color to display. This is a purely combinational process — no registers, no state, just logic gates making instant decisions.
// ===== DISPLAY RENDERING (Combinational - no clock) =====
assign pixel_color = (is_in_score_bar) ? render_score_text :
(is_in_tank) ? BLUE :
(is_in_bullet) ? WHITE :
(is_in_alien) ? PINK :
BLACK;
// ===== Detailed Pixel Decision Logic =====
wire is_in_tank = (pixel_x >= tank_x) AND (pixel_x <= tank_x + 40) AND
(pixel_y >= 450) AND (pixel_y <= 480);
wire is_in_bullet = distance(pixel_x, pixel_y, bullet_x, bullet_y) < 2;
wire is_in_alien = distance(pixel_x, pixel_y, alien_x, alien_y) < 15;
// ===== Color Definitions =====
parameter BLUE = 12'b0000_1111_1111;
parameter PINK = 12'b1111_0000_1111;
parameter WHITE = 12'b1111_1111_1111;
parameter BLACK = 12'b0000_0000_0000;
parameter GREEN_TEXT = 12'b0000_1111_0000;
Key Algorithms
- Debounce Algorithm: Counter-based debounce using 20ms wait. Prevents noise from switch bouncing from generating multiple input events.
- Collision Detection Algorithm: O(n×m) brute-force comparison of all bullets against all aliens. Acceptable because n,m are small (≤20 each).
- Movement Update Algorithm: Position-based movement using registers. Each entity stores X,Y coordinates as integers. Movement is calculated as: new_position = old_position ± speed.
- FSM State Machine Algorithm: Mealy machine with current state register and next state combinatorial logic. Transitions occur on clock edges.
- Pixel Rendering Algorithm: Hierarchical color selection using nested ternary operators. Evaluates entity containment in priority order: score bar → tank → bullets → aliens → background.
Complex Logic
Multi-entity Collision System: The most complex logic is the simultaneous collision detection across all bullet-alien pairs. With up to 20 bullets and 24 aliens, this requires 480 parallel comparisons each clock cycle. Rather than sequential checking, the hardware performs all comparisons instantly using combinational logic. If any pair collides, the collision signals are asserted immediately.
Synchronized Display Pipeline: The display rendering must stay perfectly synchronized with the VGA timing signals. The VGA module generates Hsync (horizontal) and Vsync (vertical) signals at precise intervals. The pixel colors must be valid at exactly the right time. Any timing violation causes visual artifacts (tearing, flickering). This synchronization is achieved through careful clock domain management and pipelining.
State Transition Logic: The FSM transition logic must handle multiple simultaneous conditions. For example, in PLAYING_LEVEL_1, the next state depends on: aliens_cleared, aliens_reached_bottom, lives_remaining, and pause_button. The combinational logic must evaluate all conditions and select the correct next state. Priority is encoded through the case statement order.
Expected Screen Outputs
Difficulty Progression
| Level | Alien Formation | Alien Speed | Bullet Speed | Difficulty Curve |
|---|---|---|---|---|
| Level 1 | 8×3 = 24 aliens | 2 px/cycle, every 8 cycles | 5 px/cycle upward | ⭐ Introductory |
| Level 2 | 8×3 = 24 aliens | 4 px/cycle, every 5 cycles | 6 px/cycle upward | ⭐⭐ Moderate |
| Level 3+ (Future) | 10×4 = 40 aliens | 6 px/cycle, every 3 cycles | 7 px/cycle upward | ⭐⭐⭐ Challenging |
Key Hardware Utilization
| Resource | Usage | Available (Basys3) | % Utilized |
|---|---|---|---|
| LUT (Look-Up Tables) | ~3,600 | 20,800 | 17% |
| FF (Flip-Flops/Registers) | ~400 | 41,600 | 1% |
| IO Blocks | ~25 | 210 | 12% |
| BUFG (Global Buffers) | ~8 | 32 | 25% |
LUT Usage Breakdown: Collision detection logic uses ~40%, Display rendering uses ~35%, Game logic/FSM uses ~25%. The project is resource-efficient, leaving 83% of LUTs available for enhancements.
8-Week Implementation Breakdown
| Week | Module | Tasks | Deliverables | Est. Hours |
|---|---|---|---|---|
| Week 1 | VGA Timing & Sync |
• Study VGA standard timing • Implement horizontal sync generator • Implement vertical sync generator • Implement pixel counter |
Working VGA sync signals verified with oscilloscope | 20 |
| Week 2 | Display Color Output |
• Implement color ROM/combinational logic • Connect 12-bit RGB to VGA DAC • Display solid colors (test pattern) • Test on monitor |
Colored rectangles displaying on monitor, no artifacts | 18 |
| Week 3 | Keyboard Input |
• Study PS/2 protocol • Implement PS/2 receiver • Implement scan code to ASCII converter • Add debounce circuit • Test key detection |
LEDs on FPGA board toggle with key presses | 22 |
| Week 4 | Entity Rendering |
• Implement tank sprite rendering • Implement alien sprite rendering • Implement bullet rendering • Test all sprites on display |
Tank, aliens, bullets visible on screen in correct colors | 20 |
| Week 5 | Entity Movement |
• Implement tank movement logic • Implement bullet movement • Implement alien movement with counter • Test smooth animation |
Tank moves smoothly with A/D keys, aliens descend, bullets ascend | 18 |
| Week 6 | Collision Detection |
• Implement collision comparator • Test bullet-alien collision • Test entity removal on hit • Verify no false positives |
Hitting aliens removes them, scoring works correctly | 20 |
| Week 7 | FSM & Game Logic |
• Implement FSM state machine • Implement game state transitions • Implement win/lose conditions • Implement pause/resume • Test all state paths |
Complete game flow: start → play → advance/game over → reset | 22 |
| Week 8 | Polish & Optimize |
• Score/Lives display • Level indicator • Game over screen • Edge case testing • Performance optimization • Demo & documentation |
Fully playable game, documentation complete, ready for showcase | 16 |
Total Implementation Time: ~156 hours spread over 8 weeks. This includes design, coding, testing, debugging, and iteration.
End of Project 1 detailed guide. Projects 2-8 coming with equal comprehensive documentation.