홈으로 돌아가기

SpinalHDL에서의 USB 1.0 컨트롤러: 구현

이 기사는 RISC-V SoC를 위한 SpinalHDL에서 USB 1.0 호스트 컨트롤러 구현을 설명합니다. 물리 계층, 프로토콜, HID 디스크립터, 하드웨어 FSM 및 드라이버를 다룹니다. 키보드, 마우스, 게임패드와의 테스트 예제.

SpinalHDL USB 1.0: 프로토콜부터 FPGA까지
Advertisement 728x90

RISC-V SoC를 위한 SpinalHDL에서의 USB 1.0 호스트 컨트롤러 구현

RISC-V 기반의 합성 가능한 시스템온칩을 개발하려면 현대적인 주변 인터페이스를 통합해야 합니다. USB 1.0 호스트 컨트롤러는 HID 입력 장치인 키보드, 마우스, 게임패드를 연결할 수 있게 해줍니다. SpinalHDL에서 이를 구현하면 PS/2나 아날로그 조이스틱의 소프트웨어적 타협 없이 하드웨어 수준의 프로토콜 처리가 가능합니다.

USB 물리 계층은 D+와 D-의 차동 쌍과 함께 VBUS 및 GND 선을 사용합니다. 하프 듀플렉스 전송 모드는 USB를 UART와 구분 짓는데, 데이터는 한 방향으로 한 번에 비트 단위로 전송되며 호스트와 디바이스의 역할이 엄격히 분리됩니다.

USB 1.0 물리 계층

전기적 특성은 신호 레벨을 정의하며, D+와 D-의 아이들 상태가 속도를 설정합니다. 저속(1.5 Mbps) — D- high, 고속(12 Mbps) — D+ high. NRZI 인코딩: 신호 전환이 '1'을, 없음이 '0'을 인코딩합니다. 비트 스터핑을 통한 동기화: 6개의 동일한 비트 후 반전 비트를 삽입합니다.

Google AdInline article slot

제어 신호:

  • SE0 (Single Ended Zero): D+/D- 모두 low — 버스 리셋용.
  • J/K 상태: 아이들과 속도를 위한 차동 레벨.
  • Chirp: 허브 속도 감지를 위한 K/J 교환.

전송은 SYNC(8비트 '0')로 시작하며, 그 뒤에 PID(Packet ID)가 옵니다.

USB 프로토콜: 패킷과 트랜잭션

PID는 패킷 유형을 정의합니다:

Google AdInline article slot
  • 토큰: SETUP(제어 요청), IN(읽기), OUT(쓰기), SOF(프레임 시작).
  • 데이터: DATA0/1(무결성을 위한 토글 비트).
  • 핸드셰이크: ACK(승인), NAK(거부), STALL(오류).

트랜잭션:

  • 제어 전송: SETUP + DATA(선택) + IN/OUT + ACK.
  • 인터럽트 전송: IN/OUT + DATA + ACK — HID 보고용.
  • 벌크 전송: 대용량 블록, 재시도 포함.
  • 아이소크로너스: 핸드셰이크 없음, 스트림용.

체크섬: 토큰용 CRC5, 데이터용 CRC16. 공식:

// CRC5 for address/kontsa
crc5_next = crc5_reg ^ data_in;
// Polinom: x^5 + x^2 + 1 (0b001101)

디스크립터와 디바이스 초기화

디스크립터는 디바이스를 설명합니다:

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.

초기화:

  • 버스 리셋(SE0 >10 μs).
  • GET_DESCRIPTOR (Device).
  • SET_ADDRESS.
  • GET_DESCRIPTOR (Configuration).
  • SET_CONFIGURATION.

HID의 경우 GET_DESCRIPTOR (Report) 추가. 키보드 보고 예: 수정자 바이트 + 예약 + 6 키코드.

SpinalHDL에서의 하드웨어 구현

컨트롤러는 유한 상태 기계의 계층 구조로 구축됩니다:

  • USBMain: 메인 FSM, 시퀀스 관리.
  • USBSendSE0: 리셋을 위한 SE0 생성.
  • USBSendShortToken: 짧은 토큰(SOF).
  • USBSendLongToken: 전체 토큰(addr+endp).
  • USBSendData: NRZI 인코딩 + 비트 스터핑.
  • USBReceiver: NRZI 디코딩, CRC 검사.

인터페이스:

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은 APB3를 통해 SoC에 통합됩니다. 클럭킹: 고속을 위한 48 MHz.

KarnixSoC와 드라이버 통합

연결: Karna 보드의 USB Type A, FPGA에서 신호 라우팅. SpinalHDL 구성으로 최상위 레벨에 모듈 추가.

RISC-V용 C 드라이버:

  • usb10_bus_reset(): 20 μs 동안 SE0.
  • usb10_in_request(): IN 토큰 + DATA1 + ACK.
  • usb10_setup_request(): SETUP + DATA + IN.

초기화: usb10_init()으로 디바이스 감지, 디스크립터 읽기, 주소 설정.

HID 디바이스 테스트

애플리케이션 karnix_usb10_test:

  • 게임패드: 아날로그 축, 인터럽트 엔드포인트 1의 버튼.
  • 마우스: X/Y 델타, 4바이트 보고의 버튼.
  • 키보드: 부트 프로토콜, 8바이트 보고(수정자 + 키).

TetRISC-V 통합: PS/2를 USB 입력으로 대체.

핵심 사항:

  • FSM으로 MACRO-IP 없이 구현한 USB 1.0 고속(12 Mbps).
  • SpinalHDL이 FPGA 합성을 위한 RTL 생성.
  • HID 부트 프로토콜로 키보드/마우스 드라이버 간소화.
  • NRZI + 비트 스터핑은 정밀한 타이밍(48 MHz 클럭) 필요.
  • CRC5/16 검증으로 패킷 오류 방지.

— Editorial Team

Advertisement 728x90

다음 읽기