Playable Doom arrives on a custom built RISC-V platform

Doom has turned up on plenty of strange hardware over the years. Calculators. Cameras. Printers. Even devices that were never meant to run a game at all. This project is different. Armaan Gomes and his team didn’t simply squeeze Doom onto an unusual gadget. They built the processor first. Then they made the game run on it. The result is a playable version of Doom running on a custom five-stage RISC-V CPU, designed at logic-gate level and implemented on an FPGA. The system also includes external memory, caches, video output, keyboard controls and the supporting hardware needed to turn a processor experiment into a working gaming platform. That’s a serious engineering job.

Doom has turned up on plenty of strange hardware over the years. Calculators. Cameras. Printers. Even devices that were never meant to run a game at all. This project is different. Armaan Gomes and his team didn’t simply squeeze Doom onto an unusual gadget. They built the processor first. Then they made the game run on it. The result is a playable version of Doom running on a custom five-stage RISC-V CPU, designed at logic-gate level and implemented on an FPGA. The system also includes external memory, caches, video output, keyboard controls and the supporting hardware needed to turn a processor experiment into a working gaming platform. That’s a serious engineering job.

Building a RISC-V processor from the ground up

The processor uses a subset of the open RISC-V instruction set and follows a classic five-stage pipeline. Instructions move through fetch, decode, register access, execution and writeback. On paper, that sounds tidy. Real hardware isn’t.

The team had to deal with data hazards, branch changes, cache behaviour, memory delays and communication between parts of the system running at different clock speeds. A mistake in any one of those areas could freeze the game, corrupt an instruction or send the processor jumping to the wrong place in memory. Earlier versions of the CPU had already run smaller projects, including Pong and Mandelbrot calculations. Doom demanded much more.

The game’s shareware data file takes up roughly 14 MB. The FPGA had less than 1 MB of fast on-chip block RAM available. That meant the team couldn’t keep everything close to the processor. They had to use external DDR3 memory instead. DDR3 gave them the required capacity, but it also introduced delays.

Without a cache, the CPU would spend far too much time waiting for instructions and game data to arrive. So the team added separate instruction and data caches. They also built a memory arbiter to manage requests when both caches needed access at the same time. Data-cache traffic received priority. That choice helped keep the game moving when the processor needed to read or update active game data.

Making the hardware behave like a real computer

A working CPU isn’t enough to run Doom. The game also needs a display, controls, timing information and some way to report errors. The team connected these features through memory-mapped input and output. From the software’s point of view, talking to a keyboard or screen looked similar to reading and writing memory.

The video system supported 12-bit colour and sent the image through HDMI. Keyboard input came from a laptop over UART because the board’s USB setup wasn’t suitable for direct control. The same serial connection also helped with debugging. That debugging channel mattered.

When Doom crashed, the cause wasn’t obvious. The software might be wrong. The processor might be wrong. The cache might have returned bad data. A timer could be behaving differently from what the code expected. Small test programs hadn’t exposed every problem. Doom did.

The team found incorrect immediate values, failed cache writebacks, damaged instructions and unexpected jumps. One bug came from the game assuming that uninitialised memory contained zeroes. Simulations had hidden the issue because the simulated memory happened to behave that way. Once the team filled memory with random values, the failure appeared. That matched what they were seeing on the FPGA and gave them a clear route to a fix.

From barely moving to genuinely playable

The first successful run reached just 0.7 frames per second. It worked. Barely. At that speed, Doom looked more like a slideshow than a game. The team then began improving the hardware and software step by step. They increased the processor clock from 100 MHz to 125 MHz and reworked the instruction-fetch stage. Performance climbed to around 2.5 fps.

Next came hardware multiplication support. That moved the processor closer to an RV32I-Zmmul design and pushed the game to roughly 3.5 fps. The team then changed how the game wrote image data to the display. Instead of passing everything through a slower route, Doom wrote directly into the video controller’s block memory. Faster pipelined cache hits helped too. That brought the frame rate to about 6.7 fps.

The biggest improvement didn’t come from new hardware. It came from the compiler. The team had built Doom with optimisation switched off. Turning optimisation on should have made the code faster, but it caused crashes instead. The problem came from the hardware timer pointer, which hadn’t been marked as volatile. The compiler looked at some timer reads and decided they weren’t needed. So it removed them. Once the team corrected that issue, the optimised version reached around 15 to 20 fps. That’s not modern gaming performance, but it’s fast enough to play Doom properly.

Why this RISC-V Doom project stands out

This build shows what makes RISC-V useful for custom processor work. Designers can start with a basic instruction set, test it with real software and add features when the workload exposes a weakness. Doom gave this CPU nowhere to hide.

It tested the processor pipeline, memory system, caches, display hardware, keyboard input, timers, compiler settings and software port at the same time. A small benchmark might confirm that an instruction works. Doom shows whether the whole machine works.

The team now plans to chase higher performance with features such as out-of-order execution and faster memory handling. For the moment, though, the result already speaks for itself. They built a CPU. They loaded Doom. And after a long list of hardware and software fixes, they made it playable.

Spread the love
error: