Zpět na domů

USB kontrolér na FPGA: vývoj pro HID zařízení na příkladu klávesnice

Článek je věnován vývoji USB 1.1 kontroléru na bázi FPGA pro připojení HID zařízení, jako je klávesnice. Je zde popsána modulární architektura v Verilogu, proces inicializace zařízení, důležitost včasného odesílání paketů SOF a analýza HID deskriptorů.

Vytváříme USB kontrolér na FPGA: od teorie k funkční klávesnici
Advertisement 728x90

Vývoj USB 1.1 řadiče na FPGA: praktický průvodce připojením HID zařízení

Vytvoření vlastního USB řadiče na bázi FPGA vyžaduje hluboké pochopení protokolu a hardwarových specifik. V tomto průvodci se rozebírá implementace řadiče pro standard USB 1.1 s připojením klávesnice, včetně klíčových modulů, inicializace zařízení a zpracování HID deskriptorů.

Hardwarové specifikace USB 1.1

USB 1.1, na rozdíl od USB 2.0, používá dvě digitální linky (D+ a D-), které pracují v protifázi, což umožňuje jejich přímé připojení k digitálním výstupům FPGA. Existují dva podstandardy: Low Speed (1,5 Mbit/s) a Full Speed (12 Mbit/s). Pro určení rychlosti zařízení přivádí logickou jedničku na linku D- pro Low Speed nebo na D+ pro Full Speed při připojení.

Důležité hardwarové nuance:

Google AdInline article slot
  • Datové linky musí být připojeny k zemi přes rezistory na straně hostitele.
  • Je nutná ochrana před napětím 5V na vstupy FPGA, například pomocí Zenerových diod na 3,3V.
  • Pro testování lze použít desky jako STM32 BluePill, které emulují HID zařízení.

Architektura modulu USB řadiče

Řadič se skládá z několika vzájemně propojených modulů, z nichž každý odpovídá za konkrétní úlohu v zásobníku protokolu USB.

  • M_DATA — hlavní modul pro přenos a příjem dat.
  • M_CRC16_USB — vypočítá kontrolní součet CRC16 pro datové pakety.
  • M_GET_PACKET — řídí proces příjmu dat: odešle token IN, přijme paket, zkontroluje CRC a odešle potvrzení (ACK).
  • M_RECEIVE_MODULE — modul pro příjem dat, zahrnující:

* M_GET_DATA — přímo čte data ze sběrnice.

* M_MEMORY_BUF_CRC16 — buffer s výpočtem CRC16 za běhu.

Google AdInline article slot

* M_BUF_RETRANSLATOR — retransluje data z bufferu pouze po úspěšné kontrole CRC.

  • M_SEND_PACKET — řídí proces odesílání dat: token OUT, přenos dat, čekání na ACK.
  • M_TRANSMIT_MODULE — přenáší data, tokeny, pakety začátku rámce (SOF) a služební pakety.
  • M_CRC_5 — vypočítá kontrolní součet CRC5 pro tokeny, SOF a potvrzení.
  • M_SEND_DATA — odesílá datové pakety s CRC16.
  • M_SEND_TOKEN — odesílá tokeny, SOF a potvrzení (vše s CRC5).
  • M_SEND_END_OF_PACKET — vytváří signál konce paketu (EOP).
  • M_DATA_TRANSFER — fyzická vrstva pro přenos bitů na sběrnici.
  • M_SOF_SENDER — periodicky odesílá pakety SOF pro synchronizaci.
  • M_MAIN_AUTOMAT — hlavní konečný automat, který řídí stav řadiče.
  • M_USB_INIT — provádí inicializaci USB zařízení.
  • M_TRANSACTION — zpracovává řídicí transakce (Control Transfers).
  • M_HID_ANALYZER — analyzuje HID deskriptory zařízení pro pochopení formátu dat.
  • MEMORY_BUF (4 instance) — buffery pro data analýzy HID.

Proces inicializace zařízení

Inicializace začíná určením rychlosti zařízení podle stavu linek D+ a D-. Následuje přísná sekvence kroků, implementovaná v hlavním konečném automatu (M_MAIN_AUTOMAT).

