Coding for fun - the hard way. Trying to implement a Game Boyยฎ compatible machine with Verilog.
This project is an open source Game Boyยฎ compatible console Verilog RTL implementation.
The main system architecture is designed as follows (outdated):
There are three major parts needs to be implemented: the Game Boy CPU (8-bit CISC Processor called SM83, Intel 8080 like), the PPU (Pixel Processing Unit), and the sound unit (sometimes referred as a PSG, Programmable Sound Generator). Several interfacing modules are needed to support the IO capability provided by the hardware (such as an FPGA development board).
Current Pano Logic G1 is the only supported platform.
Refactoring in progress. Current version could run several commerical games with no noticable glitch on the Pano Logic G1 device. 'Master' branch contains the previous version that runs on the ML505.
- SM83 CPU (Refactoring stage 1 done, passes all Blargg's tests)
- PPU (Pixel Processing Unit, Pixel-FIFO architecture)
- OAMDMA (Object Attribute Memory DMA)
- PSG (Programmable Sound Generator)
- Timer
- Link (Dummy link module, allows some games to run in single player mode)
Next step would be improving the accuracy.
Photo of VerilogBoy on Pano G1 running open source GameBoy game Tobu Tobu Girl:
For progress regarding different ports, view README.md under the specific target folder.
This project is not built to be entirely accurate, but built with accuracy in mind. Most of the CPU timing should follow the original DMG-CPU, and implement a rudimentary 2-stage pipelining just as the original one does.
Here are the results of several tests I have tried to run on it.
PPU implementation is ... wrong: There are two pipelines in the GameBoy PPU, one for BG and one for sprite. I only implemented one for both. There is only one fetcher, though.
Note: Tests which depends on the revision / model of GameBoy are omitted. VerilogBoy only focus on behaviors that are common among all monochrome GameBoys (GS).
Test | mooneye-gb | BGB | Gambatte | Higan | MESS | VerilogBoy |
---|---|---|---|---|---|---|
cpu instrs | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
Notes: other tests hasn't been tried.
Test | mooneye-gb | BGB | Gambatte | Higan | MESS | VerilogBoy |
---|---|---|---|---|---|---|
add sp e timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
call timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
call timing2 | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
call cc_timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
call cc_timing2 | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
di timing GS | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
div timing | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
ei sequence | ๐ | ๐ | ๐ | ๐ | โ | ๐ |
ei timing | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
halt ime0 ei | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
halt ime0 nointr_timing | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
halt ime1 timing | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
halt ime1 timing2 GS | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
if ie registers | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
intr timing | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
jp timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
jp cc timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
ld hl sp e timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
oam dma_restart | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
oam dma start | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
oam dma timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
pop timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
push timing | ๐ | โ | โ | ๐ | ๐ | ๐ |
rapid di ei | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
ret timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
ret cc timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
reti timing | ๐ | โ | ๐ | ๐ | ๐ | ๐ |
reti intr timing | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
rst timing | ๐ | โ | โ | ๐ | ๐ | ๐ |
Test | mooneye-gb | BGB | Gambatte | Higan | MESS | VerilogBoy |
---|---|---|---|---|---|---|
daa | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
Test | mooneye-gb | BGB | Gambatte | Higan | MESS | VerilogBoy |
---|---|---|---|---|---|---|
ie push | ๐ | โ | โ | โ | โ | ๐ |
Test | mooneye-gb | BGB | Gambatte | Higan | MESS | VerilogBoy |
---|---|---|---|---|---|---|
basic | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
reg_read | ๐ | ๐ | ๐ | โ | โ | ๐ |
sources dmgABCmgbS | ๐ | ๐ | โ | โ | โ | โ |
Test | mooneye-gb | BGB | Gambatte | Higan | MESS | VerilogBoy |
---|---|---|---|---|---|---|
boot sclk align dmgABCmgb | โ | ๐ | ๐ | โ | โ | โ |
Note: this test only seems to test the time to finish the first transfer. What about the second? (Delta time required to do a transfer and get notified by the interrupt)
Test | mooneye-gb | BGB | Gambatte | Higan | MESS | VerilogBoy |
---|---|---|---|---|---|---|
hblank ly scx timing GS | ๐ | ๐ | โ | โ | ๐ | โ |
intr 1 2 timing GS | ๐ | ๐ | ๐ | ๐ | ๐ | โ |
intr 2 0 timing | ๐ | ๐ | โ | ๐ | ๐ | โ |
intr 2 mode0 timing | ๐ | ๐ | โ | โ | ๐ | โ |
intr 2 mode3 timing | ๐ | ๐ | โ | โ | ๐ | โ |
intr 2 oam ok timing | ๐ | ๐ | โ | โ | ๐ | โ |
intr 2 mode0 timing sprites | โ | ๐ | โ | โ | ๐ | โ |
lcdon timing dmgABCmgbS | โ | ๐ | โ | โ | โ | โ |
lcdon write timing GS | โ | ๐ | โ | โ | โ | โ |
stat irq blocking | โ | ๐ | ๐ | โ | ๐ | โ |
stat lyc onoff | โ | ๐ | โ | โ | โ | โ |
vblank stat intr GS | ๐ | ๐ | โ | ๐ | ๐ | โ |
Test | mooneye-gb | BGB | Gambatte | Higan | MESS | VerilogBoy |
---|---|---|---|---|---|---|
div write | ๐ | ๐ | โ | ๐ | ๐ | ๐ |
rapid toggle | ๐ | ๐ | โ | โ | ๐ | ๐ |
tim00 div trigger | ๐ | ๐ | ๐ | โ | ๐ | ๐ |
tim00 | ๐ | ๐ | โ | ๐ | ๐ | ๐ |
tim01 div trigger | ๐ | ๐ | โ | โ | ๐ | ๐ |
tim01 | ๐ | ๐ | ๐ | ๐ | ๐ | ๐ |
tim10 div trigger | ๐ | ๐ | โ | โ | ๐ | ๐ |
tim10 | ๐ | ๐ | โ | ๐ | ๐ | ๐ |
tim11 div trigger | ๐ | ๐ | โ | โ | ๐ | ๐ |
tim11 | ๐ | ๐ | โ | ๐ | ๐ | ๐ |
tima reload | ๐ | ๐ | โ | โ | ๐ | ๐ |
tima write reloading | ๐ | ๐ | โ | โ | ๐ | ๐ |
tma write reloading | ๐ | ๐ | โ | โ | ๐ | ๐ |
Note: things that will be removed in the near future may not shown here. Not all source files are shown here.
.
โโโ doc -- Documents
โย ย โโโ control_unit.ods -- CPU control unit LUT
โย ย โโโ cpu_internal.md -- CPU internal signal encoding
โย ย โโโ cpu.md -- CPU design note
โโโ LICENSE -- OHDL
โโโ Makefile -- Toplevel Makefile
โโโ README.md -- This document
โโโ roms -- Place for platform independent ROMs
โย ย โโโ bootrom.s -- Boot ROM
โย ย โโโ Makefile -- Makefile for building the Boot ROM
โย ย โโโ tests -- Unit tests
โย ย ย ย โโโ compare.sh -- Script for comparing results between VBC and emulator
โย ย ย ย โโโ dmg_emu.exe -- Reference emulator
โย ย ย ย โโโ Makefile -- Makefile for running tests
โโโ rtl -- RTL files
โย ย โโโ alu.v -- ALU
โย ย โโโ boy.v -- VerilogBoy portable top level file
โย ย โโโ brom.v -- Boot ROM
โย ย โโโ common.v -- Common definitions
โย ย โโโ control.v -- Control Unit
โย ย โโโ cpu.v -- CPU top level
โย ย โโโ dma.v -- OAM DMA
โย ย โโโ Makefile -- Makefile for building the VBC using Verilator
โย ย โโโ mbc5.v -- Cartridge paging, optional
โย ย โโโ ppu.v -- Pixel Processing Unit
โย ย โโโ regfile.v -- CPU Register file
โย ย โโโ singleport_ram.v -- Singleport RAM template
โย ย โโโ singlereg.v -- Singlebit register template
โย ย โโโ timer.v -- Timer
โโโ sim -- Simualtion
โย ย โโโ verilator -- Verilator-based simulator
โย ย โโโ dispsim.cpp -- LCD simulator based on SDL 2.0
โย ย โโโ Makefile -- Makefile for building the simulator
โย ย โโโ mbcsim.cpp -- MBC cartridge controller simulator
โย ย โโโ memsim.cpp -- Boot ROM or Game ROM simulator
โย ย โโโ mmrprobe.cpp -- Unit for dumping memory or MMR accesses
โย ย โโโ vb_sim.cpp -- Simulator main file
โโโ target -- Targets (ports) of VBC
โย ย โโโ panog1 -- Pano Logic G1 devices
โย ย โย ย โโโ fpga -- FPGA RTL
โย ย โย ย โย ย โโโ dualport_ram.v -- Template of dual port RAM
โย ย โย ย โย ย โโโ idt_clkgen.v -- Code for interfacing with clock generator
โย ย โย ย โย ย โโโ mig -- LPDDR memory controller
โย ย โย ย โย ย โโโ mig_picorv_bridge.v -- Bridge for connecting PicoRV32 and LPDDR controller
โย ย โย ย โย ย โโโ mig.ucf -- Timing constraint for memory controller
โย ย โย ย โย ย โโโ mobile_ddr.v -- Simulation model for LPDDR
โย ย โย ย โย ย โโโ panog1.xise -- ISE project file
โย ย โย ย โย ย โโโ pano_top.v -- Top level HDL
โย ย โย ย โย ย โโโ pano.ucf -- Main pin location constraint
โย ย โย ย โย ย โโโ picorv32.v -- PicoRV32 RISC-V softcore
โย ย โย ย โย ย โโโ picosoc_mem.v -- PicoRV32 scratchpad memory
โย ย โย ย โย ย โโโ simple_uart.v -- Simple UART transmitter
โย ย โย ย โย ย โโโ testbench.v -- Testbench with LPDDR model
โย ย โย ย โย ย โโโ usb_picorv_bridge.v -- Bridge for connecting PicoRV32 and USB controller
โย ย โย ย โย ย โโโ vga_font.v -- VGA font ROM
โย ย โย ย โย ย โโโ vga_mixer.v -- Mixing PicoRV32 and VerilogBoy image
โย ย โย ย โย ย โโโ vga_timing.v -- VGA timing generator
โย ย โย ย โโโ fw -- Firmware for RV softcore
โย ย โย ย โย ย โโโ bootloader -- Bootloader for loading firmware from SPI Flash
โย ย โย ย โย ย โย ย โโโ bootloader.c -- Main source code
โย ย โย ย โย ย โย ย โโโ Makefile -- Makefile for building the bootloader
โย ย โย ย โย ย โย ย โโโ sections_bl.lds -- Link script
โย ย โย ย โย ย โย ย โโโ start_bl.s -- Startup code
โย ย โย ย โย ย โโโ dhrystone -- Dhrystone test for RV softcore
โย ย โย ย โย ย โโโ firmware -- Firmware for softcore
โย ย โย ย โย ย โย ย โโโ COPYING -- GPLv2 License for firmware
โย ย โย ย โย ย โย ย โโโ firmware.c -- Main source code
โย ย โย ย โย ย โย ย โโโ isp1760.c -- ISP1760 HCD
โย ย โย ย โย ย โย ย โโโ isp_roothub.h -- RootHub emulation for HCD (optional)
โย ย โย ย โย ย โย ย โโโ Makefile -- Makefile for building the firmware
โย ย โย ย โย ย โย ย โโโ misc.c -- Delay and other common routines
โย ย โย ย โย ย โย ย โโโ sections.lds -- Link script
โย ย โย ย โย ย โย ย โโโ syscalls.c -- Syscalls for the newlib
โย ย โย ย โย ย โย ย โโโ term.c -- Simple virtual terminal
โย ย โย ย โย ย โย ย โโโ usb.c -- Host USB stack
โย ย โย ย โย ย โย ย โโโ usb_gamepad.c -- Generic USB HIB gamepad driver
โย ย โย ย โย ย โย ย โโโ usb_storage.c -- USB mass storage driver
โย ย โย ย โย ย โโโ README.md -- README about firmware
โย ย โย ย โโโ README.md -- README about Pano Logic G1 port
โย ย โโโ vbh -- VerilogBoy Handheld
โย ย โโโ fpga -- FPGA RTL
โย ย โโโ fw -- Firmware for on-board MCU
โโโ tools -- Tools for building things
โโโ bin2mif -- Convert binary blob to mif
โโโ vga_timing.xlsx -- Tool for calculating VGA timing
Tested environment: Ubuntu 20.04 LTS, mac OS Big Sur.
Dependencies: build-essential, verilator, libsdl2-dev, wine(optional, for unit test only, for now), rgbds(not available from apt, need build manually).
On Debian/ Ubuntu, do the following:
sudo apt install build-essential verilator libsdl2-dev wine byacc flex pkg-config libpng-dev
On macOS, do the following:
brew install verilator sdl2 pkg-config libpng
To install rgbds:
git clone https://github.com/rednex/rgbds
cd rgbds
make
make install
At project directory:
make
Copy the bootrom.mif to where it is required. (For example, target/panog1)
At project directory:
cd roms/tests
make
./compare.sh
At project directory:
./sim/verilator/vb_sim <path_to_your_rom.gb> --mbc --nostop
Few parameters:
--nostop: Don't stop execution at halt/stop (but stop at illegal instructions)
--trace: Generate vcd waveform trace
--testmode: Disable internal Boot ROM, headless mode, limit cycles to 32K.
--noboot: Disable internal Boot ROM, code execution starts at 0x0000 rather than 0x0100.
--verbose: Enable debug output
--mbc: Enable MBC1/3/5 emulation for ROMs larger than 32KB
See README inside target directory.
This project reused codes from several other projects. A great thanks to their efforts!
- https://github.com/nightslide7/Gameboy
- https://github.com/cliffordwolf/picorv32
- https://github.com/u-boot/u-boot
- https://github.com/twlostow/dsi-shield
- https://github.com/MParygin/v.vga.font8x16
These projects are used as references. Again, thanks for sharing.
These are extremely helpful resources about the Game Boyยฎ itself:
Game used for demonstration, thanks for the great game:
I'm not affiliated with Nintendo in any way. Game Boyยฎ is a registered trademark by Nintendo. Nintendoยฎ is a registered trademark. All other trademarks are property of their respective owner.
The dsicore is made by twlostow, released under LGPL 3.0.
The PicoRV32 is free and open hardware licensed under the ISC license (a license that is similar in terms to the MIT license or the 2-clause BSD license).
Some firmware code of pano-g1 target are released to public domain.
All other software codes (including simulation code) are licensed under MIT.
All other HDL codes are licensed under OHDL 1.0.
All other text documents are licensed under CC BY-SA 4.0