Project 20: Pong Game on VGA

Implement a Pong game with VGA output and paddle control.

Quick Reference

Attribute Value
Difficulty Expert
Time Estimate 2-3 weeks
Main Programming Language Verilog (Alternatives: VHDL, SystemVerilog)
Alternative Programming Languages VHDL, SystemVerilog
Coolness Level Very High
Business Potential Low
Prerequisites VGA timing, FSMs, Collision logic
Key Topics Frame ticks, Collision, Rendering

1. Learning Objectives

  1. Update game state per frame
  2. Render sprites in VGA space
  3. Implement collision and scoring

2. All Theory Needed (Per-Concept Breakdown)

VGA Timing and Scan Counters

Description/Expanded Explanation of the concept

VGA displays pixels by scanning rows and columns at precise timing. Horizontal and vertical counters generate sync pulses and identify the visible region. If timing is wrong, the image rolls or flickers.

Definitions & Key Terms
  • Front porch / back porch -> blanking intervals around visible area
  • HSYNC/VSYNC -> sync pulses for horizontal and vertical timing
  • Pixel clock -> rate of pixel output
Mental Model Diagram (ASCII)
[visible] [front] [sync] [back] -> repeat

VGA timing segments

How It Works (Step-by-Step)
  1. Increment horizontal counter each pixel.
  2. When end-of-line reached, reset hcount and increment vcount.
  3. Generate HSYNC/VSYNC based on counter ranges.
  4. Output pixels only in visible region.
Minimal Concrete Example
visible = (hcount < 640) && (vcount < 480);
Common Misconceptions
  • “Any pixel clock works.” -> VGA requires exact timing.
  • “You can skip blanking.” -> Sync pulses must be correct.
Check-Your-Understanding Questions
  1. Why are porches required?
  2. What happens if HSYNC width is wrong?
  3. How do you compute total line length?
Where You’ll Apply It
  • This project: used in Section 3.2 and Section 4
  • Also used in: P20-pong-game-on-vga.md

Frame Rendering and Collision Logic

Description/Expanded Explanation of the concept

Games like Pong combine rendering and physics. A frame tick updates object positions; rendering logic draws shapes only inside the visible region. Collision detection can be done with simple bounding boxes.

Definitions & Key Terms
  • Frame tick -> periodic signal for game updates
  • Bounding box -> rectangular collision region
  • Sprite -> a drawn object
Mental Model Diagram (ASCII)
frame_tick -> update positions -> render -> output pixels

Frame tick render pipeline

How It Works (Step-by-Step)
  1. Update ball and paddle positions on frame tick.
  2. Clamp paddles to screen edges.
  3. Detect collisions via bounding boxes.
  4. Render pixels based on current positions.
Minimal Concrete Example
hit = (ball_x >= paddle_x) && (ball_x <= paddle_x + P_W);
Common Misconceptions
  • “Update logic every pixel.” -> Use frame ticks to stabilize motion.
  • “Collision requires heavy math.” -> Simple rectangles are enough.
Check-Your-Understanding Questions
  1. Why separate game update from rendering?
  2. How do you avoid tearing?
  3. What is a bounding box collision test?
Where You’ll Apply It
  • This project: used in Section 3.2 and Section 4
  • Also used in: P18-vga-pattern-generator.md (timing foundation)

Debouncing and Synchronizers

Description/Expanded Explanation of the concept

Mechanical buttons bounce: they produce multiple rapid transitions on a single press. Also, a button is asynchronous to your clock, so it can cause metastability. A synchronizer chain plus a stability counter creates a clean, single transition.

Definitions & Key Terms
  • Bounce -> rapid oscillation at a switch transition
  • Synchronizer -> chain of flip-flops to reduce metastability
  • Stable window -> required time with no changes
Mental Model Diagram (ASCII)
raw_btn -> FF -> FF -> stable_counter -> clean_btn

Debounce pipeline

How It Works (Step-by-Step)
  1. Synchronize the raw input with two flip-flops.
  2. Count how long the input stays the same.
  3. Once stable for N cycles, update the clean signal.
Minimal Concrete Example
if (sync_btn == stable_btn) count <= 0;
else count <= count + 1;
Common Misconceptions
  • “A button is just a logic input.” -> It is noisy and asynchronous.
  • “One flip-flop is enough.” -> Two are standard for safety.
