\chapter{Descrizione hardware} \label{chap:hardware} \section{Panoramica della scheda} Il progetto realizza un acceleratore neurale su una scheda custom (non una dev-board commerciale), basata su un componente FPGA nudo Xilinx Artix-7, affiancato da memoria DDR3 reale, una flash di configurazione dedicata e un microcontrollore ESP32 come processore host/centrale. La scheda non utilizza moduli di sviluppo preassemblati: ogni parte è stata scelta, verificata in reperibilità reale (LCSC) e posizionata pin-per-pin a partire da un vero place-and-route Vivado, non da valori stimati. \begin{table}[h] \centering \begin{tabular}{lll} \toprule \textbf{Componente} & \textbf{Parte} & \textbf{Note} \\ \midrule FPGA & XC7A100T-CSG324-2 & Speed grade $-2$ \\ DDR3 SDRAM & 2$\times$ Micron MT41J128M16JT-125:K & 2Gb, x16, canale fisico a 32 bit \\ Flash di configurazione & Winbond W25Q32JVSSIQ & 32Mbit, SOIC-8, esclusiva della FPGA \\ Host / processore centrale & ESP32-S3-WROOM-1-N16R8 & 16MB flash, 8MB PSRAM \\ \bottomrule \end{tabular} \caption{Componenti principali, tutti verificati realmente reperibili su LCSC.} \end{table} \section{FPGA: Xilinx XC7A100T-CSG324-2} Il componente centrale è un Artix-7 XC7A100T, package CSG324 (324 BGA), speed grade $-2$. La scelta dello speed grade $-2$ (corretta rispetto a un'ipotesi iniziale $-1$) non comporta alcuna differenza di die, package o footprint: offre solamente un margine di timing strettamente migliore, confermato dai reali segni di place-and-route (Capitolo~\ref{chap:tests}). Risorse rilevanti utilizzate dal design (target reale N=8, Capitolo~\ref{chap:architecture}): \begin{itemize} \item 240 DSP48E1 totali disponibili; 64 utilizzati (26.7\%). \item 63400 LUT disponibili; 12535 utilizzate (19.77\%). \item 126800 registri disponibili; 19902 utilizzati (15.70\%). \item Nessuna BRAM utilizzata. \end{itemize} \section{Memoria DDR3} Il canale DDR3 è realizzato con due chip Micron MT41J128M16JT-125:K (2Gb, x16, DDR3-1600) collegati in parallelo, formando un canale fisico reale a \textbf{32 bit} (bus dati raddoppiato rispetto alla configurazione iniziale a 16 bit di un solo chip). Le linee di indirizzo/comando/controllo sono condivise e distribuite identicamente a entrambi i chip; le linee DQ/DQS/DM sono invece divise 16 bit per chip. Il canale DDR3 è pilotato dal MIG (Memory Interface Generator) di Xilinx, generato realmente per questo esatto part number. I due domini di clock reali coinvolti sono: \begin{itemize} \item \textbf{sys\_clk\_p/n} --- clock differenziale della PHY DDR3, \textbf{310.078\,MHz} (periodo 3.225\,ns). \item \textbf{ui\_clk / clk\_pll\_i} --- dominio di calcolo interno, derivato dal PLL del MIG con rapporto 2:1 dal clock PHY, \textbf{155.039\,MHz}. Tutta la logica neurale (Director, arbitraggio, PE) gira in questo dominio. \end{itemize} Questa combinazione di frequenze non è una scelta libera: è l'unica uscita reale del calcolatore JEDEC/PLL del wizard MIG di Vivado per questo speed grade e questa larghezza di canale, e determina direttamente il vincolo di temporizzazione usato in ogni place-and-route reale del progetto (Capitolo~\ref{chap:tests}). \subsection{Convenzione di indirizzamento in DDR3} Pesi e attivazioni condividono lo stesso spazio di indirizzi DDR3, indirizzato a parola. La parola nativa è a 32 bit (\texttt{BURST\_LEN=8} per transazione, cio\`e 256 bit/burst). \begin{itemize} \item \textbf{Pesi}: l'insieme di pesi di un layer parte all'indirizzo parola \texttt{layer\_index * WORDS\_PER\_LAYER}, letto in burst sequenziali in un buffer on-chip una sola volta per job (riuso reale attraverso pi\`u posizioni). \item \textbf{Attivazioni}: quattro tile consecutivi (8 valori INT8 ciascuno) condividono un solo burst da 256 bit; la selezione del quarto di burst \`e latenziata al momento della richiesta (non un multiplexer indicizzato a runtime), preservando il margine di temporizzazione. \end{itemize} \section{Flash di configurazione} Una Winbond W25Q32JVSSIQ (32Mbit / 4MB, SOIC-8) ospita il bitstream di configurazione (circa 30.5Mbit per un XC7A100T pieno) ed \`e collegata \textbf{esclusivamente} alla FPGA --- l'ESP32 non ha alcun collegamento elettrico diretto ad essa. L'unico percorso elettrico dall'ESP32 alla flash \`e un relay software attraverso la FPGA (opcode SPI \texttt{0x40 FLASH\_XFER}, \S\ref{sec:spi-protocol}). \section{Host: ESP32-S3} Il processore host \`e un modulo ESP32-S3-WROOM-1-N16R8 (16MB flash, 8MB PSRAM, dual-core), verificato realmente reperibile su LCSC. Comunica con la FPGA tramite un bus SPI dedicato dove la \textbf{FPGA \`e slave}, e --- tramite la FPGA come relay --- raggiunge la flash di configurazione su un secondo bus SPI fisicamente distinto dove la \textbf{FPGA \`e master}. \section{Assegnazione dei pin (reale, dal design instradato)} Tutti i pin elencati sotto provengono da un vero file di vincoli generato da Vivado (XDC), non da valori ipotizzati. \subsection{DDR3 (fissati dall'hardware PHY della FPGA)} I pin DDR3 sono generati dal wizard MIG e non sono una scelta libera: banchi \textbf{34/35}, standard \texttt{SSTL15}/\texttt{DIFF\_SSTL15} (1.5V). Il clock di riferimento differenziale \texttt{clk\_ref\_p/n} vive necessariamente nel \textbf{banco 14} (regola di piazzamento UG586 del wizard per questo package), a \textbf{2.5V} (\texttt{LVDS\_25}) --- un vincolo che ha richiesto lo spostamento del bus SPI della flash (si veda sotto), poich\'e un banco pu\`o avere una sola tensione VCCO. \subsection{SPI di gestione (ESP32 $\leftrightarrow$ FPGA, FPGA slave)} Banco 15, colonna di bordo del package (tracce corte), \texttt{LVCMOS33}: \begin{table}[h] \centering \begin{tabular}{lll} \toprule \textbf{Segnale} & \textbf{Pin} & \textbf{Direzione (lato FPGA)} \\ \midrule sclk & A15 & input \\ mosi & B16 & input \\ miso & B17 & output \\ cs\_n & A16 & input \\ sys\_rst & G13 & input (pin provvisorio) \\ data\_ready\_n & D14 & output (IRQ sticky attivo-basso) \\ \bottomrule \end{tabular} \caption{Pinout del bus SPI di gestione, banco 15, VCCO assunto 3.3V.} \end{table} \subsection{SPI della flash di configurazione (FPGA $\leftrightarrow$ flash, FPGA master)} Originariamente sui pin dedicati di configurazione Master-SPI della FPGA (banco 14); spostati nel \textbf{banco 16} per risolvere un conflitto reale di VCCO con \texttt{clk\_ref} (rilevato da un vero fallimento di \texttt{place\_design}, non ipotizzato): \begin{table}[h] \centering \begin{tabular}{llll} \toprule \textbf{Segnale} & \textbf{Pin} & \textbf{Direzione} & \textbf{Note} \\ \midrule flash\_mosi & D9 & output & banco 16 (era K17, banco 14) \\ flash\_miso & D10 & input & banco 16 (era K18, banco 14) \\ flash\_cs\_n & C9 & output & banco 16 (era L13, banco 14) \\ (CCLK) & E9 & output & pilotato internamente via \texttt{STARTUPE2} \\ \bottomrule \end{tabular} \caption{Pinout del bus SPI della flash, banco 16, VCCO 3.3V.} \end{table} \subsection{Controllo di configurazione FPGA (banco 0, non negoziabile)} \begin{table}[h] \centering \begin{tabular}{ll} \toprule \textbf{Segnale} & \textbf{Pin} \\ \midrule PROGRAM\_B & P9 \\ INIT\_B & P7 \\ DONE & P10 \\ M0 / M1 / M2 & P12 / P13 / P11 \\ CFGBVS & P8 \\ \bottomrule \end{tabular} \end{table} Per il boot autonomo da Master SPI: \texttt{M[2:0] = 001}. \subsection{JTAG} \begin{table}[h] \centering \begin{tabular}{ll} \toprule \textbf{Segnale} & \textbf{Pin} \\ \midrule TCK & E10 \\ TDI & E11 \\ TMS & E12 \\ TDO & E13 \\ \bottomrule \end{tabular} \end{table} Usato per la programmazione di fabbrica/recupero quando la flash \`e vuota, e per debug --- pilotato via bit-banging da firmware ESP32 (non ancora implementato, lavoro software separato). \section{Alimentazione (stato di avanzamento)} La ricerca dei componenti di alimentazione \`e parziale e onestamente dichiarata incompleta: \begin{itemize} \item \textbf{VCCINT} (1.0V, alimentazione core FPGA): candidato reale identificato, Infineon IR38060 (SupIRBuck integrato, fino a 6A) --- \textbf{stock non confermato}. \item \textbf{VTT} (terminazione DDR3, opzionale): candidato reale TI TPS51200 --- la necessit\`a effettiva dipende dalla lunghezza reale delle tracce sul layout, non ancora stabilita da questo progetto (nessuna simulazione di signal integrity eseguita). \item \textbf{VCCAUX (1.8V) e VCCO per banco} (1.5V banchi 34/35, 2.5V banco 14, 3.3V banchi 15/16): \textbf{non ancora ricercati}. \end{itemize} \section{Oscillatori di clock} \begin{table}[h] \centering \begin{tabular}{lll} \toprule \textbf{Segnale} & \textbf{Frequenza richiesta} & \textbf{Stato} \\ \midrule sys\_clk\_p/n & 310.077\,MHz differenziale & Nessun SKU a catalogo a questa esatta frequenza; candidato reale SiTime SiT9122 (oscillatore MEMS programmabile 220--625\,MHz) --- richiede un ordine a specifica, non ancora confermato in stock. \\ clk\_ref\_p/n & 200\,MHz differenziale LVDS & \textbf{Confermato reale, in stock}: SiTime SiT9121AC-2CF-33E-200.00000, LCSC C835051. \\ \bottomrule \end{tabular} \end{table} \section{Protocollo SPI di gestione (per il firmware ESP32)} \label{sec:spi-protocol} Un byte di opcode (MSB-first) per transazione CS-basso, gestito da \texttt{spi\_host\_bridge\_v3.v}: \begin{table}[h] \centering \begin{tabular}{lp{2.3cm}p{3.5cm}p{5cm}} \toprule \textbf{Opcode} & \textbf{Nome} & \textbf{Payload} & \textbf{Scopo} \\ \midrule 0x00 & NOP & 0 byte & inerte \\ 0x0F & RESET & 0 byte & soft-reset \\ 0x10 & WRITE\_JOB & 16 byte & sottomette un job di inferenza \\ 0x20 & STATUS & 0 $\to$ 1 byte & bit di stato (busy, ultimo job accettato) \\ 0x01 & WRITE\_MEM & $4+2N$ byte & scrittura raw in DDR3 ($N$ parole) \\ 0x02 & READ\_MEM & 6 $\to$ 2$N$ byte & lettura raw da DDR3 ($N$ parole) \\ 0x30 & REG\_WRITE & 5 byte & scrive un registro di controllo \\ 0x31 & REG\_READ & 1 $\to$ 4 byte & legge un registro di stato/ID \\ 0x40 & FLASH\_XFER & $N \to N{+}2$ byte & passthrough grezzo verso la flash \\ \bottomrule \end{tabular} \caption{Riepilogo del protocollo SPI di gestione. Il layout completo dei campi \`e documentato nell'intestazione di \texttt{spi\_host\_bridge\_v3.v}.} \end{table} Un pin dedicato \texttt{data\_ready\_n} (attivo-basso, sticky) permette all'ESP32 di essere interrupt-driven invece di eseguire polling continuo su STATUS. \section{Procedura di avvio (boot)} Due percorsi reali, entrambi presenti sulla scheda per progetto: \begin{enumerate} \item \textbf{Primo avvio / recupero (JTAG, pilotato da ESP32)}: su una scheda vergine la flash \`e vuota --- solo JTAG pu\`o inizializzarla (vincolo reale, non aggirabile via SPI finch\'e la FPGA non esegue gi\`a la logica che relaya i comandi). \item \textbf{Avvio normale (Master SPI, autonomo)}: a ogni accensione successiva la FPGA si auto-configura dalla flash tramite il proprio hardware dedicato, senza intervento dell'ESP32. \item \textbf{Aggiornamento firmware sul campo} (\texttt{FLASH\_XFER}): a FPGA gi\`a in funzione, l'ESP32 pu\`o riscrivere la flash relayando byte SPI-NOR grezzi attraverso la FPGA. \end{enumerate}