Implementierung eines USB-1.0-Hostcontrollers in SpinalHDL für RISC-V-SoC
Die Entwicklung eines synthetisierbaren System-on-Chips auf RISC-V-Basis erfordert die Integration moderner Peripherieschnittstellen. Ein USB-1.0-Hostcontroller ermöglicht den Anschluss von HID-Eingabegeräten: Tastaturen, Mäusen, Gamepads. Die Implementierung in SpinalHDL bietet eine Hardware-Protokollbehandlung ohne die Software-Kompromisse von PS/2 oder analogen Joysticks.
Die USB-physische Schicht verwendet ein differentielles Paar D+ und D- sowie die Leitungen VBUS und GND. Der Halb-Duplex-Übertragungsmodus unterscheidet USB von UART: Daten werden bitweise in einer Richtung zur Zeit gesendet, mit strenger Trennung der Host- und Device-Rollen.
USB-1.0-Physische Schicht
Elektrische Kennwerte definieren die Signalebenen: Der Leerlaufzustand auf D+ und D- legt die Geschwindigkeit fest. Low-Speed (1,5 Mbit/s) — D- hoch, Full-Speed (12 Mbit/s) — D+ hoch. NRZI-Codierung: Signalübergang kodiert '1', Fehlen kodiert '0'. Synchronisation durch Bit-Stuffing: Nach sechs gleichen Bits wird ein invertiertes Bit eingefügt.
Steuersignale:
- SE0 (Single Ended Zero): beide D+/D- niedrig — für Bus-Reset.
- J/K-Zustände: differentielle Pegel für Leerlauf und Geschwindigkeit.
- Chirp: K/J-Austausch zur Geschwindigkeitserkennung von Hubs.
Übertragung beginnt mit SYNC (8 Bits '0'), gefolgt von PID (Packet-ID).
USB-Protokoll: Pakete und Transaktionen
PID definiert den Pakettyp:
- Tokens: SETUP (Control-Anfragen), IN (Lesen), OUT (Schreiben), SOF (Start of Frame).
- Data: DATA0/1 (Toggle-Bits für Integrität).
- Handshake: ACK (Bestätigung), NAK (Ablehnung), STALL (Fehler).
Transaktionen:
- Control-Transfer: SETUP + DATA (optional) + IN/OUT + ACK.
- Interrupt-Transfer: IN/OUT + DATA + ACK — für HID-Reports.
- Bulk-Transfer: große Blöcke, mit Wiederholung.
- Isochronous-Transfer: kein Handshake, für Streams.
Prüfsummen: CRC5 für Tokens, CRC16 für Daten. Formeln:
// CRC5 for address/kontsa
crc5_next = crc5_reg ^ data_in;
// Polinom: x^5 + x^2 + 1 (0b001101)
Deskriptoren und Geräteinitialisierung
Deskriptoren beschreiben das Gerät:
- Device Descriptor: bLength=18, bDescriptorType=1, idVendor, idProduct.
- Configuration Descriptor: bConfigurationValue, maxPower.
- Interface/Endpoint: bInterfaceClass (HID=3), bEndpointAddress, bmAttributes (Interrupt).
- HID Descriptor: bcdHID, bCountryCode, Report Descriptor.
Initialisierung:
- Bus-Reset (SE0 >10 μs).
- GET_DESCRIPTOR (Device).
- SET_ADDRESS.
- GET_DESCRIPTOR (Configuration).
- SET_CONFIGURATION.
Für HID zusätzlich GET_DESCRIPTOR (Report). Tastatur-Report-Beispiel: Modifier-Byte + reserved + 6 Keycodes.
Hardware-Implementierung in SpinalHDL
Der Controller ist als Hierarchie endlicher Zustandsmaschinen aufgebaut:
- USBMain: Haupt-FSM, steuert die Sequenz.
- USBSendSE0: SE0-Erzeugung für Reset.
- USBSendShortToken: kurze Tokens (SOF).
- USBSendLongToken: vollständige Tokens (Addr+Endp).
- USBSendData: NRZI-Codierung + Bit-Stuffing.
- USBReceiver: NRZI-Dekodierung, CRC-Prüfung.
Schnittstellen:
import spinal.core._
case class USB_IO() extends Bundle {
val dpp = in Bool()
val dpn = in Bool()
val txen = out Bool()
val txdp = out Bool()
val txdn = out Bool()
}
Apb3USB10Ctrl integriert in den SoC über APB3. Taktung: 48 MHz für Full-Speed.
Integration in KarnixSoC und Treiber
Anschluss: USB Type A auf dem Karna-Board, Signale vom FPGA geroutet. SpinalHDL-Konfiguration fügt das Modul zur Top-Level hinzu.
C-Treiber für RISC-V:
- usb10_bus_reset(): SE0 für 20 μs.
- usb10_in_request(): IN-Token + DATA1 + ACK.
- usb10_setup_request(): SETUP + DATA + IN.
Initialisierung: usb10_init() erkennt das Gerät, liest Deskriptoren, setzt Adresse.
Test mit HID-Geräten
Anwendung karnix_usb10_test:
- Gamepad: analoge Achsen, Tasten im Interrupt-Endpoint 1.
- Maus: X/Y-Delta, Tasten in 4-Byte-Reports.
- Tastatur: Boot-Protokoll, 8-Byte-Reports (Modifier + Tasten).
Integration in TetRISC-V: Ersetzung von PS/2 durch USB-Eingabe.
Wichtige Punkte:
- USB 1.0 Full-Speed (12 Mbit/s) implementiert mit FSM ohne MACRO-IP.
- SpinalHDL generiert RTL für FPGA-Synthese.
- HID Boot-Protokoll vereinfacht Treiber für Tastatur/Maus.
- NRZI + Bit-Stuffing erfordern präzises Timing (48-MHz-Takt).
- CRC5/16-Prüfung verhindert Paketfehler.
— Editorial Team
Noch keine Kommentare.