Heim Der Blog Blog Details

Wie verbindet man einen externen Speicher mit einem FPGA?

September 18 2025
Ampheo

Anfrage

Globaler Lieferant elektronischer Komponenten AMPHEO PTY LTD: Umfangreiches Inventar für One-Stop-Shopping. Einfache Anfragen, schnelle, individuelle Lösungen und Angebote.

SCHNELLE ANFRAGE
ZUR RFQ-LISTE HINZUFÜGEN
Hier ist ein praxisnaher Leitfaden für FPGA-Ingenieur:innen zum Anschluss externer Speicher – was man auswählt, wie man es verdrahtet, welche IP man nutzt und wie man Timing sicher einhält und das Ganze sauber in Betrieb nimmt.

Hier ist ein praxisnaher Leitfaden für FPGA-Ingenieur:innen zum Anschluss externer Speicher – was man auswählt, wie man es verdrahtet, welche IP man nutzt und wie man Timing sicher einhält und das Ganze sauber in Betrieb nimmt.

Wie verbindet man einen externen Speicher mit einem FPGA?

1) Den passenden Speicher wählen

  • Paralleles asynchrones SRAM (z. B. 10–20 ns): Am einfachsten zu integrieren; ideal für kleine, latenzarme Puffer oder Frame-FIFOs. Begrenzte Kapazität und Bandbreite.

  • SDR/DDR-SDRAM (DDR2/DDR3/DDR4/LPDDR): Hohe Bandbreite (GB/s). Verwende den Speichercontroller des Herstellers. Optimal für Framebuffer, ML-Scratch, große Caches.

  • NOR-Flash (SPI/QSPI/OSPI): Für XIP (Execute-in-Place), Bitstreams, Code-Speicher. Langsame Schreibzugriffe; sehr gute Random-Reads.

  • NAND-Flash / eMMC / SD: Hohe Kapazität für Datenlogging. Benötigt Wear-Leveling (im Controller oder in der FS-Schicht).

  • HyperRAM / Octal-SPI-PSRAM: Mittelweg – geringe Pinzahl wie SPI, aber deutlich schneller (bis einige 100 MB/s).

  • MRAM/FRAM: Nichtflüchtig mit SRAM-ähnlichem Zugriff; kleinere Größen; einfache Controller.

Faustregel:
Braucht ihr Bandbreite, nehmt DDR. Braucht ihr Einfachheit/Latenz, nehmt SRAM/HyperRAM. Braucht ihr Nichtflüchtigkeit, nehmt (Q)SPI-NOR (Code) oder NAND/eMMC (Masse-Speicher).

2) I/Os & Banks vor dem PCB planen

  • I/O-Standard & Spannung:

    • DDR3/DDR4: SSTL/POD (z. B. SSTL15, POD12) mit Vref-Pins; differentielle Takte (CK/CK#), pro Byte DQS/DQS#-Strobes, ODT/RESET-Leitungen.

    • SRAM/Flash: LVCMOS (1,8 V/2,5 V/3,3 V), teils Dual-Voltage-Banks.

  • Bank-Auswahl: Halte eine komplette DDR-Byte-Lane (DQ[7:0], DQS, DM) in einer Bank; keine Bank-Überkreuzungen.

  • Pin-Swapping: Datenbits dürfen innerhalb einer Byte-Lane getauscht werden; DQS muss bei seinem Byte bleiben.

  • Clocking: Einen MMCM/PLL für die Speicher-Controller-Takte reservieren; plane eine asynchrone Domain-Kreuzung zu deinem System-AXI-Takt.

3) Die passende Controller-IP nutzen

  • DDRx:

    • Xilinx: MIG (Memory Interface Generator).

    • Intel/Altera: EMIF/UniPHY.

    • Lattice: Gerätespezifische DDR-Hard/Soft-IP.
      Liefert PHY+Controller, Kalibrierlogik, Beispiel-Designs und Constraints.

  • (Q)SPI/OSPI, HyperBus, SD/eMMC: Hersteller-IP oder bewährte Open-Cores verwenden; nach außen AXI4 (oder Avalon/Wishbone) anbieten.

  • SRAM/PSRAM: Kleiner FSM oder generischer SRAM-Controller reicht; oft via Lightweight-Bridge speicherabgebildet an AXI.

4) Topologie & PCB-Richtlinien (High-Level)

  • DDR Fly-By (typisch bei DDR3/4): CK/ADDR/CMD in Kettenführung; DQS innerhalb jeder Byte-Lane längenmatchen; kurze Stubs, kontrollierte Impedanz, solide Referenzebenen.

  • Abschluss/Termination: Datenblatt/IP-Wizard folgen (z. B. ODT-Einstellungen, Serienwiderstände bei Parallelbussen).

  • Platzierung: Speicher nahe an der passenden FPGA-Bank; kurze, gematchte Byte-Lanes; DQS-Paare sehr eng führen.

  • Power-Integrität: Viele Hochfrequenz-Kondensatoren in Nähe von Speicher und FPGA-I/O-Banks.

5) Timing & Constraints (nicht auslassen!)

  • Hersteller-IP generiert XDC/SDC mit Clocks, IODELAY/PHASER-Settings und False-Path-Ausnahmen – so übernehmen, dann eigene System-Constraints ergänzen (AXI-Clocks, CDC-FIFOs).

  • Für asynchrones SRAM/HyperRAM explizit create_clock und set_input_delay/set_output_delay relativ zum Speicher-Takt schreiben; Leiterbahn-Verzögerungen (grob 150–170 ps/Zoll, besser aus dem Stackup nehmen) und tSU/tH/tCO aus dem Datenblatt einrechnen.

