\chapter{Register-level interface \& internal state encodings} \label{ch:regs} \begin{fnwarn}[Real SPI opcode map exists; state encodings below are per-module reference] Ch.~\ref{ch:host} now documents V2's real, physical SPI opcode map (\code{WRITE\_JOB}/\code{WRITE\_MEM}/\code{READ\_MEM}/\code{STATUS}/ \code{RESET}) --- this chapter's own node-registration field layout below remains the logical field reference (repeated here for quick reference). The \textbf{internal FSM state encodings} below are useful for simulation-level debug; \S\S\ref{ch:regs}'s Dependency Manager/Neural Director tables are shared by every V2 architecture (unchanged between the PSRAM-era and current SDRAM boards). The Memory Manager and Neural Processor tables were captured from the PSRAM-era \code{memory\_manager.v}/\code{neural\_processor.v} pairing (ch.~\ref{ch:arch}) --- the current SDRAM board's \code{nms\_memory\_manager\_stream\_wide.v} implements the same functional handshake (prefetch $\to$ stream $\to$ write-back $\to$ done) against the SDRAM backend instead of PSRAM, but its own internal state encoding was not re-transcribed into this table. \end{fnwarn} \section{Node registration fields (quick reference)} See ch.~\ref{ch:host} for the full field-level description. \code{reg\_node\_id}, \code{reg\_required}, \code{reg\_producer\_ids}, \code{reg\_x\_base}, \code{reg\_w\_base}, \code{reg\_n\_tiles}, \code{reg\_result\_addr} --- valid/ready handshake, \code{reg\_ready} gated on the target node id's table slot being \code{EMPTY}. \section{Dependency Manager node state (\texttt{node\_state})} \begin{tabularx}{\textwidth}{C{1.4cm} L{2.6cm} Y} \toprule \rowh \thd{Value} & \thd{Name} & \thd{Meaning} \\ \midrule \op{2'd0} & \code{ST\_EMPTY} & Table slot free; \code{reg\_ready} asserted for this node id. \\ \rowa \op{2'd1} & \code{ST\_WAITING} & Registered, at least one producer not yet resolved. \\ \op{2'd2} & \code{ST\_READY} & All producers resolved; eligible for dispatch. \\ \rowa \op{2'd3} & \code{ST\_DISPATCHED} & Handed to the Director; \textbf{terminal} (\S\ref{ch:sched}). \\ \bottomrule \end{tabularx} \section{Neural Director state (\texttt{dir\_state})} \begin{tabularx}{\textwidth}{C{1.4cm} L{2.6cm} Y} \toprule \rowh \thd{Value} & \thd{Name} & \thd{Meaning} \\ \midrule \op{4'd0} & \code{DIR\_IDLE} & Reset/startup. \\ \rowa \op{4'd1} & \code{DIR\_SCAN\_READY} & Checking whether a queued job and a free slot both exist. \\ \op{4'd2} & \code{DIR\_ALLOCATE} & Dispatching the head-of-queue job to the first free slot. \\ \rowa \op{4'd3} & \code{DIR\_ERROR} & Recoverable only via reset (an isolated fault never blocks other slots). \\ \bottomrule \end{tabularx} \section{Memory Manager state (\texttt{state})} \begin{tabularx}{\textwidth}{C{1.4cm} L{3.0cm} Y} \toprule \rowh \thd{Value} & \thd{Name} & \thd{Meaning} \\ \midrule \op{3'd0} & \code{MM\_IDLE} & Waiting for \code{job\_start}. \\ \rowa \op{3'd1} & \code{MM\_PREFETCH\_FIRST} & Waiting for tile~0's activation \emph{and} weight halves to both arrive. \\ \op{3'd2} & \code{MM\_STREAM} & Presenting tiles to the Neural Processor, double-buffering the next one. \\ \rowa \op{3'd3} & \code{MM\_WAIT\_RESULT} & Last tile handed off; waiting for the Neural Processor's own result. \\ \op{3'd4} & \code{MM\_WRITE\_RESULT} & Issuing the real PSRAM word write for the INT8 result. \\ \rowa \op{3'd5} & \code{MM\_DONE} & Waiting for the write's own \code{mem\_ready}; then pulses \code{job\_done}. \\ \bottomrule \end{tabularx} \section{Neural Processor state (\texttt{np\_state})} \begin{tabularx}{\textwidth}{C{1.4cm} L{2.8cm} Y} \toprule \rowh \thd{Value} & \thd{Name} & \thd{Meaning} \\ \midrule \op{4'd0} & \code{NP\_IDLE} & No job in flight. \\ \rowa \op{4'd1} & \code{NP\_LOAD\_JOB} & Latching \code{job\_bias}/\code{job\_activation}, clearing the accumulator. \\ \op{4'd2} & \code{NP\_WAIT\_OPERANDS} & Consuming tiles as they arrive (absorbs the per-tile MAC/accumulate/next-tile sequence). \\ \rowa \op{4'd3} & \code{NP\_FINISH} & Draining the pipeline after \code{tile\_last}. \\ \op{4'd4} & \code{NP\_WRITE\_RESULT} & Result available for the Memory Manager to consume. \\ \rowa \op{4'd5} & \code{NP\_DONE} & Job complete. \\ \op{4'd6} & \code{NP\_ERROR} & Reachable only via an unreachable \code{default} case --- isolated per-processor, never blocks other slots. \\ \bottomrule \end{tabularx} \section{Slot Memory Arbiter owner encoding} \code{owner} is \code{0} for ``no port granted'', or (port index $+1$) for the currently-granted port --- indices \code{0..N\_SLOTS-1} are the per-slot Memory Managers' own weight/write-back traffic; index \code{N\_SLOTS} is the shared Activation Cache's own traffic.