always @(posedge clk)
begin
    if (rst)
    begin
        State_main <= S_IDLE;
        SOF_En <= 1'b0;
        FullSpeedConnect <= 1'b0;
        // ... reset dalších signálů
    end
    else
    begin
        case (State_main)
            S_IDLE:
                // Čekání na připojení a určení rychlosti
                if (Dm & !Dp) // Low Speed
                begin
                    FullSpeedConnect <= 1'b0;
                    ResetTime <= 15_000; // 10 ms při 1.5 MHz
                    // ... nastavení časovačů pro Low Speed
                    State_main <= S_POWER_RISE;
                end
                else if(Dp & !Dm) // Full Speed
                begin
                    FullSpeedConnect <= 1'b1;
                    ResetTime <= 120_000; // 10 ms při 12 MHz
                    // ... nastavení časovačů pro Full Speed
                    State_main <= S_POWER_RISE;
                end
            S_POWER_RISE:
                // Čekání 100 ms na stabilizaci napájení zařízení
                if (WaiteCount == PowerRiseTime || SKIP_POWER_RISE)
                begin
                    WaiteCount <= 0;
                    State_main <= S_USB_RESET;
                end
            S_USB_RESET:
                // Reset zařízení (0 na D+ a D- po dobu 10 ms)
                if (WaiteCount == ResetTime || SKIP_POWER_RISE)
                begin
                    WaiteCount <= 0;
                    State_main <= S_INIT_SOF_SENDER;
                end
            S_INIT_SOF_SENDER:
                // Okamžitý start odesílání paketů SOF po resetu
                if (Eof1) State_main <= S_WAITE_SOF;
                else SOF_En <= 1'b1;
            S_WAITE_SOF:
                if (!Eof1) State_main <= S_USB_RESET_RECOWERY;
            S_USB_RESET_RECOWERY:
                // Obnova po resetu (10 ms)
                if (WaiteCount == ResetTime || SKIP_POWER_RISE)
                begin
                    WaiteCount <= 0;
                    State_main <= S_USB_INIT;
                end
            S_USB_INIT:
                // Provedení sekvence řídicích transakcí
                if (InitComplite)
                begin
                    State_main <= S_REQUEST;
                end
                else if (InitFail)
                    State_main <= S_FAIL;
            // ... stavy pro dotazování zařízení (S_REQUEST, S_WAIT atd.)
        endcase
    end
end

Kriticky důležitý moment: odeslání paketů SOF (Start Of Frame) musí začít ihned po fázi resetu (S_USB_RESET), nikoli po období obnovy. SOF slouží k synchronizaci zařízení s hostitelem. Pro Full Speed jde o paket s číslem rámce a CRC5, pro Low Speed je to pouze signál EOP (dva takty s nulou na obou linkách). Zpoždění s odesláním SOF může vést k nefunkčnosti některých zařízení.

Google AdInline article slot

Analýza HID deskriptorů a dotazování zařízení

Po úspěšné inicializaci, která zahrnuje přiřazení adresy zařízení (odlišné od 0), řadič přechází do stavu dotazování (S_REQUEST). Modul M_HID_ANALYZER zkoumá deskriptory zařízení, získané přes řídicí transakce, aby určil formát a velikost datových paketů. Například pro klávesnici je nutné extrahovat informace o počtu reportů, jejich velikosti a identifikátorech.

Typický cyklus dotazování HID zařízení:

  • Odeslání tokenu IN na adresu zařízení a koncovou bodu (Endpoint) 1.
  • Příjem datového paketu.
  • Kontrola CRC16.
  • Odeslání potvrzení ACK v případě úspěchu.
  • Extrakce užitečných dat (např. scan kódů kláves), přeskočením služebních bajtů na začátku paketu.
  • Čekání na stanovený interval (např. 24 ms) před dalším dotazem.

Pokud zařízení odpoví NAK (Not Acknowledged), hostitel později opakuje požadavek. Při absenci odpovědi nebo chybách může řadič přejít do stavu čekání nebo provést opětovnou inicializaci.

Co je důležité

  • Včasné odeslání SOF: Spuštění paketů Start Of Frame ihned po resetu zařízení je kritické pro stabilní provoz, zejména s různorodými HID zařízeními.
  • Ochrana vstupů FPGA: Je nutná schématická ochrana proti zvýšenému napětí na datových linkách, protože standard USB používá úrovně 3,3V/5V.
  • Analýza deskriptorů: Správná práce s HID zařízeními není možná bez parsování deskriptorů pro pochopení struktury dat.
  • Zpracování chyb: Řadič musí správně zpracovávat NAK, STALL a časové limity, zajišťující odolnost spojení.
  • Rozdělení odpovědnosti: Modulární architektura zjednodušuje ladění a umožňuje opakované použití komponent pro další projekty.

— Editorial Team

Advertisement 728x90

Číst dál