Check-Your-Understanding Questions
  1. Why is metastability a risk with buttons?
  2. What is the trade-off between stability time and responsiveness?
  3. Why not debounce in software on an FPGA-only design?
Where You’ll Apply It
  • This project: used in Section 3.2 and Section 5
  • Also used in: P19-calculator-with-7-segment-display.md, P20-pong-game-on-vga.md

3. Project Specification

3.1 What You Will Build

A Pong game with VGA output, paddles, ball, and scoring.

3.2 Functional Requirements

  1. Requirement 1: Render ball and paddles
  2. Requirement 2: Handle paddle inputs
  3. Requirement 3: Detect collisions and update score

3.3 Non-Functional Requirements

  • Performance: Stable operation at the target clock and interfaces.
  • Reliability: Deterministic outputs on all defined inputs.
  • Usability: Clear ports and documented behavior.

3.4 Example Usage / Output

{p['example_usage']}

3.5 Data Formats / Schemas / Protocols

{p[‘data_format’]}

3.6 Edge Cases

  • Ball hitting corners
  • Paddle at screen edge

3.7 Real World Outcome

3.7.1 How to Run (Copy/Paste)

vvp pong_tb

3.7.2 Golden Path Demo (Deterministic)

Run the demo command above with the provided testbench and confirm the outputs match the golden transcript.

3.7.3 CLI Transcript

Screen shows ball and paddles
Score increments on miss

3.7.4 Failure Demo (Expected)

# Example failure case
ERROR: Output mismatch at vector 3
Expected: 0x0A, Got: 0x0B
EXIT CODE: 1

Notes:

  • Exit code 0 indicates all tests passed
  • Exit code 1 indicates a test failure

4. Solution Architecture

4.1 High-Level Design

[inputs] -> [core logic] -> [outputs]

Core logic flow

4.2 Key Components

Component Responsibility
vga_core VGA timing generator
game_logic Ball/paddle updates
renderer Pixel generation

4.3 Data Structures (No Full Code)

// Example signals (adapt to your design)
reg [7:0] state_reg;
reg [7:0] data_reg;

4.4 Algorithm Overview

Key Algorithm: Core control flow

  1. Initialize state/reset conditions.
  2. Apply inputs and compute outputs.
  3. Update state on clock edges (if sequential).

Complexity Analysis:

  • Time: O(1) per cycle
  • Space: O(N) for registers and logic

5. Implementation Guide

5.1 Development Environment Setup

iverilog -v
# Ensure GTKWave is installed for waveform viewing

5.2 Project Structure

project-root/
|-- src/
|   |-- top.v
|   |-- core.v
|-- tb/
|   |-- tb.v
|-- Makefile
|-- README.md

Project folder structure

5.3 The Core Question You’re Answering

“How do you build a real-time interactive system purely in hardware?”

5.4 Concepts You Must Understand First

  • VGA timing
  • FSMs
  • Collision logic

5.5 Questions to Guide Your Design

  • Update every frame or every N frames?
  • How will you limit paddle speed?

5.6 Thinking Exercise

Simulate ball position updates for 5 frames.

5.7 The Interview Questions They’ll Ask

  • Why use a frame tick?
  • How do you avoid tearing?

5.8 Hints in Layers

  • Start with static paddles and moving ball.
  • Add collision detection after rendering works.

5.9 Books That Will Help

Topic Book Chapter
Graphics basics Computer Graphics from Scratch Ch. 1-2

5.10 Implementation Phases

Phase 1: Foundation

Goals:

  • Establish core module structure
  • Implement minimal behavior

Tasks:

  1. Scaffold module ports and internal signals
  2. Write a minimal testbench that compiles

Checkpoint: Simulation runs without errors

Phase 2: Core Functionality

Goals:

  • Implement full logic
  • Verify edge cases

Tasks:

  1. Complete core logic
  2. Add directed tests for edge cases

Checkpoint: All tests pass and waveforms match expectations

Phase 3: Polish & Edge Cases

Goals:

  • Improve readability
  • Document behavior

Tasks:

  1. Add comments and README notes
  2. Expand tests for unusual inputs

