Real synthesis and place-and-route of the actual final board-level
top (fpga_neural_v2_top.v -- SPI bridge, real EHXPLLL, reset_sync,
compute+memory core), against a real, fully ball-assigned LPF. Also
ports the V2 datasheet to LaTeX using V1's own preamble/macros/
typography, and records a real (non-ESP32, honestly labeled) software
reference comparison.
Synthesis (Yosys, real run): 0 CHECK-pass problems, 38 unique warnings
(43 total), all matching this project's own previously-reviewed benign
set (neural_processor.v's known genvar multi-driver artifact, small-
array-to-register unrolling, the real SDRAM DQ tristate bus) -- no new
warnings from the SPI bridge, PLL, or reset synchronizer.
TRELLIS_FF=6322, TRELLIS_COMB=7084, MULT18X18D=32, EHXPLLL=1 (real PLL
confirmed present), DP16KD=0 (all small SRAMs -> distributed RAM).
Place-and-route (nextpnr-ecp5, real runs, 8 seeds, new
v2_board_top.lpf with all 44 top-level signals ball-assigned from the
official Lattice pinout CSV -- no placeholders): 8/8 PASS at 64MHz.
Worst 68.51MHz (seed 4), best 74.17MHz (seed 7), mean 71.16MHz. Zero
unrouted nets, zero placement/routing errors, TRELLIS_IO=44/245 (17%).
Critical path alternates between dependency_manager's own priority
encoder and sdram_unified_backend's own weight-cache hit-index logic,
matching this project's own prior documented timing investigations --
not a new defect.
New: hardware/v2/constraints/v2_board_top.lpf (final LPF, supersedes
v2_unified.lpf for the board-level top), hardware/v2/reports/
step_final_{synthesis,pnr_worst_seed4,timing}.* (raw evidence),
hardware/v2/docs/DatasheetLatex/ (V2 datasheet, real LaTeX build,
16 pages, visually inspected, ported from hardware/v1/docs/
DatasheetLatex/'s own preamble and macros).
Real, honestly-labeled software baseline: the D-Stress arithmetic
(256 neurons x 128 INT8 MACs) compiled and run on THIS development
machine (Apple M4, arm64, NOT an embedded target, NOT ESP32) --
1.28us/inference, included in the datasheet with an explicit
disclosure that no physical ESP32 hardware was available for a real
embedded-target comparison.
Remaining, disclosed, NOT-yet-closed items (this commit does NOT
claim silicon readiness): real KiCad schematic + ERC, PCB layout,
sourced BOM, real power current-budget estimate, SDRAM-datasheet-
parameter cross-check, configuration-flash selection, and (necessarily)
physical fabrication/bring-up. See hardware/v2/docs/DatasheetLatex/
chapters/08-status-roadmap.tex for the complete, itemized checklist.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
87 lines
4.0 KiB
TeX
87 lines
4.0 KiB
TeX
\chapter{Architecture}
|
|
|
|
\section{Compute: Neural Multiprocessor}
|
|
Each of the \code{N\_PROCESSORS} Neural Processors is an independent
|
|
INT8 datapath: \code{P\_IN}=8 parallel multipliers feeding a balanced
|
|
binary adder tree into a 32-bit accumulator, followed by ReLU and INT8
|
|
saturation -- byte-for-byte identical to \code{neural\_processor.v},
|
|
unmodified since before the V2 single-SDRAM freeze. Job dispatch is a
|
|
real dependency-graph pipeline:
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[node distance=5mm and 6mm,font=\scriptsize]
|
|
\node[fnreg] (host) {SPI host\\bridge};
|
|
\node[fnreg,right=of host] (dm) {Dependency\\Manager};
|
|
\node[fnreg,right=of dm] (dir) {Neural\\Director};
|
|
\node[fnreg,below=of dir] (mm) {Memory Manager\\(per slot)};
|
|
\node[fnreg,left=of mm] (np) {Neural\\Processor};
|
|
\draw[fnarrow] (host) -- (dm);
|
|
\draw[fnarrow] (dm) -- (dir);
|
|
\draw[fnarrow] (dir) -- (mm);
|
|
\draw[fnarrow] (mm) -- (np);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
The Dependency Manager holds a per-node table (state, required/
|
|
resolved producer count, job descriptor fields) and hands READY nodes
|
|
to the Director one at a time (valid/ready, backpressure-safe). The
|
|
Director allocates the first free processor slot (first-free, not
|
|
load-balanced) and frees it the instant that slot's job completes.
|
|
|
|
\section{Unified single-SDRAM memory}
|
|
\begin{center}
|
|
\begin{tikzpicture}[node distance=6mm and 10mm,font=\footnotesize]
|
|
\node[fnblockT,minimum width=50mm,minimum height=20mm] (fpga){};
|
|
\node[anchor=north,font=\bfseries,text=fnDark] at (fpga.north){FPGA};
|
|
\node[fnreg,fill=white] (np) at ([yshift=2mm]fpga.center){4$\times$ Neural Processor};
|
|
\node[fnreg,fill=white,below=2mm of np] (be){Unified SDRAM Backend / Arbiter};
|
|
\node[fnblock,right=16mm of fpga,minimum height=20mm] (ram){\code{AS4C4M16SA-6TIN}\\Weights\\Activations\\Results};
|
|
\draw[fnbus] (fpga.east|-be) -- node[fnlbl,above]{16-bit SDRAM bus} (ram);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
\code{sdram\_unified\_backend.v} owns exactly one \code{sdram\_
|
|
controller.v} instance and presents two logical ports:
|
|
\begin{itemize}
|
|
\item \textbf{W} (weight fetch): 64-bit, read-only, a 4-entry
|
|
fully-associative ``other half'' cache (round-robin eviction --
|
|
safe under any sizing, since an evicted-too-early entry only costs
|
|
an extra real fetch, never wrong data).
|
|
\item \textbf{AR} (activation fill + result write-back): 16-bit,
|
|
read/write, byte-maskable via real SDR SDRAM DQM semantics
|
|
(\code{lb\_n}/\code{ub\_n}).
|
|
\end{itemize}
|
|
Both ports are, in turn, each arbitrated across the N\_PROCESSORS
|
|
slots by a generic, reused \code{slot\_mem\_arbiter} (a proven,
|
|
pending-latch-based, single-owner-until-ready design used identically
|
|
throughout this project).
|
|
|
|
\subsection*{Official V2 memory map}
|
|
\begin{tabularx}{\textwidth}{L{3.2cm}L{3.2cm}Y}
|
|
\toprule
|
|
\rowh \thd{Region} & \thd{Base address} & \thd{Notes} \\
|
|
\midrule
|
|
Weights & \code{0x010000} & 1\,MB-aligned \\
|
|
\rowa Activations & \code{0x200000} & 1\,MB-aligned \\
|
|
Results & \code{0x300000} & 1\,MB-aligned \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
All three regions are non-overlapping within the single 8\,MB
|
|
(\code{0x000000}--\code{0x7FFFFF}) SDRAM address space. Base addresses
|
|
are host-programmable per job (via \code{WRITE\_JOB}'s own
|
|
\code{x\_base}/\code{w\_base}/\code{result\_addr} fields), not hard-coded
|
|
in the datapath.
|
|
|
|
\section{Read-timing discipline (ERR-0025)}
|
|
The shared weight and activation SRAMs (\code{nms\_weight\_packed.v},
|
|
\code{nms\_activation\_replicated.v}) use \textbf{combinational} read
|
|
ports, matching the exact 1-cycle latency assumption of the per-slot
|
|
Memory Manager's own pipelined read-ahead consumer. An earlier,
|
|
registered-read implementation added one uncounted cycle of latency
|
|
that a busy, multi-tile job's own prefetch lead time always absorbed
|
|
invisibly, but that an uncontested single-tile job exposed on its
|
|
first (only) tile -- found and fixed via this revision's own
|
|
board-level SPI integration testing, with zero regression to the
|
|
existing bit-exact regression suite (identical cycle counts before and
|
|
after the fix).
|