Minimales Beispiel (Idee für async-SRAM, kein vollständiges XDC):

 
create_clock -name sram_clk -period 20.000 [get_ports sram_clk] ;# 50 MHz
set_output_delay -clock sram_clk  tSU_ns  [get_ports {sram_addr[*] sram_we_n sram_oe_n sram_cs_n}]
set_input_delay  -clock sram_clk  tCO_ns  [get_ports {sram_dq[*]}]

6) Einfacher Lese/Schreib-Ablauf für async-SRAM (Konzept)

 

// 16-Bit asynchrones SRAM, getrennte Addr/Data, OE#/WE#/CS#
assign sram_oe_n = ~(read_req  & chip_select);
assign sram_we_n = ~(write_req & chip_select);
assign sram_cs_n = ~chip_select;

// Tri-State-Datenbus
assign sram_dq   = (write_req && chip_select) ? write_data : 16'hzzzz;

always @(posedge clk) begin
  if (read_req && chip_select) read_data <= sram_dq; // nach gültigem OE# & tAA sampeln
end

Erweitere um Wait-States (tAA/tOE/tRC) und eine kleine FSM für Burst-Reads/Writes.

7) DDR: Praktischer Bring-Up-Ablauf (Xilinx-MIG-Beispiel)

  1. MIG mit eurem Bauteil + Speicher-Datenblatt konfigurieren: Datenbreite, Speed-Grade, Timing, ODT, Pinout.

  2. Board anhand des von MIG exportierten Pinouts platzieren/ROUTEN.

  3. In Vivado MIG-Core instantiieren → AXI mit eurer Logik (DMA/Video/CPU) verbinden.

  4. Takte (MMCM) genau wie im MIG-Beispiel erzeugen.

  5. Bitstream laden + MIG-Beispiel ausführen (inkl. Kalibrierung). Prüfen, dass „calib done“-LED/Flag aktiv ist.

  6. Mit Traffic belasten: AXI-DMA-Memtests, Video-Write/Read-Loops. ILA beobachten (DQS/DQ-Phasenprobleme).

8) Bandbreite dimensionieren (Schnellrechnung)

Bandbreite (Bytes/s) ≈ bus_width_bytes × transfers_per_cycle × f_clk

  • DDR3, x16 @ 800 MT/s → 2 Transfers/Takt × 16 Bit = 1,6 GB/s theoretisch (vor Effizienzverlusten).

  • HyperRAM, x8 @ 200 MT/s DDR → ca. 400 MB/s-Klasse.

  • QSPI @ 100 MHz DDR (4 Bit) → ca. 100 MB/s Best-Case (controller/latency-abhängig).

9) Bewährte Architektur-Muster

  • AXI-Fabric + DMA: Hochratige Daten zu/von DDR streamen (Videoframes, ADC-Samples).

  • Ping-Pong-Puffer: Zwei (oder mehr) Framebuffer zur Latenzverdeckung.

  • Cache/ECC: Für Soft-CPUs Cache aktivieren; für Zuverlässigkeit ECC erwägen (z. B. 64+8 = 72-Bit-DDR).

  • Clock-Domains: System ↔ Speicher per AXI-Clock-Converter oder FIFOs kreuzen.

10) Software & Boot-Images (häufige Setups)

  • QSPI-NOR: FPGA-Bitstream und CPU-Firmware ablegen; optional XIP für Soft/Hard-CPU.

  • NAND/eMMC/SD: Dateisystem mit Wear-Leveling; Bootloader, falls Code ausgeführt werden soll.

  • Memory-Map: Klare Basisadressen definieren; Burst-Alignment und Max-Längen für DMA dokumentieren.

11) Validierungs-Checkliste

  • Muster-Tests: Walking-1/0, Adresse-als-Daten, 0xAA/0x55, Zufall, Row/Column-Strides.

  • Thermik & Spannungsecken: DDR-Kalibrierung über Temperatur erneut fahren; Margen prüfen (MPR/Read-Eye falls verfügbar).

  • Signal-Integrität: CK/DQS/DQ an Testpunkten messen; ODT/Drive-Settings verifizieren.

  • Durchsatz: Mit AXI-Performance-Monitor messen; mit der Theorie vergleichen.

12) Häufige Fallstricke (mit Abhilfe)

  • DQS/DQ nicht längengematcht → Kalibrierfehler oder sporadische Fehler. Routing fixen oder Interface verlangsamen.

  • Bank/Vref-Fehler → DDR trainiert nicht. I/O-Standards und Referenzschienen doppelt prüfen.

  • Byte-Lanes über mehrere Banks → Skew, den die PHY nicht ausgleichen kann. Bytes zusammen halten.

  • Falsches ODT/Termination → Eye-Collapse. Zuerst IP-Empfehlungen verwenden.

  • Keine I/O-Timing-Constraints bei einfachen Bussen → Läuft im Labor, fällt bei Temperatur durch. Realistische I/O-Delays ergänzen.

  • Clocking-Mismatch → AXI-Timeouts/Underruns. FIFOs einsetzen oder Burstgrößen anpassen.

Ampheo