Overview
This is a fully digital Whack-A-Mole game implemented in Verilog and synthesized onto a Nexys4 DDR FPGA (Xilinx Artix-7 XC7A100T). All game logic — mole spawning, hit detection, scoring, timing, and display — runs entirely in hardware using finite state machines and synchronous digital design. There is no soft-core processor; every behavior, from switch debouncing to VGA pixel output, comes from combinational and sequential logic synthesized directly onto the FPGA fabric.
Players have 90 seconds to hit as many moles as possible. Each of the 16 switches corresponds to one mole; when a mole spawns, its LED lights and its cell on the VGA display turns green. Toggling the switch before the 1-second window expires registers a hit. A 16-bit LFSR pseudorandomly selects which mole spawns next and adds jitter to the spawn interval, keeping the sequence unpredictable. Score and remaining time appear on the 7-segment display throughout the round. When the timer reaches zero, LED16_R turns red and the VGA screen floods to solid red — game over.
Design decisions
Distributed mole FSMs via generate loop
Rather than a single monolithic game FSM, each mole is an independent mole module with its own active flag, 1-second countdown timer, and hit register. The top level instantiates all 16 with a genvar loop, wiring each to its corresponding switch, LED, and spawn-bus bit. This keeps the per-mole logic self-contained — adding moles means only changing the loop bound — and lets each module handle its own reset independently when the game ends.
LFSR for mole selection and spawn-interval jitter
A 16-bit maximal-length LFSR (feedback taps at bits 15, 14, 12, and 3) generates a new pseudorandom value every clock cycle. The spawner uses bits [3:0] to one-hot decode which of the 16 moles to activate next, and bits [7:4] to add interval jitter: current_period = MIN_PERIOD + {rng[7:4], 23'b0}, giving a spawn delay between 1.0 and ~2.3 seconds. The LFSR is seeded once at startup with a fixed 16-bit value; the combination of a fixed seed and the maximal-length polynomial means every game session follows the same sequence, but it appears random during play.
Two-FF synchronizer and any-edge hit detection
Each switch input passes through a two-stage D flip-flop synchronizer to resolve metastability before any logic looks at it. The module then compares the current and previous synchronized values: sw_change = sw_sync1 ^ sw_prev. Any transition — press or release — within the active window registers as a hit. The others_active input, driven from the OR of all other LEDs, gates this: a hit only scores when no other moles are simultaneously lit. This prevents a single switch flick from accidentally crediting multiple moles during edge cases where two are active at once.
Custom VGA renderer — no IP blocks
The VGA display is implemented from scratch as a state machine that generates standard 640×480 @ 60 Hz sync signals and 12-bit color output. The screen is divided into a 4×4 grid of 160×120-pixel cells, one per mole. At each pixel clock, the module computes col = h_pos / 160 and row = v_pos / 120, indexes the 16-bit mole bus with mole_index = {row, col}, and paints the cell: green for an active mole, dark gray for idle, with an 8-pixel black border between cells. On game over the entire screen switches to solid red. No framebuffer or block RAM is used — the pixel color is computed combinationally each cycle directly from the mole bus.