Skip to the content
PCBKitNew board
2 layers92 × 64 mmCarrier, the printed circuit board in 3D

First-Person Gate Array (FPGA): a DOOM-like first-person shooter built entirely in VHDL on a Cmod A7-35T. Raycast 3D, monsters, sound and PS/2 input, all in hardware with no CPU.

Size
92 × 64 mm
Copper layers
2
Thickness
1.6 mm
Parts
14
Nets
62
Pads
114
Tracks, vias
123, 34
Pours
2
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
22 Oct 2026
Updated
25 Oct 2026

Overview

Carrier is an open-source printed circuit board by s0b0s, from the s0b0s/first-person-gate-array repository on GitHub. It is a 2-layer board of 92 × 64 mm with 14 parts on 62 nets, routed with 123 tracks and 34 vias.

It belongs with the audio and music and fPGA and programmable logic boards of this library.

README

README.md

First-Person Gate Array

A first-person shooter built entirely out of digital logic on a small FPGA board. There is no processor anywhere in the design: no soft CPU in the FPGA and no microcontroller on the side. The 3D renderer, the monsters, the game rules, the keyboard and mouse interface and the sound are all state machines and memories written in VHDL.

What the game is

You walk through a textured 3D maze, open doors, pick up keys, health, ammo and weapons, and fight monsters that see you, chase you and shoot back. There are three levels, the last one ending with a boss. Later levels have rooms with different floor and ceiling heights, steps, ramps and pits, flickering and glowing lights, outdoor areas with a sky, and animated slime walls. Firing a gun makes noise that wakes up monsters in nearby rooms, unless they are set to lie in ambush.

The screen also shows a status bar, a minimap and a full-screen automap, along with title, briefing and score screens. Sound effects and music play in stereo.

How it runs

  • Board: Digilent Cmod A7-35T (a Xilinx Artix-7 FPGA with 512 KB of external SRAM and 4 MB of flash).
  • Video: 320x240 pixels, each drawn as a 2x2 block on a standard 640x480, 60 Hz VGA monitor through a Digilent Pmod VGA. Colors come from a 256-entry palette.
  • Input: a PS/2 keyboard and a PS/2 mouse through two Digilent Pmod PS2 boards.
  • Sound: stereo through a Digilent Pmod I2S2 to headphones.
  • Boot: the design and all game data load from the board's flash at power-up, so no PC is needed.

The modules plug into a small custom carrier PCB. Inside the FPGA, the main blocks are:

BlockWhat it does
Ray engineCasts one ray per screen column through the tile map to find the walls
Column rasterizerDraws each column: walls, floors, ceilings, sky, lighting
Sprite engineDraws monsters, items and projectiles, hidden correctly behind walls
OverlayStatus bar, minimap, automap and text screens
Game corePlayer movement, collision, doors, monsters, weapons, pickups, levels
Display controllerReads the finished frame from SRAM and sends it to the monitor
PS/2 hostTalks to the keyboard and mouse
Audio mixerMixes 8 sound effect voices and a music track
SRAM and flash controllersShared memory access and loading game data at boot

Two frames are kept in SRAM: the game draws the next frame into one while the monitor shows the other. A frame takes about 3 to 6 ms to draw out of the 16.7 ms available at 60 Hz.

Controls

ActionKeys
Move forward / backW / S, or the up / down arrows
StrafeA / D
TurnMouse, or the left / right arrows
FireLeft click, or Ctrl
Use (doors, switches)Space
RunShift
DuckHold C
Peek left / rightHold Q / E
Weapons1, 2, 3, or right click to cycle
AutomapTab
PauseEsc

Development stages

The design was built in stages, each ending in a working bitstream, and comments in the code refer to them:

StageWhat it addedTop level
0Bring-up: test patterns, SRAM and flash tests, raw keyboard and mouse codes, test tone, UARTbringup_top
1A textured maze to walk through, with doors and collisiongame_top
2 and 3The full game: monsters, weapons, items, keys, HUD, maps, sound, three levelsshooter_top
4Floor and ceiling heights, steps, ramps, light effects, sky, animated wallsshooter_top
5Monsters woken by gunfire, and ambushing monstersshooter_top

How it was checked

A Python model of the whole game (in tools/model/) is the reference. It generates the textures, levels and sounds, and it produces "golden" outputs: whole frames, game states and audio samples. Every hardware block has a self-checking simulation testbench that compares its output with the model, pixel for pixel and bit for bit. The largest test boots the complete design from a simulated flash chip and plays a scripted session.

Repository layout

FolderContents
rtl/The hardware design (VHDL), one block per file
sim/Simulation testbenches and models of the SRAM, flash, keyboard, mouse and monitor
constraints/Pin assignments and timing constraints for the board
scripts/Build the bitstream and run the simulations
tools/Python: the game model, asset generators, flash image builder, style checkers, PC debug tools
assets/levels/Text pictures of the three level maps, written by the model, so a person can read the levels
build/Everything generated (not kept in git)

