Commit Graph
5 Commits
Author SHA1 Message Date
micheleandClaude Sonnet 5 7e2711fa27 feat: widen ADDR_WIDTH to 23 bits for full 8MB PSRAM addressing
Bumps ADDR_WIDTH's default from 22 to 23 bits across every RTL
module (neuron_memory, layer_sequencer, spi_engine, spi_neuron_top,
mem_arbiter, int8_memory_access, memory_interface, psram_controller,
memory_model) and every testbench that mirrors it, so the system's
byte-address space reaches the full 8 MiB the recommended PSRAM part
(ISSI IS66WVE4M16EBLL-70BLI, docs/FPGA-Neural-Hardware-Design.md §3)
actually provides -- previously only 4 MiB (half the chip) was
reachable, since int8_memory_access.v's byte->word address shift
(addr >> 1) turned the old 22-bit byte address into only 21 real word
bits, one short of the chip's real 22-bit word address (A0-A21). At
23 bits, that same shift lands exactly on all 22 chip address lines,
so the whole part is usable now instead of deferred to a future
widening.

Also fixes a stray 22'd11-sized literal in layer_sequencer.v's
descriptor-table address increment (numerically already safe via
Verilog's zero-extension, but now correctly unsized so it always
matches ADDR_WIDTH instead of silently assuming 22).

Updated docs/FPGA-NeuralNetwork-Engine.md's SPI protocol address-field
note (23 bits, top 1 reserved bit instead of 2) and
docs/FPGA-Neural-Hardware-Design.md's PSRAM section (the "chip has
one spare address line" framing is gone now that all 22 are wired
and used).

Full regression (all 11 ADDR_WIDTH-touching testbenches, plus a
Yosys elaboration check of spi_neuron_top with the new default and
no override) passes clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQV3vS9TXaGDJ5cRfnfidt
2026-09-02 21:00:46 +02:00
micheleandClaude Sonnet 5 a918c3f1e9 feat: configurable activation functions + runtime-configurable network topology
Two related Phase 5 additions, both threaded the same way (a new
runtime field defaulting to the pre-existing behavior, settable
per-layer via the descriptor table or per-run via SET_BASE):

Configurable activation functions:
- neuron_parallel.v gains a 2-bit `activation` port (ACT_NONE =
  linear + two-sided INT8 saturate, ACT_RELU = the original
  hardwired behavior, kept as the default so every pre-existing
  caller/testbench is unaffected), threaded through neuron_memory.v.
- spi_engine.v: SET_BASE sel=6 (single-layer path); the descriptor
  table gains a 7th byte (multi-layer path).
- Verified in neuron_parallel_tb.v (negative pass-through + negative
  saturation to -128) and end-to-end in
  spi_neuron_top_runnetwork_tb.v (a real negative accumulator that
  ACT_RELU would clamp to 0 comes through unclamped under ACT_NONE,
  over real SPI/RAM).

Runtime network width (one bitstream, any topology up to its
build-time max, entirely host-configured over SPI):
- neuron_parallel.v gains n_inputs_real, bounding its MAC group loop
  (n_inputs_real/PARALLEL groups instead of the fixed build-time
  count). neuron_memory.v gains n_inputs_real/n_neurons_real,
  bounding its X/W RAM-read loop and its neuron loop. All default to
  the build-time max, so unconnected callers are unaffected.
  n_inputs_real must stay a multiple of PARALLEL (same constraint
  N_INPUTS itself is held to at elaboration time, now the caller's
  runtime responsibility).
- spi_engine.v: SET_BASE sel=7/8 (single-layer path); the descriptor
  table grows to 11 bytes/layer (+n_inputs_real +n_neurons_real,
  multi-layer path) -- layer_sequencer.v also now copies only
  n_neurons_real bytes into the ping-pong buffer, not the full
  build width.
- This is real early termination, not bookkeeping: no RAM
  zero-padding needed for the unused tail, and it measurably
  completes faster. neuron_parallel_tb.v TEST 7: 3 cycles vs 6 for a
  reduced-vs-full run, with garbage loaded into the skipped lanes to
  prove they're never read. neuron_memory_tb.v TEST 5: through the
  real PSRAM stack, 209 cycles vs 788. layer_sequencer_tb.v proves a
  reduced n_neurons_real shortens the ping-pong copy-out itself
  (bytes beyond the real count stay untouched, not just differing).

docs/FPGA-NeuralNetwork-Engine.md: §8.1 opcode/SET_BASE table, new
"Runtime network width" subsection, Phase 5 checklist, Current
Status table, and the "Core architectural principle" statement
updated to reflect that topology (not just trained parameters) is
now host-configured at runtime up to a build-time ceiling.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQV3vS9TXaGDJ5cRfnfidt
2026-09-02 20:18:24 +02:00
micheleandClaude Sonnet 5 661363f637 feat: extend neuron_memory to support N_NEURONS>1 (Phase 3)
neuron_memory.v only handled a single neuron. Added an N_NEURONS
parameter (default 1, fully backward compatible) and a memory-bound
neuron loop: X is read once (shared layer input), and for each
neuron in turn W and bias are re-read from PSRAM and fed to a
single, reused neuron_parallel instance -- no change to the
validated compute datapath (neuron_parallel/mac8/mac_unit).

Addressing follows layer.v's neuron-major convention: neuron n's
weights live at w_base + n*N_INPUTS bytes, its bias at
bias_addr + n. Output changed from a single `y` port to a packed
`y_bus` (DATA_WIDTH*N_NEURONS bits, neuron-major), matching
layer.v's y_bus.

- rtl/neuron_memory.v: N_NEURONS parameter, neuron_index/
  w_group_base/bias_group_addr tracking, y_reg[] array assembled
  into y_bus, STATE_WAIT_N now loops back to STATE_READ_W for the
  next neuron instead of finishing after one.
- sim/neuron_memory_tb.v: updated to the new y_bus port
  (N_NEURONS=1 explicit); all 5 existing tests still pass unchanged,
  confirming backward compatibility.
- sim/neuron_memory_multi_tb.v: new end-to-end test (full
  memory_interface + psram_controller + psram_model stack) with
  N_NEURONS=3, validating per-neuron addressing and a single done
  pulse at the end of the sequence (scale, larger value, ReLU).
- Full regression re-run: all existing testbenches still pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQV3vS9TXaGDJ5cRfnfidt
2026-09-02 14:50:45 +02:00
micheleandClaude Sonnet 5 896f56c675 fix: correct byte/word address conversion in neuron_memory_tb preload tasks
preload_vector and preload_weights wrote using base as a word address
instead of a byte address (base + (k>>1) instead of (base>>1) + (k>>1)),
misaligning X/W data in PSRAM relative to what int8_memory_access expects.
Also adds a PATTERN test (X=1..32) to exercise mixed even/odd byte reads
and catch this class of bug going forward.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQV3vS9TXaGDJ5cRfnfidt
2026-09-02 14:08:13 +02:00
michele 16769eaa4b working with memory 2026-09-02 13:09:20 +02:00