Powrót do strony głównej

Kontroler USB 1.0 na SpinalHDL: implementacja

Artykuł opisuje implementację kontrolera hosta USB 1.0 na SpinalHDL dla RISC-V SoC. Omówiono warstwę fizyczną, protokół, deskryptory HID, sprzętowe FSM i sterownik. Przykłady testowania z klawiaturą, myszą, gamepadem.

SpinalHDL USB 1.0: od protokołu do FPGA
Advertisement 728x90

# Implementacja kontrolera hosta USB 1.0 w SpinalHDL dla SoC RISC-V

Rozwój syntetyzowalnego system-on-chip na bazie RISC-V wymaga integracji nowoczesnych interfejsów peryferyjnych. Kontroler hosta USB 1.0 umożliwia podłączanie urządzeń HID wejściowych: klawiatur, myszy, gamepadów. Realizacja w SpinalHDL zapewnia sprzętową obsługę protokołu bez programowych kompromisów PS/2 czy analogowych dżojstików.

Warstwa fizyczna USB korzysta z pary różnicowej D+ i D-, linii VBUS i GND. Półdupleksowy tryb transmisji odróżnia USB od UART: dane są przesyłane bit po bicie w jednym kierunku, z obowiązkowym podziałem ról host i device.

Warstwa fizyczna USB 1.0

Charakterystyki elektryczne określają poziomy sygnałów: stan idle na D+ i D- ustala prędkość. Low-speed (1.5 Mbit/s) — D- wysoki, full-speed (12 Mbit/s) — D+ wysoki. Kodowanie NRZI: przejście sygnału koduje '1', brak — '0'. Synchronizacja przez bit stuffing: po sześciu identycznych bitach wstawiany jest odwrócony bit.

Google AdInline article slot

Sygnały służbowe:

  • SE0 (Single Ended Zero): oba D+/D- niskie — do resetu magistrali.
  • Stany J/K: poziomy różnicowe dla idle i prędkości.
  • Chirp: wymiana K/J do określenia prędkości huba.

Transmisja zaczyna się od SYNC (8 bitów '0'), po którym następuje PID (Packet ID).

Protokół USB: pakiety i transakcje

PID określa typ pakietu:

Google AdInline article slot
  • Tokeny: SETUP (żądania kontrolne), IN (odczyt), OUT (zapis), SOF (start of frame).
  • Dane: DATA0/1 (toggle bits dla integralności).
  • Handshake: ACK (potwierdzenie), NAK (odmowa), STALL (błąd).

Transakcje:

  • Control Transfer: SETUP + DATA (opcjonalnie) + IN/OUT + ACK.
  • Interrupt Transfer: IN/OUT + DATA + ACK — dla raportów HID.
  • Bulk Transfer: duże bloki, z retry.
  • Isochronous: bez handshake, dla strumieni.

Sumy kontrolne: CRC5 dla tokenów, CRC16 dla danych. Formuły:

// CRC5 dla adresu/końca
crc5_next = crc5_reg ^ data_in;
// Polinom: x^5 + x^2 + 1 (0b001101)

Deskryptory i inicjalizacja urządzenia

Deskryptory opisują urządzenie:

Google AdInline article slot
  • 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.

Inicjalizacja:

  • Bus Reset (SE0 >10 μs).
  • GET_DESCRIPTOR (Device).
  • SET_ADDRESS.
  • GET_DESCRIPTOR (Configuration).
  • SET_CONFIGURATION.

Dla HID dodatkowo GET_DESCRIPTOR (Report). Przykładowy raport klawiatury: bajt modyfikatorów + reserved + 6 kodów klawiszy.

Sprzętowa realizacja w SpinalHDL

Kontroler jest zbudowany jako hierarchia automatów skończonych:

  • USBMain: główny FSM, zarządza sekwencją.
  • USBSendSE0: generowanie SE0 dla resetu.
  • USBSendShortToken: krótkie tokeny (SOF).
  • USBSendLongToken: pełne tokeny (addr+endp).
  • USBSendData: kodowanie NRZI + bit stuffing.
  • USBReceiver: dekodowanie NRZI, sprawdzenie CRC.

Interfejsy:

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 integruje w SoC przez APB3. Taktyka: 48 MHz dla full-speed.

Integracja w KarnixSoC i sterownik

Podłączenie: USB Type A na płycie „Karno”, wyprowadzenie sygnałów z FPGA. Konfiguracja SpinalHDL dodaje moduł do topu.

Sterownik w C dla RISC-V:

  • usb10_bus_reset(): SE0 20 μs.
  • usb10_in_request(): token IN + DATA1 + ACK.
  • usb10_setup_request(): SETUP + DATA + IN.

Inicjalizacja: usb10_init() wykrywa urządzenie, odczytuje deskryptory, ustawia adres.

Testowanie z urządzeniami HID

Aplikacja karnix_usb10_test:

  • Gamepad: osie analogowe, przyciski w endpoint interrupt 1.
  • Mouse: delty X/Y, przyciski w 4-bajtowych raportach.
  • Keyboard: boot protocol, 8-bajtowe raporty (modyfikatory + klawisze).

Integracja w TetRISC-V: zastąpienie PS/2 wejściem USB.

Co ważne:

  • USB 1.0 full-speed (12 Mbit/s) realizowane FSM bez MACRO-IP.
  • SpinalHDL generuje RTL do syntezy na FPGA.
  • HID boot protocol upraszcza sterownik dla klawiatury/myszy.
  • NRZI + bit stuffing wymagają precyzyjnego timingu (48 MHz clk).
  • Weryfikacja CRC5/16 zapobiega błędom pakietów.

— Editorial Team

Advertisement 728x90

Czytaj dalej