Wie implementiert man UART, SPI oder I2C in einem FPGA?
Globaler Lieferant elektronischer Komponenten AMPHEO PTY LTD: Umfangreiches Inventar für One-Stop-Shopping. Einfache Anfragen, schnelle, individuelle Lösungen und Angebote.
Die Implementierung von UART, SPI oder I2C in einem FPGA erfordert das Entwerfen oder Verwenden bestehender Verilog/VHDL-Module, die diese Kommunikationsprotokolle handhaben. Nachfolgend sind die wichtigsten Schritte und Überlegungen für jedes Protokoll aufgeführt.
1. UART (Universal Asynchronous Receiver-Transmitter)
UART ist ein einfaches serielles Protokoll mit TX (Senden) und RX (Empfangen) und konfigurierbarer Baudrate.
Implementierungsschritte
Sender (UART_TX)
-
Baudraten-Generator:
-
Erzeugt ein Taktsignal mit der gewünschten Baudrate (z. B. 9600, 115200 Baud).
-
Beispiel für 100 MHz FPGA-Takt und 115200 Baud:
localparam CLK_FREQ = 100_000_000; localparam BAUD_RATE = 115200; localparam BAUD_COUNT = CLK_FREQ / BAUD_RATE;
-
-
Zustandsautomat für TX:
-
Leerlauf → Startbit (0) → 8 Datenbits → Stoppbit (1).
-
Datenbits nacheinander ausgeben.
-
Empfänger (UART_RX)
-
Oversampling (optional, aber empfohlen):
-
Abtasten der RX-Leitung mit 16x Baudrate für Rauschimmunität (z. B. Erkennung des Startbits durch mehrere Abtastwerte).
-
-
Zustandsautomat für RX:
-
Warten auf Startbit → 8 Datenbits einlesen → Stoppbit prüfen.
-
Beispiel für ein UART-Modul (Verilog)
module uart_tx ( input clk, input [7:0] data, input tx_start, output reg tx, output reg tx_done ); reg [3:0] bit_counter = 0; reg [15:0] baud_counter = 0; reg [9:0] shift_reg = 10'b1_11111111_0; // Stopp + Daten + Start always @(posedge clk) begin if (tx_start) shift_reg <= {1'b1, data, 1'b0}; // Daten laden if (baud_counter == BAUD_COUNT-1) begin tx <= shift_reg[0]; shift_reg <= {1'b1, shift_reg[9:1]}; // Rechts schieben bit_counter <= bit_counter + 1; if (bit_counter == 9) tx_done <= 1; end end endmodule
2. SPI (Serial Peripheral Interface)
SPI ist ein synchrones, vollduplex-Protokoll mit SCLK (Takt), MOSI (Master Out Slave In), MISO (Master In Slave Out) und CS (Chip Select).
Implementierungsschritte
SPI-Master
-
SCLK erzeugen (einstellbare Frequenz, CPOL, CPHA).
-
Daten über MOSI senden und über MISO empfangen (getaktet).
-
CS (Chip Select) steuern (aktiv-low für Slave-Auswahl).
SPI-Slave
-
MOSI bei SCLK-Flanken einlesen (abhängig von CPHA/CPOL).
-
MISO steuern, wenn CS aktiv ist.
Beispiel für SPI-Master (Verilog)
module spi_master ( input clk, input [7:0] data, input start, output reg sclk, mosi, cs, output reg [7:0] miso_data ); reg [2:0] bit_counter = 0; reg [7:0] shift_reg; always @(posedge clk) begin if (start) begin cs <= 0; shift_reg <= data; bit_counter <= 0; end if (!cs) begin sclk <= ~sclk; // Takt toggeln if (sclk) begin // Bei steigender Flanke mosi <= shift_reg[7]; shift_reg <= {shift_reg[6:0], miso}; // MISO einlesen bit_counter <= bit_counter + 1; if (bit_counter == 7) cs <= 1; // Fertig end end end endmodule
3. I2C (Inter-Integrated Circuit)
I2C ist ein Zwei-Draht-Protokoll (SDA, SCL) mit Multi-Master- und Multi-Slave-Fähigkeit und 7/10-Bit-Adressierung.
Implementierungsschritte
I2C-Master
-
SCL (Takt) erzeugen (~100 kHz im Standardmodus, ~400 kHz im Fast Mode).
-
I2C-Zustandsautomat:
-
Startbedingung (SDA fällt, während SCL hoch ist).
-
7-Bit-Adresse + R/W-Bit senden.
-
Auf ACK warten (SDA wird vom Slave auf Low gezogen).
-
Datenbytes senden/empfangen.
-
Stoppbedingung (SDA steigt, während SCL hoch ist).
-
I2C-Slave
-
Startbedingung erkennen (SDA/SCL überwachen).
-
Adressabgleich prüfen (ACK senden, wenn übereinstimmend).
-
Daten lesen/schreiben basierend auf R/W-Bit.
Beispiel für I2C-Master (Verilog)
module i2c_master ( input clk, input [6:0] addr, input [7:0] data, input start, inout sda, output scl ); reg sda_out, scl_out; reg [3:0] state = 0; assign sda = (sda_out) ? 1'bz : 1'b0; // Open-Drain assign scl = (scl_out) ? 1'bz : 1'b0; always @(posedge clk) begin case (state) 0: if (start) begin // Startbedingung sda_out <= 0; state <= 1; end 1: begin // Adresse + R/W senden scl_out <= 1; sda_out <= addr[6]; // MSB zuerst state <= 2; end // ... (ACK-Prüfung, Datenübertragung, Stoppbedingung) endcase end endmodule
Vergleichstabelle
Protokoll | Geschwindigkeit | Leitungen | Komplexität | Anwendungsfall |
---|---|---|---|---|
UART | Langsam (bis ~4 Mbps) | 2 (TX, RX) | Einfach | Debugging, PC-Kommunikation |
SPI | Schnell (bis 100+ MHz) | 4 (SCLK, MOSI, MISO, CS) | Mittel | Hochgeschwindigkeitssensoren, Flash-Speicher |
I2C | Langsam (~100-400 kHz) | 2 (SDA, SCL) | Komplex (Multi-Master) | Niedriggeschwindigkeitssensoren, EEPROM |
Wichtige Tipps
-
Verwenden Sie FIFOs zur Datenpufferung bei UART/SPI/I2C.
-
Implementieren Sie Clock Domain Crossing (CDC), wenn verschiedene Taktdomänen verwendet werden.
-
Nutzen Sie FPGA-Hersteller-IP-Cores (Xilinx AXI UART, Intel SPI Controller) für schnelle Integration.
-
Simulieren Sie mit Tools wie ModelSim/GTKWave vor der Implementierung.
Verwandte Artikel
- ·Entwurf eines multifunktionalen Roboterarmsystems mit Gestenerkennungssteuerung auf Basis der FPGA-Technologie
- ·Entwurfstechniken zur Reduzierung des FPGA-Stromverbrauchs
- ·Was sind die wichtigsten Merkmale der Intel 8085 / 8086 / ARM Cortex-A-Serie?
- ·Kosten-Effektivität im Vergleich: Altera vs Xilinx vs Lattice
- ·Wie werden FPGAs in AI/ML Anwendungen eingesetzt?
- ·Wie bootet man Linux auf einem Xilinx FPGA?
- ·Ist ein FPGA-Chip für die Algorithmusentwicklung geeignet?
- ·Die besten MCUs/MPUs für industrielle humanoide Roboter
- ·Was sind die Unterschiede zwischen FPGA- und DSP-Prozessoren für die Signalverarbeitung?