Building

You need Vivado 2025.1 (its simulator, xsim, runs the testbenches) and Python 3.9 or newer. The Python tools use only the standard library, so building and simulating need no packages. The one exception is the UART debug tool (tools/uart/debug_uart.py), which needs pyserial. Either install it with pip install -r requirements.txt, or, if you use uv, run that script as uv run tools/uart/debug_uart.py ... and uv fetches pyserial by itself. Run everything from the repository root.

On a fresh clone, run the first two steps before anything else. They write the art, level and game-data files into build/, which the testbenches and the flash image read.

StepCommand
Generate the assets, ROM contents and test datapython tools/model/build_assets.py
Build the flash game-data imagepython tools/flash_image/make_gamedata.py
Run every testbench (about 30 minutes; most of it is the full-boot test)python scripts/run_sim.py
Run some testbenchespython scripts/run_sim.py tb_sram tb_ray_engine
Check the code stylepython tools/style/check_vhdl_style.py and python tools/style/check_vhdl_structure.py
Build the bitstream and flash imagevivado -mode batch -source scripts/build.tcl -tclargs shooter_top

The build writes build/shooter_top/shooter_top.bit (to load straight into the FPGA) and shooter_top.mcs (to program into flash, so the game boots on its own). Two smaller designs build the same way: bringup_top shows test pages for checking the board and its wiring, and game_top is the first playable maze.

Art and sound

All textures, sprites, sounds and music are original, generated by the Python scripts in tools/model/. No assets from other games are used.

Parts

14
QtyValueFootprintReferences
4MountingHoleMountingHole:MountingHole_3.2mm_M3H1, H2, H3, H4
13V3_INConnector_PinSocket_2.54mm:PinSocket_1x02_P2.54mm_VerticalJ10
1CMOD_A_DIP1-24Connector_PinSocket_2.54mm:PinSocket_1x24_P2.54mm_VerticalJ1
1CMOD_B_DIP25-48Connector_PinSocket_2.54mm:PinSocket_1x24_P2.54mm_VerticalJ2
1I2S2carrier:PinSocket_2x06_P2.54mm_Horizontal_Edge2mmJ5
1PS2_KEYBOARDcarrier:PinSocket_1x06_P2.54mm_Horizontal_Edge2mmJ7
1PS2_MOUSEcarrier:PinSocket_1x06_P2.54mm_Horizontal_Edge2mmJ6
1SHIFT_HVConnector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_VerticalJ9
1SHIFT_LVConnector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_VerticalJ8
1VGA_J1carrier:PinSocket_2x06_P2.54mm_Horizontal_Edge2mmJ4
1VGA_J2carrier:PinSocket_2x06_P2.54mm_Horizontal_Edge2mmJ3

Questions

How big is the Carrier PCB?

It measures 92 × 64 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Carrier use?

14 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Carrier KiCad files?

From the s0b0s/first-person-gate-array repository on GitHub, at the commit this page was made from: the board is pcb/carrier.kicad_pcb and its schematic pcb/carrier.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Carrier design in my own project?

Its repository states no licence, so its author keeps all rights: ask s0b0s before reusing the design.

Similar boards

  • 2 layers116.8 × 30 mmType d, the printed circuit board in 3D

    Type d

    google/mozc-devices

    Circuit diagrams and firmware source code for Gboard DIY keyboards

    14 parts3kApache-2.0
  • 2 layers32 × 22 mmDiff driver, the printed circuit board in 3D

    Diff driver

    rene-dev/stmbl

    AC Servo Driver for STM32F4

    14 parts990GPL-3.0
  • 2 layers34 × 45 mm2032Charger, the printed circuit board in 3D

    2032Charger

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    14 parts915
  • 2 layers34 × 109.9 mmTdisplay s3, the printed circuit board in 3D

    Tdisplay s3

    landonr/homeThing

    Wifi Smart Home Remotes that run on ESPHome

    14 parts551GPL-3.0
  • 2 layers45.3 × 42.7 mmMainPcb, the printed circuit board in 3D

    MainPcb

    adamb314/ServoProject

    Getting the most out of your hobby servo

    14 parts545
  • 2 layers42.5 × 28.8 mmC5VRX JACK DIY, the printed circuit board in 3D

    C5VRX JACK DIY

    Twotoz/C5VRX

    Ultra-minimal, zero-CPU 5.8 GHz analog FPV video receiver using ESP32-C5 Wi-Fi 6 PHY MODEM_DIAG, BitScrambler WBFM demodulation & resistor DAC CVBS

    14 parts515GPL-3.0
  • 2 layers62 × 24 mmMai button, the printed circuit board in 3D

    Mai button

    whowechina/mai_pico

    Pico controller for Maimai

    14 parts475