Checkpoint: Design is deterministic and documented

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Reset strategy Sync / Async Sync Simpler timing closure
Test coverage Directed / Exhaustive Exhaustive for small logic Prevents missed cases

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Unit Tests Test core logic Small vectors
Integration Tests Test modules together Full system
Edge Case Tests Boundary conditions Max/min values

6.2 Critical Test Cases

  1. Test 1: Ball stays within bounds
  2. Test 2: Score updates on miss

6.3 Test Data

Use deterministic vectors and document expected outputs.

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

Pitfall Symptom Solution
Flicker Drawing outside visible area Gate draw to visible region

7.2 Debugging Strategies

  • Inspect waveforms at key internal signals
  • Add temporary debug outputs to verify state
  • Reduce testcases to the smallest failing case

7.3 Performance Traps

  • Overly wide counters or combinational paths can reduce max clock

8. Extensions & Challenges

8.1 Beginner Extensions

  • Add parameterization for widths
  • Add optional features (enable, reset)

8.2 Intermediate Extensions

  • Add configuration registers
  • Build a simple driver or demo program

8.3 Advanced Extensions

  • Integrate with another project in this series
  • Implement a hardware demo on FPGA

9. Real-World Connections

9.1 Industry Applications

  • Digital control systems and embedded peripherals
  • FPGA prototyping and validation
  • Yosys / nextpnr toolchain for open-source FPGA flow
  • Example HDL projects in the FPGA community

9.3 Interview Relevance

  • Demonstrates RTL thinking and verification skills

10. Resources

10.1 Essential Reading

  • Computer Graphics from Scratch - Focus on Ch. 1-2

10.2 Video Resources

  • Search for project-specific HDL walkthroughs and waveforms

10.3 Tools & Documentation

  • Icarus Verilog
  • GTKWave
  • See adjacent projects in VERILOG_FROM_ZERO_PROJECTS/

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain the core concept without notes
  • I can predict waveform behavior for basic inputs

11.2 Implementation

  • All functional requirements are met
  • All tests pass
  • Edge cases are documented

11.3 Growth

  • I can explain this project in an interview
  • I documented at least one lesson learned

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Functional requirements implemented
  • Testbench passes
  • Waveforms inspected

Full Completion:

  • All minimum criteria plus
  • Edge cases covered and documented

Excellence (Going Above & Beyond):

  • Hardware demo on FPGA
  • Clear write-up of lessons learned

    Appendix A: Deep Dive Walkthrough

A.1 Signal Map and Timing Contract

  • Inputs: clk, reset, btn_up, btn_down
  • Outputs: hsync, vsync, rgb[2:0]

A.2 Game State Variables

  • ball_x, ball_y, vx, vy
  • paddle_y
  • score_left, score_right

A.3 Frame Tick Strategy

  • Update positions once per frame to avoid tearing.
  • Use frame_tick when hcount==0 && vcount==0.

A.4 Deterministic Test Plan

  • Simulate 10 frames with fixed initial velocity.
  • Verify ball bounces at borders and paddle.
  • Verify score increments when ball crosses boundary.

A.5 Debugging Tip

If ball flickers, ensure drawing is gated to the visible region only.

13. Deep Dive Appendix

13.1 Timing and Resource Budget

  • Use a frame tick (e.g., once per VSYNC) to update game state.
  • Rendering happens at pixel clock; game logic should be slower.
  • Collision checks are small, but keep them synchronized to the frame tick.

13.2 Waveform Interpretation Guide

  • Track frame_tick, ball_x, ball_y, and paddle_y.
  • Confirm that positions update only on frame tick, not every pixel.

Example:

frame_tick: 1 per frame
ball_x: 100,101,102,103...

13.3 Hardware Bring-Up Notes

  • Reuse the VGA generator from Project 18.
  • Map paddles to buttons or switches; debounce inputs.
  • If the ball flickers, check visible gating and sprite draw order.

13.4 Alternate Implementations and Trade-offs

  • Add simple AI for a single-player mode.
  • Implement acceleration so the ball speeds up over time.
  • Add sound with a PWM buzzer for hits and misses.

13.5 Additional Exercises

  • Add a scoreboard using a 7-seg overlay.
  • Add multi-ball mode for chaos.
  • Add a pause feature and game reset.