A hardware Monte Carlo simulation, inspired by the tight-binding model, of particles hopping on a 7×7 lattice, written in VHDL and running on an Artix-7 FPGA. Seven walkers are injected on the bottom row of the lattice and hop stochastically between neighbouring sites (with obstacles baked into a neighbour ROM) until they reach one of seven detectors on the top row. Results are streamed live over UART to a Python visualizer on the host PC.
- Lattice: 7×7 grid (49 sites). Each site's connectivity is stored in
tb_rom.vhdas a degree ROM + neighbour ROM, so arbitrary lattice geometries (walls, defects, channels) can be encoded without touching the core logic. - Walkers: 7 independent walkers, each with its own 16-bit LFSR random number generator. Every simulation step a walker either stays put (~20% probability) or hops to a uniformly-chosen neighbouring site.
- Detectors: the top row acts as 7 detectors. A walker reaching row 0 is absorbed, the corresponding detector count increments, and an on-board LED latches.
- Two run modes (selected by a switch):
- Animate — steps at a human-visible rate (default 100 Hz) and streams every walker position over UART so the host can draw the walk live.
- Bulk — repeatedly re-injects all 7 walkers for
BULK_ROUNDS(default 500) rounds at full speed, then streams the final detector histogram.
| Path | Description |
|---|---|
tightbinding.srcs/sources_1/new/tb_pkg.vhd |
Shared types, LFSR step function, row/col helpers |
tightbinding.srcs/sources_1/new/tb_rom.vhd |
Lattice geometry: degree ROM and neighbour ROM |
tightbinding.srcs/sources_1/new/tightbinding_core.vhd |
Walker update FSM, RNGs, detectors, animate/bulk control |
tightbinding.srcs/sources_1/new/uart_tx.vhd |
Simple UART transmitter (115200 baud, 8N1) |
tightbinding.srcs/sources_1/new/top_tb_uart.vhd |
Top level: switch edge-detect, step-tick divider, packet framing FSM |
tightbinding.srcs/constrs_1/new/constr.xdc |
Pin constraints (Nexys A7-100T / Nexys 4 DDR) |
a.py |
Host-side viewer: live walker animation and detector histogram |
tightbinding.ipynb |
Python reference model / exploration notebook (Colab) |
tightbinding.xpr |
Vivado project file |
- Target:
xc7a100tcsg324-1(Artix-7 100T), pinned for the Digilent Nexys A7-100T (also matches Nexys 4 DDR): 100 MHz clock onE3, UART TX onD4, LEDsU17…H17. - Controls:
sw_start— start a run (rising edge)sw_stop— abort back to idlesw_bulk—0= animate mode,1= bulk moderst_n— active-low reset
- LEDs 0–6: latch when the corresponding detector has been hit.
115200 baud, 8N1. Every packet is framed as AA 55 <type> <len> <payload>:
| Type | Length | Payload |
|---|---|---|
0x01 (step) |
8 | walker positions pos0…pos6 (site index 0–48), then active bitmask |
0x03 (detectors) |
14 | 7 detector counts as little-endian uint16 |
-
Open
tightbinding.xprin Vivado, generate the bitstream, and program the board. -
Install host dependencies:
pip install pyserial numpy matplotlib -
Live animation (with
sw_bulkoff, press start):python a.py anim COM8 -
Detector histogram (with
sw_bulkon, press start and wait for the bulk run to finish):python a.py bar COM8Replace
COM8with your board's serial port.
Top-level generics in top_tb_uart.vhd:
| Generic | Default | Meaning |
|---|---|---|
CLK_HZ |
100 000 000 | Input clock frequency |
BAUD |
115200 | UART baud rate |
STEP_HZ |
100 | Simulation step rate in animate mode |
BULK_ROUNDS |
500 | Number of injection rounds in bulk mode |
MIT — see LICENSE.