working with memory

This commit is contained in:
2026-09-02 13:09:20 +02:00
parent d4ae2417a4
commit 16769eaa4b
40 changed files with 1263404 additions and 3560 deletions
+929
View File
@@ -0,0 +1,929 @@
# FPGA-Neural — Analisi datapath e benchmark ECP5
## 1. Obiettivo
Questa fase del progetto FPGA-Neural ha avuto lo scopo di verificare il comportamento sintetizzabile e le prestazioni del core neurale parametrico sul dispositivo:
**Lattice LFE5U-45F-8BG381C**
Configurazione FPGA:
- ECP5-45F
- Speed grade: `-8`
- Package: `CABGA381`
- 72 blocchi `MULT18X18D`
- circa 43.8k LUT/FF equivalenti
La configurazione funzionale utilizzata nei benchmark è:
```text
DATA_WIDTH = 8 bit
ACC_WIDTH = 32 bit
N_INPUTS = 256
N_NEURONS = 4
PARALLEL = variabile
Il datapath implementa:
INT8 × INT8
INT16
sign extension
INT32
accumulation
+ bias
ReLU
INT8 saturation
Lo scopo principale del benchmark è stato determinare il compromesso tra:
numero di MAC paralleli;
utilizzo dei DSP;
complessità del datapath;
routing;
frequenza massima;
latenza di elaborazione.
2. Architettura RTL
L'attuale datapath è organizzato gerarchicamente:
layer
┌────────┴────────┐
│ │
neuron 0 neuron N
│ │
▼ ▼
neuron_parallel neuron_parallel
│ │
▼ ▼
mac8 mac8
│ │
MAC × PARALLEL MAC × PARALLEL
Ogni neurone elabora N_INPUTS ingressi a gruppi di PARALLEL.
Con:
N_INPUTS = 256
il numero di gruppi è:
GROUPS = 256 / PARALLEL
Pertanto:
PARALLEL Gruppi per neurone
16 16
8 32
4 64
2 128
I quattro neuroni vengono elaborati contemporaneamente.
3. MAC unit
Il modulo mac_unit implementa un singolo prodotto-accumulatore.
Per la configurazione INT8:
x : signed INT8
w : signed INT8
Il prodotto è:
INT8 × INT8 = INT16
Il risultato viene quindi esteso con segno a 32 bit:
INT16 → INT32
e sommato all'accumulatore.
L'operazione fondamentale è quindi:
acc_out = acc_in + (x × w)
L'implementazione è completamente parametrica rispetto a:
DATA_WIDTH
ACC_WIDTH
4. Balanced adder tree
Una modifica importante rispetto alla prima implementazione è stata la sostituzione dell'accumulatore combinazionale lineare con un balanced binary adder tree.
Una riduzione lineare avrebbe prodotto:
((((p0 + p1) + p2) + p3) + ...)
con profondità:
O(PARALLEL)
La nuova implementazione utilizza invece:
sum
/ \
sum sum
/ \ / \
p0 p1 p2 p3
La profondità diventa:
O(log2(PARALLEL))
Per esempio:
PARALLEL = 8
→ 3 livelli
PARALLEL = 16
→ 4 livelli
PARALLEL = 32
→ 5 livelli
Questa modifica riduce significativamente la profondità combinazionale del datapath.
5. neuron_parallel
neuron_parallel esegue il calcolo di un singolo neurone.
Il funzionamento è:
start
group 0
group 1
...
group N
+ bias
ReLU
saturation
done
Durante ogni ciclo viene elaborato un gruppo di:
PARALLEL
prodotti.
L'accumulatore mantiene il risultato tra un gruppo e il successivo.
6. Test funzionale
Il testbench sim/parametric_tb.v utilizza:
DATA_WIDTH = 8
N_INPUTS = 256
N_NEURONS = 4
PARALLEL = variabile
ACC_WIDTH = 32
Sono stati definiti quattro casi di test.
N0 — accumulazione su più gruppi
Input:
x = 1
Pesi:
primi 32 = +1
restanti = 0
Risultato:
32 × 1 × 1 = 32
Output atteso:
32
Questo test verifica soprattutto la corretta gestione dell'accumulatore attraverso più gruppi.
N1 — bias
Pesi:
tutti = 0
Bias:
+10
Output atteso:
10
N2 — ReLU
Pesi:
tutti = -1
Input:
tutti = +1
Il risultato è negativo.
La ReLU produce:
0
N3 — saturazione
Pesi:
primi 32 = +4
restanti = 0
Input:
tutti = +1
Risultato:
32 × 4 = 128
L'uscita INT8 positiva viene saturata:
128 → 127
7. Risultato simulazione
Il test è passato con PARALLEL=16:
PARALLEL = 16
PASS N0: 32
PASS N1: 10
PASS N2: 0 (ReLU)
PASS N3: 127 (saturation)
INT8 PARAMETRIC TEST PASSED
È passato anche con PARALLEL=32:
PARALLEL = 32
PASS N0: 32
PASS N1: 10
PASS N2: 0 (ReLU)
PASS N3: 127 (saturation)
INT8 PARAMETRIC TEST PASSED
La correttezza funzionale del datapath parametrico è quindi confermata.
8. Sintesi e Place & Route
Dopo la simulazione il datapath è stato sintetizzato per ECP5 utilizzando:
Yosys
e successivamente piazzato e instradato con:
nextpnr-ecp5
Target:
LFE5U-45F
CABGA381
Speed grade -8
Il wrapper di benchmark genera internamente:
input;
pesi;
bias;
segnali di test.
In questo modo non vengono portati all'esterno i giganteschi bus del modello neurale.
Il top-level espone solamente:
clk
rst
start
y_bus
busy
done
Questa modifica è stata fondamentale.
Il primo tentativo esponeva infatti direttamente:
x_bus ≈ 2048 bit
weights ≈ 8192 bit
bias ≈ 32 bit
portando a oltre 10.000 I/O fisiche richieste.
Il risultato era:
TRELLIS_IO: 10309/245
e quindi un errore di placement.
Il problema non era la dimensione logica del circuito, ma esclusivamente il numero di I/O.
9. PARALLEL = 16
Risorse sintetizzate:
LUT4 ≈ 2531
DFF = 186
Risorse FPGA:
MULT18X18D = 64 / 72
quindi:
88% dei DSP
Timing:
Fmax ≈ 52.13 MHz
Tcrit ≈ 19.18 ns
Il percorso critico risultava fortemente influenzato dal routing.
Configurazione:
PARALLEL = 16
N_NEURONS = 4
produce:
16 × 4 = 64 MAC simultanei
10. PARALLEL = 8
Risorse:
MULT18X18D = 32 / 72
quindi:
32 DSP
Con quattro neuroni:
8 × 4 = 32 MAC simultanei
Timing:
Fmax ≈ 61.71 MHz
Tcrit ≈ 16.20 ns
Composizione del percorso critico:
logic ≈ 6.43 ns
routing ≈ 9.77 ns
total ≈ 16.20 ns
Questa configurazione è particolarmente importante perché corrisponde esattamente al target originale di:
32 MAC hardware simultanei
11. PARALLEL = 4
Risorse:
LUT4 = 804
DFF = 194
MULT18X18D = 16 / 72
Quindi:
16 MAC simultanei
Timing:
Fmax ≈ 75.01 MHz
Tcrit ≈ 13.33 ns
Composizione:
logic ≈ 6.67 ns
routing ≈ 6.66 ns
total ≈ 13.33 ns
In questa configurazione logica e routing sono quasi perfettamente bilanciati.
12. PARALLEL = 2
Risorse:
LUT4 = 481
DFF = 198
MULT18X18D = 8 / 72
Quindi:
8 MAC simultanei
Timing finale dopo routing:
Fmax ≈ 87.88 MHz
Tcrit ≈ 11.38 ns
Composizione:
logic ≈ 6.43 ns
routing ≈ 4.95 ns
total ≈ 11.38 ns
Il design è stato quindi verificato con target:
80 MHz
ottenendo:
87.88 MHz
e:
PASS
Il margine teorico rispetto a 80 MHz è:
T80MHz = 12.50 ns
12.50 - 11.38 ≈ 1.12 ns
13. Tabella comparativa
PARALLEL MAC/neurone Neuroni MAC totali DSP Fmax Tcrit 80 MHz
16 16 4 64 64 52.13 MHz 19.18 ns FAIL
8 8 4 32 32 61.71 MHz 16.20 ns FAIL
4 4 4 16 16 75.01 MHz 13.33 ns FAIL
2 2 4 8 8 87.88 MHz 11.38 ns PASS
14. Interpretazione
I risultati mostrano chiaramente il trade-off fondamentale.
Riducendo PARALLEL:
PARALLEL ↓
MAC simultanei ↓
DSP ↓
adder tree ↓
routing/congestione ↓
Fmax ↑
ma contemporaneamente:
PARALLEL ↓
numero gruppi ↑
cicli necessari ↑
latenza ↑
Quindi la frequenza massima non è sufficiente per scegliere la configurazione.
Occorre considerare il throughput complessivo:
throughput ≈ MAC_per_cycle × clock_frequency
A parità di quattro neuroni:
P2
8 MAC × 87.88 MHz
≈ 703 M MAC/s
P4
16 MAC × 75.01 MHz
≈ 1.20 G MAC/s
P8
32 MAC × 61.71 MHz
≈ 1.97 G MAC/s
P16
64 MAC × 52.13 MHz
≈ 3.34 G MAC/s
Questi valori sono una misura teorica del throughput del datapath MAC, non ancora del throughput end-to-end della rete, perché non includono i limiti della memoria esterna, del trasferimento dei pesi e del controller.
15. Scelta architetturale
Il risultato più importante del benchmark è che PARALLEL=8 rimane il candidato naturale per l'architettura V1 se l'obiettivo iniziale di progetto è mantenere circa:
32 MAC simultanei
Infatti:
PARALLEL = 8
N_NEURONS = 4
→ 32 MAC
→ 32 DSP / 72
→ 61.71 MHz
L'utilizzo DSP è ancora relativamente basso:
44% circa
lasciando risorse per:
controller memoria;
buffer;
interfaccia SPI;
DMA;
gestione layer;
eventuali pipeline;
future funzioni di controllo.
PARALLEL=2 è invece la configurazione più semplice da temporizzare tra quelle testate:
87.88 MHz
e passa il target di 80 MHz.
Tuttavia richiede:
128 gruppi
per elaborare un neurone da 256 ingressi.
Per questo motivo non è opportuno adottarlo automaticamente come configurazione definitiva solo perché raggiunge la frequenza più elevata.
16. Timing a 100 MHz
Il target di:
100 MHz
non viene attualmente raggiunto.
Il miglior risultato è:
87.88 MHz
con PARALLEL=2.
Il percorso critico è ancora:
weight FF
MULT18X18D
products
adder/carry chain
acc_next
ReLU / saturation
output FF
Il problema non è quindi un'elevata occupazione delle risorse FPGA.
Al contrario, con P2 l'FPGA è utilizzato molto poco:
DSP ≈ 11%
LUT ≈ 1%
FF ≈ 0%
Il limite è principalmente temporale e dipende dal datapath combinazionale.
Per superare 100 MHz sarà probabilmente necessario introdurre una o più pipeline interne.
Questa ottimizzazione non è però ancora necessaria per procedere con la prossima fase architetturale.
17. Vincoli LPF
Durante questi benchmark il file:
synth/ecp5/top.lpf
è stato lasciato senza vincoli di pin.
nextpnr viene eseguito con:
--lpf-allow-unconstrained
Pertanto i numerosi warning relativi a I/O non vincolate sono intenzionali.
Il benchmark verifica quindi:
sintesi
placement
routing
timing
e non:
pin assignment
I/O standard della scheda
signal integrity
I vincoli LPF reali verranno aggiunti quando sarà definito il pinout della scheda FPGA-Neural.
18. Decisione per la prossima fase
Non è utile proseguire con benchmark PARALLEL=1.
Il punto di interesse architetturale è già stato individuato.
La prossima fase deve spostare il progetto dal benchmark sintetico verso l'architettura reale:
HOST
│ SPI
FPGA interface
Memory interface
┌───────────┴───────────┐
▼ ▼
PSRAM 8 MB FPGA BRAM
│ │
└──────────┬────────────┘
tile/buffer
MAC engine
accumulator
activation
output
Il core layer e neuron_parallel dovrà quindi essere separato dalla memoria fisica attraverso una Memory Interface.
19. Memoria V1
La memoria di lavoro prevista è:
ISSI IS66WVE4M16EBLL-70BLI
Caratteristiche:
64 Mbit
8 MB
4M × 16
parallel PSRAM
asynchronous/page mode
70 ns
2.73.6 V
48-TFBGA
6 × 8 mm
La memoria volatile sarà utilizzata come working memory durante l'inferenza.
La memoria persistente prevista è:
Winbond W25Q128JVS
con:
128 Mbit
16 MB
SPI NOR Flash
La divisione dei ruoli è:
W25Q128JVS
persistent storage
weights
biases
network metadata
FPGA/network configuration
e:
IS66WVE4M16EBLL
runtime working memory
input/output tensors
intermediate data
weight tiles
Infine:
FPGA BRAM
local working buffers
tiles
accumulators
20. Conclusioni
La fase di caratterizzazione del datapath ha prodotto i seguenti risultati:
Il datapath INT8/INT32 è funzionalmente corretto.
Il test parametrico è passato.
Il balanced adder tree ha sostituito con successo la precedente riduzione lineare.
Il design è sintetizzabile per LFE5U-45F.
Il placement e routing sono stati completati correttamente.
Il problema iniziale delle migliaia di I/O è stato eliminato spostando i test vector all'interno del wrapper.
PARALLEL=8 implementa esattamente 32 MAC simultanei con quattro neuroni.
PARALLEL=2 raggiunge 87.88 MHz e supera il target di 80 MHz.
Il limite attuale a 100 MHz è dovuto al percorso combinazionale, non alla saturazione delle risorse FPGA.
Non è necessario continuare il benchmark verso PARALLEL=1.
La baseline architetturale rimane quindi:
LFE5U-45F-8BG381C
INT8 / INT32
256 inputs
4 neurons
PARALLEL parametrico
con:
PARALLEL = 8
come candidato principale per la configurazione orientata al throughput e:
PARALLEL = 2
come riferimento per la configurazione orientata alla frequenza.
La prossima attività significativa è l'integrazione della Memory Interface con la PSRAM esterna, mantenendo PARALLEL come parametro del motore computazionale.
Appendice A — Toolchain
Yosys
Yosys è il tool di sintesi RTL.
Flusso:
Verilog RTL
elaborazione
ottimizzazione
mapping ECP5
JSON netlist
Versione utilizzata:
Yosys 0.68+post
Binary:
/opt/homebrew/bin/yosys
Project Trellis
Project Trellis fornisce il database open-source dell'architettura ECP5 e gli strumenti necessari all'implementazione.
Tra gli strumenti disponibili:
ecppack
ecppll
ecpbram
ecpunpack
Installazione utilizzata:
/tmp/prjtrellis/install
nextpnr-ecp5
nextpnr-ecp5 esegue:
placement
routing
timing analysis
Versione:
nextpnr-0.11.1-19-g8dbcee5
Binary:
/tmp/nextpnr/build/nextpnr-ecp5
Parametri principali:
--45k
seleziona LFE5U-45F.
--package CABGA381
seleziona il package.
--speed 8
seleziona speed grade -8.
--json
carica la netlist generata da Yosys.
--lpf
carica i vincoli di pin.
--lpf-allow-unconstrained
permette I/O non vincolate.
--freq 80
richiede un timing target di 80 MHz.
Icarus Verilog
Icarus Verilog viene utilizzato per la simulazione RTL.
Esempio:
iverilog -g2012 \
-Ptb.PARALLEL=16 \
-o sim/parametric_256x4_p16 \
sim/parametric_tb.v \
rtl/mac_unit.v \
rtl/mac8.v \
rtl/neuron_parallel.v \
rtl/layer.v
Esecuzione:
vvp sim/parametric_256x4_p16
Icarus verifica principalmente la correttezza funzionale del RTL.
Appendice B — Differenza tra simulazione e implementazione
Simulazione
Icarus Verilog
verifica:
algebra signed;
prodotti;
accumulazione;
gruppi;
bias;
ReLU;
saturazione;
segnali busy e done.
Implementazione
Yosys
+
nextpnr-ecp5
verifica:
sintetizzabilità;
mapping FPGA;
LUT;
FF;
DSP;
placement;
routing;
timing;
Fmax.
Le due verifiche sono complementari.
r
Appendice C — Stato attuale
RTL funzionale PASS
Simulazione parametrica PASS
Sintesi ECP5 PASS
Placement PASS
Routing PASS
PARALLEL=16 52.13 MHz
PARALLEL=8 61.71 MHz
PARALLEL=4 75.01 MHz
PARALLEL=2 87.88 MHz
Target 80 MHz, P2 PASS
Target 100 MHz FAIL
Memory Interface DA IMPLEMENTARE
PSRAM controller DA IMPLEMENTARE
Host SPI interface DA IMPLEMENTARE
Layer engine reale PROSSIMA FASE