Skip to content

NAND to Tetris on the iCEBreaker FPGA

Notifications You must be signed in to change notification settings

leocassarani/ice2tetris

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

iCE2Tetris

This project is an FPGA implementation of the Nand to Tetris course as set out in the book The Elements of Computing Systems. The project targets the iCE40 UltraPlus FPGA chip and specifically the iCEBreaker FPGA board.

When connected to a screen and keyboard using the VGA and PS/2 Pmods, this system is capable of running any valid Hack program, achieving full compatibility with the Java-based software emulator provided with the course materials. The program ROM can be uploaded as a binary file to the iCEBreaker board’s onboard flash chip and will be read into memory at boot time.

This system is entirely built on open source software and uses the Open Tool Forge FPGA toolchain, particularly Yosys for Verilog synthesis, Project IceStorm for iCE40 support, and nextpnr for place-and-route.

In addition, an interactive Verilator simulation of the design can be found in the sim directory. Based on the SDL2 multimedia library, the simulator captures the VGA signal and renders it on the screen; as well as providing an emulated SPI flash ROM chip and a PS/2 virtual keyboard.

A GIF of the simulator running Pong

Usage

After installing the Open Tool Forge toolchain and plugging in your iCEBreaker board over USB, simply run:

$ make prog

This will synthesise the Verilog design, run place-and-route and timing analysis, then upload it to the FPGA board.

To execute a Hack program, it must be uploaded to the iCEBreaker board as a binary file containing 16-bit Hack instructions stored in big-endian byte order. To compile a Jack program into a .bin file, you can use my Jackc compiler:

$ jackc --bin -o program.bin Main.jack

Or, if you already have a .hack file, you can convert it into binary with this handy Ruby one-liner:

$ ruby -ne 'print [$_.to_i(2)].pack("n")' < program.hack > program.bin

To upload the binary file, run:

$ make flash ROM=program.bin

This will copy the file to the on-board flash memory starting at offset 1,024KiB. Note that .bin files can be at most 64KiB as their 16-bit instructions are addressable by a 15-bit number (2^15 = 32Ki).

Next, plug in a VGA screen and a PS/2 keyboards into the Pmods, and connect the iCEBreaker to a USB port. The Hack program will start executing. To reset the execution to the start, press the button closest to the USB port.

Simulator

To execute a Hack program on the simulated Verilog design, run:

$ make test ROM=program.bin

This will compile the Verilator-based simulator and execute it. Note that the Verilator binary and library files must be installed for this to work. The simulator has been tested with Verilator 4.034 or above and is not guaranteed to work with earlier versions.

When the simulator starts, the Verilog logic will send SPI “read” operations to the simulated flash chip, which will respond by streaming the contents of program.bin. Once the ROM has been fully read into memory, the VGA output signals will be converted into a 512x256 picture and displayed within the SDL window.

Whenever a key is pressed, if its key code is supported by the Hack platform, it will be translated into PS/2 signals and sent to the simulated keyboard client. Note that as the Hack platform only supports one key press at a time, only the more recent of multiple simultaneous key presses will be picked up by the simulated logic. Pressing either Ctrl+R or ⌘R will reset the simulator and restart execution.

Acknowledgments

Thanks to everyone on the 1BitSquared Discord #icebreaker channel who volunteered to help whenever I got stuck. Particular thanks to Ed Bordin, Dave Shah, Piotr Esden-Tempski, and Sylvain “tnt” Munaut.

My VRAM implementation was inspired by smunaut/ice40-playground and my PS/2 driver was adapted from the PS/2 mouse reference system on the Digilent website.

Finally, my VGA implementation was largely possible thanks to Ben Eater's video series on building a digital circuit to output a VGA signal.

About

NAND to Tetris on the iCEBreaker FPGA

Resources

Stars

Watchers

Forks