DE10-Nano: HPS USB 2.0 standalone


Introduction


The Cyclone V SoC HPS (CPU system) integrates the Synopsys DWC2 USB 2.0 controller. It has taken several years to understand how the hardware registers and USB protocol work, and eventually have built my own custom USB 2.0 library (currently device mode only). The HPS has two of these USB controllers, but on the DE10-Nano board the USB OTG connector is wired to USB controller 1.

Source files


Some of the features and limits of the library:

  • Device mode only
  • Interrupt driven with callback functions. Note, callbacks run inside the interrupt context so you cannot put lengthy operations or wait loops in them
  • Built-in chunking which enables fixed size data buffer to process large transfers
  • Very high performance when data cache is enabled, reaching 47MBytes/s (376Mbps) using bulk mode and DMA
  • All three transfer modes are supported: Slave (manual FIFO), Standard DMA and Scatter Gather DMA (aka descriptor list DMA)

The following device classes are implemented:

  • Communication Device Class (CDC) as CDC-ACM which is a serial port
  • Human Interface Device Class (HID) as vendor device with custom reports
  • Human Interface Device Class (HID) as an analog gamepad
  • Vendor-specific class as Microsoft OS (MSOS) WinUSB device

The source files is on github: tru_usb. Prebuilt SD card images are in the github tag releases.

Maximum throughput can only be achieved with the Release build because the data cache is needed for performance, especially with DDR-3 SDRAM access. I decided that USB endpoint transfer buffers (except for endpoint 0) and application data buffers should be created at the application layer because the sizes are determined by the available memory of the hardware. There are many things on my to do list but I don't have the time for them, e.g. premptive tasks instead of interrupt callbacks and host controller mode.

The USB library source files are organised in folders:

Folder Description
usb Abstracted USB code.
synopsys Common USB low-level hardware code.
synopsys/port Manufacturer-specific USB low-level hardware code.
usb_example/device Common USB device class example code.
c5soc Manufacturer-specific code. This code complements the common implementation in usb_example/device
c5soc/usb_example/device Manufacturer-specific USB device class instance example code. This code complements the common implementation in usb_example/device

USB device examples


Example settings

There are several USB device example demonstrations. You can select a single demo at time from main.c file by uncommenting the desired header and commenting out the others:

In main you can see we also call the board specific usb initialise function tru_bsp_usb_init().

main.c
// USB example demo includes. Uncomment only one header to enable a demo
#include "c5soc/usb_examples/device/hid_gamepad1_c5soc.h"
//#include "c5soc/usb_examples/device/hid_custom_c5soc.h"
//#include "c5soc/usb_examples/device/hid_custom_ctl_c5soc.h"
//#include "c5soc/usb_examples/device/cdcacm_c5soc.h"
//#include "c5soc/usb_examples/device/cdcacm_rr_c5soc.h"
//#include "c5soc/usb_examples/device/cdcacm_rr_multi_c5soc.h"
//#include "c5soc/usb_examples/device/msos_winusb_c5soc.h"
//#include "c5soc/usb_examples/device/msos_winusb_dual_c5soc.h"

// CMSIS includes
#include "RTE_Components.h"
#include CMSIS_device_header

int main(int argc, char **argv){
  tru_bsp_init();
  tru_bsp_usb_init(TRU_USB_U1_BASE, IRQ_MODE_CPU_0, GIC_IRQ_PRIORITY_LEVEL29_7);
  ...

To enable USB debug messages set these to 1 in the user configuration file.

bsp/tru_user_config.h
// USB settings
#define TRU_UCFG_USB_LOG_INIT 0
#define TRU_UCFG_USB_LOG_EPENA 0
#define TRU_UCFG_USB_LOG_INTR 0
#define TRU_UCFG_USB_LOG_SETUP_BYTES 0
#define TRU_UCFG_USB_LOG_SETUP_TEXT 0
#define TRU_UCFG_USB_LOG_XPROGRESS 0
#define TRU_UCFG_USB_LOG_DIEPTSIZ 0
#define TRU_UCFG_USB_LOG_DOEPTSIZ 0
#define TRU_UCFG_USB_LOG_CALLBACK 0

The messages by default are output to the serial port. Please note that debug messages slows down the USB transfer.

Software for the host computer

Some examples such as CDC-ACM, HID vendor and MSOS WinUSB require host software that you run on the PC in order to initiate data transfers, they are provided in the source_hostapps folder.

The c++ sources are provided with Visual Studio 2022 IDE and codeblocks IDE project files. If you prefer my prebuilt executables you can get them from the github tag releases. The host software are in c++ and Python scripts for Windows and Linux.

Example

I would like to write up a guide for the USB library but currently don't have the time for it. I have written a very basic source guide give an idea of how to work with some of the callbacks.


Document date: Rev 1: 24 Jul 2026