Skip to content

zenbean/jane-street-AOC

Repository files navigation

Jane Street Advent of FPGA Challenge 2025: Day 7 Solution

Overview

This project solves Advent of Code Day 7 puzzle using a synthesizable SystemVerilog design. The core architecture exploits FPGA-native parallelism to simulate a "wavefront" of beams falling through a grid, processing the map line-by-line

The Approach

My initial instinct was to solve this using recursion, hashmaps, and 2D grid searches. However, fitting this onto an FPGA required a shift in thinking to facilitate hardware:

  1. Hardware Design Prototype (C++): I wrote a C++ prototype that strictly mimiced hardware constraints. Instead of std::find or random memory access, I restricted myself to single pass loops and fixed size boolean vectors
  2. Architecture:
    • O(W) Memory: Instead of storing the full $H \times W$ grid, I only store the state of the current beam
    • Logic: To avoid write conflicts (multiple beams merging), each cell calculates its next state by looking at its neighbors ($i-1$, $i$, $i+1$) in parallel
  3. Realistic I/O (top.sv): Physical chips have a limited number of input pins. The core solver requires a 2,048-bit wide input, which is impossible for standard FPGA I/O. I implemented a Serial In Parallel Out (SIPO) top module. It treats the input as a stream of 8-bit characters (similar to UART), separating the communication throughput from the computation. This reduces the I/O requirement to just 10 pins.

top.sv

In the real world, data arrives sequentially over time. This module acts as a bridge between the external flow of data and the internal logic.

  • Serial In: The rx_valid signal pulses as bytes arrive one by one. The logic captures these bytes into a line buffer.
  • Parallel Out: When the newline \n arrives, the buffer is full. The compute_start signal pulses high, dumping the entire line into the computation module in a single clock cycle.

tachyonSplit.sv

This is essentially Day7_laboratories.cpp implemented in SystemVerilog, the key to counting the number of times the beam splits. In software, moving a beam is easy. However, in hardware, having multiple beams attempting to write to the same location may cause write collisions. To resolve this, instead of looking at where the beams will move, we instead calculate the next state while looking at the neighbours.

An advantage of using hardware approach to this challenge is the ability of parallelism, where we are able to do n logic updates and split checks in a single clock cycle for an n width grid input.

top_tb.cpp

Testbench that drives the Verilator model by simulating UART input by reading the raw puzzle input input.txt and bit banging the input signals. Breaking every line of text into individual bytes and toggle rx_valid high or low for each one. From this, we are able to verify that the hardware correctly handles streaming data, pauses, and line termination sequences.

Implementation details

  • Language: SystemVerilog
  • Simulation: Verilator (C++ Testbench)
  • Key Optimisation: The entire row update happens in a single clock cycle, regardless of map width

How to run it

  1. Compile the top and component modules, and testbench:
verilator -Wall --cc --exe --build top.sv tachyonSplit.sv top_tb.cpp
  1. Run the simulation:
./obj_dir/Vtop

About

Advent of Code but FPGA

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors