(Currently, English README is machine translated and has not been proofread. I will proofread it soon.)
To realize USB devices on FPGA, the usual solution are USB chips (such as CY7C68013), which leads to high circuit cost. This repo is an FPGA-based USB Full-Speed device core, which only require a simple circuit (just like STM32 microcontrollers) instead of additional USB chips.
USB 1.1 device controller. Realize various USB devices on FPGA. such as USB speaker and microphone, USB camera, USB disk, USB keyboard and USB serial port.
Based on this, I further implement USB audio, USB camera, USB disk, USB keyboard and USB-Serial devices on FPGA. They are all standard devices specified by USB, which can be plug and play without installing drivers.
To realize USB devices on FPGA, the usual technical route is to use USB chips (such as Cypress CY7C68013), which leads to high development costs of circuits and software. This library uses FPGA to implement a universal USB 1.1 (Full Speed) device controller, which can use a very simple circuit to implement USB devices like STM32 microcontroller, without relying on additional USB chips. Based on this, I also implemented USB audio, USB camera, USB flash disk, USB keyboard and USB-Serial on the FPGA. They are the standard devices specified by USB, so they can plug and play without installing drivers.
Features:
Features of this library:
- Pure Verilog implementation for universal FPGAs such as Xilinx, Altera, etc.
- The circuit is simple, **only need three FPGA pins, one resistor and one USB connector** (see [Circuit connection](#circuit_en)).
- Pure Verilog implementation for various FPGA models such as Xilinx, Altera, etc.
- The circuitry required is very simple, except for the FPGA, **Only three FPGA pins, one resistor and one USB interface socket are needed** (see [电路连接](#circuit)).
If you're not familiar with USB protocol stack, but want to quickly implement USB devices on FPGA, you can use some USB classes I provide:
If you're not familiar with the USB stack, but want to quickly implement a USB device, you can use some of the USB features I've packaged:
- **USB audio** is a USB Audio Class (UAC) device. It can let FPGA be a speaker and a microphone (they are both in stereo 2-channel, 48ksps). It provides streaming interfaces for FPGA developers to receive speaker data and send microphone data.
- **USB camera** is a USB Video Class (UVC) device. It can let FPGA be a USB camera, which provides a streaming interface for sending video data to PC.
- **USB flash drive** is a USB Mass Storage (MSC) device. It can let FPGA be a USB flash disk.
- **USB keyboard** is a USB Human Interface (HID) device. It can let FPGA be a USB keyboard, which provides a interface for FPGA developers to send "key press" action.
- **USB-Serial** is a USB Communication Device Class (USB-CDC) device. It can let FPGA be a USB serial port device, which provides interfaces for FPGA developers to receive and send data to PC.
- **USB-Serial-2channel**: is a composite device that includes two USB-CDC devices. It can let FPGA a two-channel serial port device, which provides interfaces for FPGA developers to receive and send data to PC.
- **USB audio**: is a composite device that includes a speaker and microphone (2-channel, 48ksps) and provides a streaming interface for receiving speaker audio data and sending microphone audio data.
- **USB camera**: Video can be transmitted to the computer (width and height can be customized), providing a streaming interface for sending video data.
- **USB flash drive**。
- **USB keyboard**: Provide the control interface of "key press".
- **USB-Serial** Realize serial port equipment, and use minicom, putty, HyperTerminal, serial port assistant and other software to transmit data with FPGA on the computer.
- **USB-Serial-2ch**: is a composite device that includes 2 independent USB-Serial.
If you are familiar with the USB stack, you can use this library to develop more USB devices (see [Secondary development of USB-device](#usbcore)). It provides:
If you are familiar with USB protocol stack, you can use the usb device core in this repo to develop more USB devices (see [Development using USB core](#usbcore_en)). The core provides:
- 4 IN endpoints (0x81\~0x84), 4 OUT endpoints (0x01\~0x04).
- The optional debug output interface prints the debug information to the computer through an additional UART, and the communication process of the USB data packet can be seen.
- 4 IN endpoints (0x81\~0x84), 4 OUT endpoints (0x01\~0x04).
- An optional debug interface for printing debug information to the computer via a UART, you can see the USB communication process through it.
## Effect display
## Demonstration of USB devices
| | Windows 设备管理器中看到的设备 |Effect display|
| | What you can see in Windows Device Manager |What you can see in softwares|
| **USB Serial 2channel** | :heavy_check_mark: |:heavy_check_mark:| :heavy_check_mark: |
> :x: macOS recognizes my USB camera device, but it can't read the video, for an unknown reason, to be resolved later.
> :x: macOS recognizes my USB camera device, but it can't read the video. The reason is unknown and to be resolved later.
### Special thanks
- Thanks for [github.com/xiaowuzxc](https://github.com/xiaowuzxc) submitting the code for the USB speaker. I later expanded it to the current USB audio (speaker + microphone).
- Thanks to \ *\* \ *\* \ *8125@qq.com for solving the problem of one channel not being recognized in USB-Serial-2ch.
- Thanks [xiaowuzxc](https://github.com/xiaowuzxc) for submitting the code of a USB speaker device. I later expanded it to current USB audio device (speaker+microphone).
- Thanks *\*\*\*8125@qq.com for solving the problem of Linux cannot recongnize one of the channels of USB-Serial-2channel.
# <spanid="circuit"> I Circuit connection</span>
# <spanid="circuit_en">Circuit connection</span>
USB has `VBUS`, `GND`, `USB_D-`, `USB_D+` these 4 wires. Taking USB Type B connector (commonly known as USB square female connector) as an example, the four wires are defined as shown in the figure below.
USB has 4 wires: `VBUS`, `GND`, `USB_D-`, and `USB_D+` . Taking USB Type B connector as an example, the 4 wires are defined in the figure below.
|![USBTypeB](./figures/usb_typeb.png)|
| :-----------------------------------: |
|**Figure**: USB connector (square female) and cable.|
Please connect the circuit as shown in the figure below. Where `usb_dp_pull`, `usb_dp`, `usb_dn` are the three common IO pins of the FPGA (the level must be 3.3 V). Among
- Connection `USB_D-` of `usb_dn` FPGA. : warning: If it is a flying line connection, ensure that the length of the connecting line is within 10 cm. If it is a PCB connection, it should be connected to the `usb_dp` differential distribution line.
- Connection `USB_D+` of `usb_dp` FPGA. : warning: If it is a flying lead connection, make sure that the length of the connecting line is within 10 cm; if it is a PCB connection, make sure that it is connected to the `usb_dn` differential distribution line.
- The `usb_dp_pull` FPGA is connected through a 1.5kΩ resistor.
- The FPGA `GND` is connected to the USB connector.
- The USB connector `VBUS` is a 5V, 500ma power supply, which can be disconnected or supply power to the FPGA.
Please connect the circuit according to the figure below. Where `usb_dp_pull`, `usb_dp`, `usb_dn` are the three common IO pins of FPGA (must be 3.3 V). Note that:
- If you use flying leads for connection, ensure that the length of flying leads not longer than 10 cm.
- If you use PCB for connection, note that `USB_D-` and `USB_D+` are differential pairs.
- The `usb_dp_pull` should connect to `USB_D+` through a 1.5kΩ resistor.
- Don't forget to connect `GND`
- The `VBUS` pin of USB connector `VBUS` is a 5V power source that comes from USB-host, it can be ignored, or can supply power for FPGA.
```
_________________
| |
| usb_dp_pull |-------|
| usb_dp_pull* |-------|
| | |
| | |-| 1.5k resistor
| | | |
| | |_| ____________ __________
| | | | | |
| usb_dp |-------^---------| USB_D+ | |
| | | | USB cable |
| usb_dn |-----------------| USB_D- |<================>| Host PC
| | | | |
| GND |-----------------| GND | |
| | | | |
----------------- ------------ ----------
FPGA USB 连接座 电脑
图 : FPGA 连接 USB 的方法
| | |_| ____________ __________
| | | | | |
| usb_dp* |-------^-------------| USB_D+ | |
| | | | USB cable |
| usb_dn* |---------------------| USB_D- |<===========================>| Host PC
| | | | |
| GND |---------------------| GND | |
| | | | |
----------------- ------------ ----------
FPGA USB connector (Type-B, mini, micro, or Type-C) Host PC
*: usb_dp_pull, usb_dp, usb_dn are common 3V3 IO pins of FPGA.
Figure : Connect FPGA to USB
```
# II List of Code Documents
# II List of Design code
[RTL](./RTL) The folder contains all the code, which is divided into three folders according to the level:
[RTL](./RTL) The folder contains all the design source code, which is divided into 3 folders according to the level:
| [RTL/fpga_examples](./RTL/fpga_examples) | 应用层 |Realize the specific application function on the basis of USB class. In order to facilitate testing, the application functions implemented here are very simple, such as loopback testing USB-Serial and generating black and white stripes to the USB camera. You can develop complex applications such as capturing data from a CMOS image sensor to a USB camera.|
| [RTL/usb_class](./RTL/usb_class) | USB class |Some USB classes are implemented on the basis of USB device core. For example, USB Communication Device Class (USB-CDC) is used to realize USB-Serial; USB Video Class (UVC) is used to realize camera.|
| [RTL/usbfs_core](./RTL/usbfs_core) | USB device core |A universal USB device core, which implements the processing of USB low-level signals, including from bit-level to transaction-level. Developers familiar with the USB stack can use it to develop more USB devices. See [Secondary development of USB device](#usbcore).|
| [RTL/fpga_examples](./RTL/fpga_examples) | Application |Realize specific applications based on USB class. To facilitate testing, the applications here are very simple. You can develop complex applications such as capturing data from a CMOS sensor and sending to the USB UVC core.|
| [RTL/usb_class](./RTL/usb_class) | USB class |Realize some USB class cores based on the USB device core.|
| [RTL/usbfs_core](./RTL/usbfs_core) | USB device core |A universal USB device core, which implements USB protocol stack from signal-level to transaction-level. Developers that know well about the USB protocol can use it to develop more USB devices. See [Development using USB core](#usbcore_en).|
Specifically, each code file is described as follows:
Specifically, each source code file is listed as follows:
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_audio.v |Connect the speaker of the USB _ audio _ top. V to the microphone in a loop, and the sound from the speaker will be recorded by the microphone.|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_camera.v |Generates a black and white stripe for the USB _ camera _ top. V, which can be seen with the camera software|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_disk.v |The USB flash disk of 24 KB FAT16 file system is implemented with USB _ disk _ top. V.|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_keyboard.v |Nerating a key signal to the USB _ keyboard _ top. V every 2 seconds;|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_serial.v |By looping back the sending and receiving of USB _ serial _ top. V, the transmitted characters are echoed back to the computer|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_serial2.v |Connect the send and receive loops of the USB _ serial2 _ top. V, and the characters sent on the computer will be echoed|
| [RTL/usb_class](./RTL/usb_class) | usb_audio_top.v |Composite device, including 2 USB Audio Class (UAC), implementation|
| [RTL/usb_class](./RTL/usb_class) | usb_camera_top.v |USB Video Class (UVC) **USB camera**|
| [RTL/usb_class](./RTL/usb_class) | usb_disk_top.v |USB Mass Storage Class (USB-MSC) Implementation|
| [RTL/usb_class](./RTL/usb_class) | usb_keyboard_top.v |USB Human Interface Device Class (USB-HID) Implementation|
| [RTL/usb_class](./RTL/usb_class) | usb_serial_top.v |USB Communication Device Class (USB-CDC) Implementation|
| [RTL/usbfs_core](./RTL/usbfs_core) | **usbfs_core_top.v** |Top module of USB device core|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_transaction.v |Implement USB transaction-level, which is called by usbfs _ core _ top. V.|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_packet_rx.v |Implement USB packet-level RX, which is called by the usbfs _ core _ top. V.|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_packet_tx.v |Realize USB packet-level TX, called by usbfs _ core _ top. V.|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_bitlevel.v |Realize USB bit-level and be called by usbfs _ core _ top. V.|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_debug_monitor.v |Collects debug information (does not interfere with USB functionality) and is called by the usbfs _ core _ top. V.|
| [RTL/usbfs_core](./RTL/usbfs_core) | uart_tx.v |Convert the debugging information to a UART signal, which is called by the usbfs _ core _ top. V.|
The following describes how to use each USB class provided by this library one by one. It will be introduced [Secondary development based on USB device core](#usbcore) at the end.
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_audio.v |Simple demo of using usb_audio_top.v. Let FPGA be a USB speaker & microphone with loopback connection, so that the speaker's voice will recorded by the microphone.|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_camera.v |Simple demo of using usb_camera_top.v. Let FPGA be a USB camera that generates a black and white stripe video.|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_disk.v |Simple demo of using usb_disk_top.v. Let FPGA be a USB flash disk with a 24 KB FAT16 file system.|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_keyboard.v |Simple demo of using usb_keyboard_top.v. Let FPGA be a USB keyborad that pressing a key every 2 seconds.|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_serial.v |Simple demo of using usb_serial_top.v. Let FPGA be a USB serial port device.|
| [RTL/fpga_examples](./RTL/fpga_examples) | fpga_top_usb_serial2.v |Simple demo of using usb_serial2_top.v. Let FPGA be a two-channel USB serial port device.|
| [RTL/usb_class](./RTL/usb_class) | usb_audio_top.v |use **usbfs_core_top.v** to implement USB speaker & microphone|
| [RTL/usb_class](./RTL/usb_class) | usb_camera_top.v |use **usbfs_core_top.v** to implement USB Video Class (UVC) camera|
| [RTL/usb_class](./RTL/usb_class) | usb_disk_top.v |use **usbfs_core_top.v** to implement USB Mass Storage Class (MSC) disk|
| [RTL/usb_class](./RTL/usb_class) | usb_keyboard_top.v |use **usbfs_core_top.v** to implement USB Human Interface Device Class (HID) keyboard|
| [RTL/usb_class](./RTL/usb_class) | usb_serial_top.v |use **usbfs_core_top.v** to implement USB Communication Device Class (CDC) serial port|
| [RTL/usb_class](./RTL/usb_class) | usb_serial2_top.v |use **usbfs_core_top.v** to implement a composite device, including 2 USB-CDC serial ports|
| [RTL/usbfs_core](./RTL/usbfs_core) | **usbfs_core_top.v** |Top module of the USB device core|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_transaction.v |USB transaction-level controller, called by usbfs_core_top.v.|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_packet_rx.v |USB packet-level RX controller, called by usbfs_core_top.v.|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_packet_tx.v |USB packet-level TX controller, called by usbfs_core_top.v.|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_bitlevel.v |USB bit-level controller (PHY) , called by usbfs_core_top.v.|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_debug_monitor.v |Collects and send out debug information. only for debug|
| [RTL/usbfs_core](./RTL/usbfs_core) | usbfs_debug_uart_tx.v |Convert the debug information to a UART signal. only for debug|
The following sections describe how to use these USB classes.
# Ⅲ USB audio
The USB audio device in this library implements speaker + microphone. The code file calling relationship is as follows. Please add these files to the FPGA project, compile and burn them to the FPGA.
The USB audio device implements speaker + microphone. The file hierarchy is as follows. Please add these files to the FPGA project, compile and program it to the FPGA.
- RTL/fpga_examples/**fpga_top_usb_audio.v**
- RTL/usb_class/**usb_audio_top.v**
- RTL/usbfs_core/**usbfs_core_top.v**
- Other.sv files in RTL/usbfs_core/ (not listed individually)
- Other.v files in RTL/usbfs_core/
> The USB core of this :warning: library requires a 60 MHz drive clock. Altera's altpll primitive is **fpga_top_usb_audio.v** called to convert the crystal's 50MHz clock to a 60MHz clock. If your FPGA is not a Altera Cyclone IV, remove the altpll part of the code and use the corresponding primitive or IP core to generate the 60 MHz clock. For Xilinx FPGAs, for example, Clock Wizard IP can be used.
> :warning: The USB core of this repo requires a 60 MHz driving clock. Since I use Altera Cyclone IV, an `altpll` primitive module is used in my code to convert inputted 50MHz clock to 60MHz clock. If your FPGA is not a Altera Cyclone IV, you should remove `altpll` module and use the corresponding primitive or IP core to generate 60 MHz clock. For example, for Xilinx FPGAs, you can use Clock Wizard IP.
### Test
After the USB is plugged in, open Windows Device Manager and you should see the speaker and microphone devices:
After the USB is plugged in, open the Windows Device Manager, you would find a device:
![](./figures/ls_audio.png)
Because **fpga_top_usb_audio.v** the speaker and the microphone are connected in a loop, the playback of the speaker is recorded by the microphone. To test, first select the device as the audio output device:
Because **fpga_top_usb_audio.v** loopback connects the speaker and the microphone, the played voice of the speaker will be recorded by the microphone.
For testing, first select the device as the audio output device:
![](./figures/select_audio.png)
Then play a random music. Then use any recording software or video recording software (such as obstudio), select FPGA-USB-Audio as the input microphone, and record an audio or video. In the end you will find that the recorded audio is the same as the music you play.
Then play a music. Meanwhile use any recording software or video recording software (such as obstudio), select FPGA-USB-audio as the input microphone, and record an audio. Finally you will find that the recorded audio is the same as the music you played.
### Application development
You can develop more complex audio applications based on this simple example, for which you need to pay attention to **usb_audio_top.v**the module interface. See the code comments for details, so I won't repeat them here.
You can develop more complex audio applications based on this simple example, for which you need to pay attention to the in/out ports of **usb_audio_top.v** . See the code comments for details.
# IV USB camera
The calling relationship of the code file of the USB camera device in this library is as follows. Please add these files to the FPGA project, compile and burn them to the FPGA.
The file hierarchy is as follows. Please add these files to the FPGA project, compile and program it to the FPGA.
- RTL/fpga_examples/**fpga_top_usb_camera.v**
- RTL/usb_class/**usb_camera_top.v**
- RTL/usbfs_core/**usbfs_core_top.v**
- Other.sv files in RTL/usbfs_core/ (not listed individually)
- Other.v files in RTL/usbfs_core/
> The USB core of this :warning: library requires a 60 MHz drive clock. Altera's altpll primitive is **fpga_top_usb_camera.v** called to convert the crystal's 50MHz clock to a 60MHz clock. If your FPGA is not a Altera Cyclone IV, remove the altpll part of the code and use the corresponding primitive or IP core to generate the 60 MHz clock. For Xilinx FPGAs, for example, Clock Wizard IP can be used.
> :warning: The USB core of this repo requires a 60 MHz driving clock. Since I use Altera Cyclone IV, an `altpll` primitive module is used in my code to convert inputted 50MHz clock to 60MHz clock. If your FPGA is not a Altera Cyclone IV, you should remove `altpll` module and use the corresponding primitive or IP core to generate 60 MHz clock. For example, for Xilinx FPGAs, you can use Clock Wizard IP.
### Test
After the USB is plugged in, open the Windows Device Manager and you should see the camera device:
After the USB is plugged in, open the Windows Device Manager, you would find a device:
![](./figures/ls_camera.png)
Open the camera software that comes with Windows 10, and you should see a scrolling black and white stripe:
Open the "camera" software of Windows, you would see a scrolling black and white stripe:
![](./figures/test_camera.png)
### Application development
You can develop more complex camera applications based on this simple example, for which you need to pay attention to **usb_camera_top.v**the module interface (see code comments for details).
You can develop more camera applications based on this simple example, for which you need to pay attention to the in/out ports of **usb_camera_top.v**
#### Parameters of USB _ camera _ top. V.
#### Parameters of usb_camera_top.v
The key parameters are described here:
The key parameters are listed here:
```verilog
@ -219,33 +219,39 @@ parameter [13:0] FRAME_W = 14'd320, // video-frame width in pixels, must b
parameter [13:0] FRAME_H = 14'd240, // video-frame height in pixels, must be a even number
```
You can set the width and height of the video frame with `FRAME_W` and `FRAME_H`. `FRAME_TYPE` Desirable `"MONO"` or `"YUY2"`.
You can set the width and height of the video frame by modifying parameter `FRAME_W` and `FRAME_H`.
As for paramter `FRAME_TYPE` , it can be `"MONO"` or `"YUY2"` .
##### FRAME_TYPE="MONO"
`FRAME_TYPE="MONO"` Is a grayscale mode, and each pixel corresponds to a lightness value of 1 byte. For example, for a 4x3 video frame, the module reads the following 12 bytes successively from the outside world:
`FRAME_TYPE="MONO"` Is grayscale mode. Each pixel is a 1-byte luminance value (0-255).
For example, for a 4x3 video frame, each frame has 12 pixels. While working, the user should send following 12 bytes successively to the module:
```
Y00 Y01 Y02 Y03 Y10 Y11 Y12 Y13 Y20 Y21 Y22 Y23
```
Where Y00 is the lightness value of row0, column0; Y01 is the lightness value of row0, column1;..
Where Y00 is the luminance value of row0 column0; Y01 is the luminance value of row0, column1; ......
##### FRAME_TYPE="YUY2"
`FRAME_TYPE="YUY2"` A color mode, also known as YUYV, in which each pixel has an independent 1-byte lightness value (Y), while two adjacent pixels share a 1-byte blue chrominance (U) and a 1-byte red chrominance (Y). For example, for a 4x2 video frame, the module reads the following 16 bytes successively from the outside world:
`FRAME_TYPE="YUY2"` is color mode, also known as YUYV, in which each pixel has an independent 1-byte luminance value (Y), while two adjacent pixels share a 1-byte blue chroma value (U) and a 1-byte red chroma value (V).
For example, for a 4x2 video frame, the user should send following 12 bytes successively to the module:
Where (y00, u00, v00) is the pixel at the 0th row and the 0th column; (y01, u00, v00) is the pixel at the 0th row and the 1st column; (y02, u02, v02) are the pixels at the 2nd row and the 2nd column; and (y03, u02, v02) are the pixels at the 3rd row and 3rd column.
Where (Y00, U00, V00) is the pixel of row0 column0; (Y01, U00, V00) is the pixel of row0 column1; (Y02, U02, V02) is the pixel of row0 column2; (Y03, U02, V02) is the pixel of row0 column3. (Y12, U10, V10) is the pixel of row1 column0; ...
#### USB _ camera _ top. V signal
#### Ports of usb_camera_top.v
The signal**usb_camera_top.v** used to read the pixel from the outside is:
The ports of**usb_camera_top.v** used to read the pixel from the outside is:
input wire [ 7:0] vf_byte, // // a byte of pixel data
```
Video frames **usb_camera_top.v** are continuously read and sent to the Host-PC via the above signals. At the beginning of each video frame, `vf_sof` a cycle of high levels occurs. The next highest level will then `vf_req` occur **N** intermittently, where **N** is the number of bytes of the video frame, for `FRAME_TYPE="MONO"`, **N** = frame width X frame height; For `FRAME_TYPE="YUY2"`, **N** = 2 × frame width × frame height. Each time `vf_req=1`, the outside world should provide a byte (pixel data) onto the `vf_byte` signal, which should be asserted on `vf_req=1` the fourth clock cycle `vf_byte` at the latest and remain asserted until the next time `vf_req=1`.
**usb_camera_top.v** will continuously input and sent frames to the Host-PC.
At the beginning of each video frame, `vf_sof=1` pulses for one cycle. Then `vf_req=1` pulses for **N** cycles, where **N** is the number of bytes of the video frame, for `FRAME_TYPE="MONO"`, **N** = frame width × frame height; For `FRAME_TYPE="YUY2"`, **N** = 2 × frame width × frame height. Each time when `vf_req=1`, the outside world should provide a byte onto `vf_byte` signal, which should be valid at most 4 cycles after `vf_req=1` and keep until the next time when `vf_req=1`.
### Frame rate and performance
This module sends the video to the Host-PC with a fixed bandwidth. The larger the video frame size, the smaller the frame rate. The theoretical bandwidth of USB Full Speed is 12Mbps. In fact, the module sends 800 bytes of pixel data (400 pixels) every 1ms. Therefore, the approximate calculation formula of the frame rate is:
This module sends the video to the Host-PC with a fixed speed. The larger the video frame size, the smaller the frame rate. The theoretical bandwidth of USB Full Speed is 12Mbps. In fact, the module sends 800 bytes of pixel data (400 pixels) every 1ms. Therefore, the approximate calculation formula of the frame rate is:
Frame Rate = 400000/ (Frame Width * Frame Height)
Frame Rate = 400000/ (Frame Width × Frame Height)
# Ⅴ U disk
The calling relationship of the code file of the U disk device in this library is as follows. Please add these files to the FPGA project, compile and burn them to the FPGA.
The file hierarchy is as follows. Please add these files to the FPGA project, compile and program it to the FPGA.
- RTL/fpga_examples/**fpga_top_usb_disk.v**
- RTL/usb_class/**usb_disk_top.v**
- RTL/usbfs_core/**usbfs_core_top.v**
- Other.sv files in RTL/usbfs_core/ (not listed individually)
- Other.v files in RTL/usbfs_core/
> The USB core of this :warning: library requires a 60 MHz drive clock. Altera's altpll primitive is **fpga_top_usb_disk.v** called to convert the crystal's 50MHz clock to a 60MHz clock. If your FPGA is not a Altera Cyclone IV, remove the altpll part of the code and use the corresponding primitive or IP core to generate the 60 MHz clock. For Xilinx FPGAs, for example, Clock Wizard IP can be used.
> :warning: The USB core of this repo requires a 60 MHz driving clock. Since I use Altera Cyclone IV, an `altpll` primitive module is used in my code to convert inputted 50MHz clock to 60MHz clock. If your FPGA is not a Altera Cyclone IV, you should remove `altpll` module and use the corresponding primitive or IP core to generate 60 MHz clock. For example, for Xilinx FPGAs, you can use Clock Wizard IP.
### Test
After the USB is plugged in, open Windows Device Manager and you should see a hard drive:
After the USB is plugged in, open the Windows Device Manager, you would find a device:
![](./figures/ls_disk.png)
Windows File Explorer should see the hard drive with a "file" example. Txt ". You can add, modify and delete files in this hard disk. Since it is implemented with the FPGA's on-chip memory (BRAM), all your modifications will disappear when the FPGA is powered off or reburned. The free space of this hard disk is only 3.5 KB, which is basically useless and only for testing.
And you would see a new disk in Windows File Explorer, with one file "example,txt" in it.
![](./figures/test_disk.png)
Since it is implemented with the FPGA's on-chip memory (BRAM), all your modifications will disappear when the FPGA is powered off or re-programed. The free space of this hard disk is only 3.5 KB, which is basically useless and only for testing.
### Application development
You can develop larger or more complex USB-disks based on this simple example, for which you need to pay attention to **usb_disk_top.v**the module interface (see code comments for details).
You can develop larger or more complex USB-disks based on this simple example, for which you need to pay attention to the in/out ports **usb_disk_top.v** (see code comments for details).
These signals are used for reading and writing **Storage space of hard disk**. `mem_addr` Is a 41-bit byte address, so the addressing space is 2 ^ 41 = 2 TB. However, the actual hard disk storage space must be less than 2 TB, so only the addresses from `mem_addr=0` to `mem_addr=硬盘容量` are valid. At each clock cycle:
These signals are used for reading and writing the **Storage space of hard disk**. `mem_addr` Is a 41-bit byte address, so the accessable addressing space is 2^41=2TB.
At each clock cycle:
- If `mem_wen=1`, the Host wants to write one byte of data to the device, the write address is `mem_addr`, and the write data is `mem_wdata`;
- If `mem_wen=0` the device needs to read a byte of data, the read address is `mem_addr`, and the read data should be sent to the `mem_rdata` next cycle.
- If `mem_wen=0` the device needs to read a byte of data, the read address is `mem_addr`, and the read data should appear on `mem_rdata` on the next cycle.
This interface is very easy to connect to the BRAM of FPGA, so we use BRAM to realize the storage space of hard disk.
This interface is very easy to connect to the BRAM of FPGA.
In order for disk to be recognized as a formatted hard disk, you can provide an initial data to the BRAM, which contains a file system. The BRAM **fpga_top_usb_disk.v** in implements a FAT16 file system with a total size of 24KB.
In order for disk to be recognized as a formatted hard disk, you can provide an initial data to the BRAM, which contains a file system.
> :warning: A file system is a data structure used to organize files and is stored on the hard disk as the files themselves. The production method is more complicated and will not be repeated here. If you need to make a customized U disk device, you can contact me through issue.
> :warning: A file system is a data structure used to organize files and is stored on the hard disk. The production method is quite complicated and will not be describe here. If you need to make a customized U disk device, you can contact me through issue or email.
# VI USB keyboard
The calling relationship of the code file of the USB keyboard device in this library is as follows. Please add these files to the FPGA project, compile and burn them to the FPGA.
The file hierarchy is as follows. Please add these files to the FPGA project, compile and program it to the FPGA.
- RTL/fpga_examples/**fpga_top_usb_keyboard.v**
- RTL/usb_class/**usb_keyboard_top.v**
- RTL/usbfs_core/**usbfs_core_top.v**
- Other.sv files in RTL/usbfs_core/ (not listed individually)
- Other.v files in RTL/usbfs_core/
> The USB core of this :warning: library requires a 60 MHz drive clock. Altera's altpll primitive is **fpga_top_usb_keyboard.v** called to convert the crystal's 50MHz clock to a 60MHz clock. If your FPGA is not a Altera Cyclone IV, remove the altpll part of the code and use the corresponding primitive or IP core to generate the 60 MHz clock. For Xilinx FPGAs, for example, Clock Wizard IP can be used.
> :warning: The USB core of this repo requires a 60 MHz driving clock. Since I use Altera Cyclone IV, an `altpll` primitive module is used in my code to convert inputted 50MHz clock to 60MHz clock. If your FPGA is not a Altera Cyclone IV, you should remove `altpll` module and use the corresponding primitive or IP core to generate 60 MHz clock. For example, for Xilinx FPGAs, you can use Clock Wizard IP.
### Test
After the USB is plugged in, open Windows Device Manager and you should see a keyboard device:
After the USB is plugged in, open the Windows Device Manager, you would find a device:
![](./figures/ls_keyboard.png)
The keyboard presses the English letter keys every 2 seconds. Open a notepad to see the effect.
The keyboard will press a English letter key every 2 seconds.
### Application development
You can develop more complex keyboard applications based on this simple example, for which you need to pay attention to **usb_keyboard_top.v**the module interface (see code comments for details).
You can develop more complex keyboard applications based on this simple example, for which you need to pay attention to the in/out ports of **usb_keyboard_top.v** (see code comments for details).
Here, the signal used to transmit the key signal is described:
Note the following signals:
```verilog
@ -346,36 +358,36 @@ input wire [15:0] key_value, // Indicates which key to press, NOT ASCII cod
input wire key_request, // when key_request=1 pulses, a key is pressed.
```
`key_request`Usually needs to maintain 0, when you need to press a key, need to let `key_request=1` a cycle, at the same time on `key_value` the input code corresponding to the key. Refer to https://www.usb.org/sites/default/files/hut1_21_0.pdf Section 10 for the definition of key code. For example, keys' a '- `key_value=16'h0004~16'h001D` ' Z 'correspond, and keys' 1'- `key_value=16'h001E~16'h0027` '0' correspond.
`key_request`usually needs to maintain 0, when you need to press a key, let `key_request=1` for a cycle, meanwhile set a key code on `key_value`. Refer to https://www.usb.org/sites/default/files/hut1_21_0.pdf Section 10 for the definition of key code. For example, keys 'A'-'Z' corresponds to `key_value=16'h0004~16'h001D`
# Ⅶ USB-Serial
The calling relationship of the code file of the USB-Serial device in this library is as follows. Please add these files to the FPGA project, compile and burn them to the FPGA.
The file hierarchy is as follows. Please add these files to the FPGA project, compile and program it to the FPGA.
- RTL/fpga_examples/**fpga_top_usb_serial.v**
- RTL/usb_class/**usb_serial_top.v**
- RTL/usbfs_core/**usbfs_core_top.v**
- Other.sv files in RTL/usbfs_core/ (not listed individually)
- Other.v files in RTL/usbfs_core/
> The USB core of this :warning: library requires a 60 MHz drive clock. Altera's altpll primitive is **fpga_top_usb_serial.v** called to convert the crystal's 50MHz clock to a 60MHz clock. If your FPGA is not a Altera Cyclone IV, remove the altpll part of the code and use the corresponding primitive or IP core to generate the 60 MHz clock. For Xilinx FPGAs, for example, Clock Wizard IP can be used.
> :warning: The USB core of this repo requires a 60 MHz driving clock. Since I use Altera Cyclone IV, an `altpll` primitive module is used in my code to convert inputted 50MHz clock to 60MHz clock. If your FPGA is not a Altera Cyclone IV, you should remove `altpll` module and use the corresponding primitive or IP core to generate 60 MHz clock. For example, for Xilinx FPGAs, you can use Clock Wizard IP.
### Test
After the USB is plugged in, open the Windows Device Manager and you should see a USB-serial device:
After the USB is plugged in, open the Windows Device Manager, you would find a device:
![](./figures/ls_serial.png)
In this example, the **usb_serial_top.v** received data is converted from lowercase letters to uppercase letters according to ASCII code, and then looped back to the sending interface. You can send data to Serial Port with minicom, putty, HyperTerminal, and Serial Assistant software on Host-PC, and the sent data will be echoed (with lowercase letters converted to uppercase letters). Take the serial port assistant as an example, as shown in the figure below.
In this example, the **usb_serial_top.v** received data is converted from lowercase letters to uppercase letters (ASCII code), and then looped back to the sending interface. You can send data to Serial Port using minicom, putty, HyperTerminal, or Serial Assistant software on Host-PC, and the sent data will be echoed (with lowercase letters converted to uppercase letters). As shown in figure below.
![](./figures/test_serial.png)
> :warning: Because the Serial-Port is not a true UART, it is also called **Virtual serial port**. Setting the baud rate, data bit, check bit, and stop bit of the virtual serial port will not have any effect.
> :warning: Because this USB-CDC-based Serial-Port is not a true UART, it is also called **Virtual serial port**. So there will be no any effects when you change baud rate, data bit, check bit, and stop bits.
### Application development
You can develop more complex Serial-Port communication applications based on this simple example, for which you need to pay attention to **usb_serial_top.v**the module interface (see the code comments for details).
You can develop more complex Serial-Port communication applications based on this simple example, for which you need to pay attention to the in/out ports of **usb_serial_top.v** (see the code comments for details).
The key signals are described here, including:
@ -391,85 +403,85 @@ input wire send_valid, // when device want to send a data byte, set s
output wire send_ready, // send_ready handshakes with send_valid. send_ready=1 indicates send-buffer is not full and will accept the byte on send_data. send_ready=0 indicates send-buffer is full and cannot accept a new byte.
```
The signal of host-to-device is relatively simple. Every time a data byte is received, `recv_valid`the high level of a cycle appears, and the byte appears at the same time `recv_data`.
The signal of host-to-device is relatively simple. Every time a data byte is received, `recv_valid`will become high of one cycle, and the byte will appear on `recv_data` at the same time.
The device-to-host signal is in the opposite direction, and there is an `send_ready`extra signal, `send_ready=0` indicating that the send buffer inside the module is full and cannot send new data for the time being. `send_ready` And `send_valid` form a handshake signal, when the user needs to send a byte, should let `send_valid=1`, at the same time let the byte appear again `send_data`. At`send_valid=1 && send_ready=1`that point, the byte is successfully sent to the send buffer, and the user can proceed to send the next byte. The handshake mechanism is similar to AXI-stream.
The device-to-host signal is in the opposite direction, and there is an `send_ready` signal, `send_ready=0` indicating that the send buffer inside the module is full and cannot send new data temporarily. `send_ready` And `send_valid` form a handshake signal, when the user needs to send a byte, he should let `send_valid=1`, at the same time let the byte appear on `send_data`. When`send_valid=1 && send_ready=1` , the byte is successfully sent to the send buffer, and the user can proceed to send the next byte. This handshake mechanism is similar to AXI-stream.
There is a send buffer of 1024 bytes **usb_serial_top.v**in. If the throughput rate of the data to be sent is not large, the send buffer will never be full, and the signal can also be ignored`send_ready`. However, when the data throughput rate is large, which may cause the sending buffer to be full, some data may be lost if the situation is ignored `send_ready=0`.
There is a send buffer of 1024 bytes in **usb_serial_top.v** . If the send throughput is not large, the send buffer will never be full, in this case you can ignore`send_ready`. However, when the send throughput is large, which may cause the sending buffer to be full, then `send_ready` shouldn't be ignored.
# Ⅷ Dual-channel USB-Serial
The calling relationship of the code file of the dual-channel USB-Serial device in this library is as follows. Please add these files to the FPGA project, compile and burn them to the FPGA.
The file hierarchy is as follows. Please add these files to the FPGA project, compile and program it to the FPGA.
- RTL/fpga_examples/**fpga_top_usb_serial2.v**
- RTL/usb_class/**usb_serial2_top.v**
- RTL/usbfs_core/**usbfs_core_top.v**
- Other.sv files in RTL/usbfs_core/ (not listed individually)
- Other.v files in RTL/usbfs_core/
> The USB core of this :warning: library requires a 60 MHz drive clock. Altera's altpll primitive is **fpga_top_usb_serial2.v** called to convert the crystal's 50MHz clock to a 60MHz clock. If your FPGA is not a Altera Cyclone IV, remove the altpll part of the code and use the corresponding primitive or IP core to generate the 60 MHz clock. For Xilinx FPGAs, for example, Clock Wizard IP can be used.
> :warning: The USB core of this repo requires a 60 MHz driving clock. Since I use Altera Cyclone IV, an `altpll` primitive module is used in my code to convert inputted 50MHz clock to 60MHz clock. If your FPGA is not a Altera Cyclone IV, you should remove `altpll` module and use the corresponding primitive or IP core to generate 60 MHz clock. For example, for Xilinx FPGAs, you can use Clock Wizard IP.
### Test
After the USB is plugged in, open the Windows Device Manager and you should see 2 USB-serial devices:
After the USB is plugged in, open the Windows Device Manager, you would find two Serial devices:
![](./figures/ls_serial2.png)
The test method is the same as that of the single-channel USB-Serial, which will not be described here.
It's behavior is as same as the single-channel USB-Serial, which will not be described here.
### Application development
You can develop a more complex Serial-Port communication application based on this simple example. For this, you need to pay attention to **usb_serial2_top.v** the module interface (see the code comment for details). Its usage is the same as that of the single-channel USB-Serial, except that the sending and receiving interfaces have become dual-channel, which will not be repeated here.
You can develop a more complex Serial-Port communication application based on this simple example. For this, you need to pay attention to the in/out ports of **usb_serial2_top.v** (see the code comment for details). Its usage is as same as the single-channel USB-Serial, except that the sending and receiving interfaces become dual-channel, which will not be repeated here.
# <spanid="usbcore"> Ⅸ Secondary development based on USB device core</span>
You can use to **usbfs_core_top.v** develop other USB devices, which provide:
# <spanid="usbcore_en"> Ⅸ Development using USB device core</span>
- In addition to the control endpoint (0 x00), four IN endpoints (0x81 \ ~ 0x84) and four OUT endpoints (0x01 \ ~ 0x04) are provided.
- The optional debug output interface prints the debug information to the computer through an additional UART, and the communication process of the USB data packet can be seen.
You can use my USB device core (**usbfs_core_top.v**) to develop more USB devices. The core provides:
The parameters and input and output signals of the are described below **usbfs_core_top.v**.
| `EP00_MAXPKTSIZE` | `logic[7:0]`| control endpoint 最大包大小 |
| `EP81_MAXPKTSIZE` | `logic[9:0]`| IN endpoint 0x81 最大包大小 |
| `EP82_MAXPKTSIZE` | `logic[9:0]`| IN endpoint 0x82 最大包大小 |
| `EP83_MAXPKTSIZE` | `logic[9:0]`| IN endpoint 0x83 最大包大小 |
| `EP84_MAXPKTSIZE` | `logic[9:0]`| IN endpoint 0x84 最大包大小 |
| `EP81_ISOCHRONOUS` |0 or 1| IN endpoint 0x81 是否是 isochronous 传输模式 |
| `EP82_ISOCHRONOUS` |0 or 1| IN endpoint 0x82 是否是 isochronous 传输模式 |
| `EP83_ISOCHRONOUS` |0 or 1| IN endpoint 0x83 是否是 isochronous 传输模式 |
| `EP84_ISOCHRONOUS` |0 or 1| IN endpoint 0x84 是否是 isochronous 传输模式 |
| `EP01_ISOCHRONOUS` |0 or 1| IN endpoint 0x01 是否是 isochronous 传输模式 |
| `EP02_ISOCHRONOUS` |0 or 1| IN endpoint 0x02 是否是 isochronous 传输模式 |
| `EP03_ISOCHRONOUS` |0 or 1| IN endpoint 0x03 是否是 isochronous 传输模式 |
| `EP04_ISOCHRONOUS` |0 or 1| IN endpoint 0x04 是否是 isochronous 传输模式 |
| `DEBUG` |TRUE or FALSE| 是否启用调试接口 |
> :warning: According to the USB 1.1 specification, when an endpoint is in isochronous transfer mode, the maximum packet size can be any value from 8 \ to 1023. When the endpoint is in interrupt or bulk transfer mode, the maximum packet size can only be 8, 16, 32, or 64.
| `EP00_MAXPKTSIZE` | `[7:0]`| max packet size of control endpoint |
| `EP81_MAXPKTSIZE` | `[9:0]`| max packet size of IN endpoint 0x81 |
| `EP82_MAXPKTSIZE` | `[9:0]`| max packet size of IN endpoint 0x82 |
| `EP83_MAXPKTSIZE` | `[9:0]`| max packet size of IN endpoint 0x83 |
| `EP84_MAXPKTSIZE` | `[9:0]`| max packet size of IN endpoint 0x84 |
| `EP81_ISOCHRONOUS` |0 or 1| Is IN endpoint 0x81 isochronous? |
| `EP82_ISOCHRONOUS` |0 or 1| Is IN endpoint 0x82 isochronous? |
| `EP83_ISOCHRONOUS` |0 or 1| Is IN endpoint 0x83 isochronous? |
| `EP84_ISOCHRONOUS` |0 or 1| Is IN endpoint 0x84 isochronous? |
| `EP01_ISOCHRONOUS` |0 or 1| Is OUT endpoint 0x01 isochronous? |
| `EP02_ISOCHRONOUS` |0 or 1| Is OUT endpoint 0x02 isochronous? |
| `EP03_ISOCHRONOUS` |0 or 1| Is OUT endpoint 0x03 isochronous? |
| `EP04_ISOCHRONOUS` |0 or 1| Is OUT endpoint 0x04 isochronous? |
| `DEBUG` |TRUE or FALSE| Enable Debug interface ? |
> :warning: According to USB 1.1 specification, when an endpoint is in isochronous transfer mode, the maximum packet size can be any value from 8 \ to 1023. When the endpoint is in interrupt or bulk transfer mode, the maximum packet size can only be 8, 16, 32, or 64.
### Ports of usbfs_core_top.v
#### Clock and Reset
The `clk` signal needs to be clocked at 60 MHz:
The `clk` signal needs to be 60 MHz:
```verilog
@ -477,7 +489,7 @@ The `clk` signal needs to be clocked at 60 MHz:
input wire clk, // 60MHz is required
```
The reset signal `rstn` should be set to high level during normal operation. If it is necessary to stop the operation, it can be `rstn` set to low level. At this time, if the USB is plugged into the Host-PC, the Host-PC will detect that the USB is unplugged.
The reset signal `rstn` should be set to high level during normal operation. If it is necessary to stop the operation, set `rstn` to low. At this time, if the USB is plugged into the Host-PC, the Host-PC will detect that the USB is unplugged.
```verilog
@ -487,7 +499,7 @@ input wire rstn, // active-low reset, reset when rstn=0 (USB will unpl
#### USB Signal
The following 3 signals need to be drawn to the pins of the FPGA and connected to the USB interface as per [电路连接方法](#circuit).
The following 3 signals need to be connect according to [Circuit connection](#circuit_en).
```verilog
@ -498,7 +510,9 @@ inout usb_dp, // USB D+
inout usb_dn, // USB D-
```
The `usb_rstn` signal indicates whether the USB is connected, high for connected and low for not connected. There are two possible reasons for no connection: either the USB cable is pulled out from the Host, or the FPGA side is actively reset ( `rstn=0`).
#### Signal for indicating whether the USB is plugged.
The `usb_rstn` signal indicates whether the USB is connected, high for connected and low for disconnected. There are two possible reasons for disconnection: either the USB cable is not plugged in the Host, or the FPGA side is in resetting state ( `rstn=0`).
The start of USB-transfer and USB-frame is indicated when the following two signals `sot` and `sof` are high for one cycle, respectively. USB-transfer refers to the whole process of USB transfer, including control transfer, interrupt transfer, bulk transfer and isochronous transfer. The USB-frame starts from the SOF token sent by the USB-host every 1ms, which can be used to guide the isochronous transfer.
When `sot` and `sof` are high for one cycle, it indicates that a USB-transfer or a USB-frame is detected, respectively.
USB-transfer refers to the whole process of USB transfer, including control transfer, interrupt transfer, bulk transfer and isochronous transfer.
USB-frame means a SOF token is sent from USB-host to USB-device every 1ms, which can be used to guide the isochronous transfer.
```verilog
@ -519,7 +537,7 @@ output reg sof, // detect a start of USB-frame
#### Response signal of control transfer
The following three signals `ep00_setup_cmd``ep00_resp_idx``ep00_resp` provide the interface for responding to a control transfer.
The following three signals `ep00_setup_cmd``ep00_resp_idx``ep00_resp` provide the interface for control transfer.
According to the USB specification, control transfer is performed only on the control endpoint (0x00), and the Host will first send an 8-byte SETUP command. The device may respond with data to the Host. Based on the fields in `bmRequestType[6:5]` the SETUP command, control transfer can be divided into three categories:
According to the USB specification, control transfer is performed only on control endpoint (0x00), and the Host will first send an 8-byte SETUP command. The device may respond data packets to the Host. Based on the fields of `bmRequestType[6:5]` of the SETUP command, control transfer can be divided into three categories:
- Standard control transfer ( `bmRequestType[6:5]=0`)
- Class-specific control transfer ( `bmRequestType[6:5]=1`)
- Vendor-specific control transfer ( `bmRequestType[6:5]=2`)
Standard control transfer is used to respond to descriptor and other data **usbfs_core_top.v**, which is processed internally and does not need to be concerned by the developer. The developer only needs to specify the descriptor with parameter. Class-specific control transfer and vendor-specific control transfer are related to the implementation of specific devices, and developers can respond to them through these three signals. For example, the UVC device provided by this library uses it to respond to the UVC Video Probe and Commit Controls, while the HID device uses it to respond to the HID descriptor. In addition, some simple devices do not need Class-specific control transfer and Vendor-specific control transfer at all, so developers can ignore these three signals.
Standard control transfer is used to respond to descriptor and other data, which is processed internally in **usbfs_core_top.v** and does not need to be concerned by the developer. The developer only needs to specify the descriptor with parameter.
Class-specific control transfer and vendor-specific control transfer are related to the implementation of specific devices. Developers can respond to them through these three signals. For example, the UVC device provided by this repo uses it to respond to the UVC Video Probe and Commit Controls. In addition, some simple devices do not need Class-specific control transfer and Vendor-specific control transfer at all, so developers can ignore these three signals.
When a control transfer is performed, `ep00_setup_cmd` the 8-byte SETUP command appears on the signal first. The `ep00_resp_idx` signal is then incremented from 0, representing the byte in which the response is currently required. The developer needs to type the th `ep00_resp_idx` byte of the response data on the `ep00_resp` signal at any time.
When a control transfer is performed, the 8-byte SETUP command will appear on `ep00_setup_cmd` first. Then `ep00_resp_idx` signal will increase from 0, representing the byte address that the response is currently required. The developer needs to set `ep00_resp` to the corresponding byte at next cycle.
Taking the UVC device as an example, the following code detects whether the SETUP command requires the device to respond to the UVC Video Probe and Commit Controls. It responds to `UVC_PROBE_COMMIT` the first `ep00_resp_idx` byte in the array on the `ep00_resp` signal, otherwise it responds to `0x00` :
Taking the UVC device as an example, the following code detects whether the SETUP command requires the device to respond to the UVC Video Probe and Commit Controls.
```verilog
// 举例:在 UVC 设备中,当 host 请求 UVC Video Probe and Commit Controls 时,应该使用以下写法进行响应:
// In the UVC device, the host requests UVC Video Probe and Commit Controls, the following code is to respond this request:
For the content of the command and response data of control transfer, please refer to the specific protocol specification.
For the content of the command and response data of control transfer, please refer to the specific USB class's specification.
#### IN endpoint (0x81\~0x84) data input signal
#### IN endpoint (0x81\~0x84) signals
The following 4 groups of signals correspond to 4 IN endpoints and are used to send device-to-host IN packets.
The following 4 groups of signals correspond to 4 IN endpoints and are used to send packets from device to host.
For example, if the FPGA needs to send an IN packet on the IN endpoint 0x81, the following is required:
- First, let `ep81_valid=1` and hold, while holding the 0th byte of the packet on `ep81_data`.
- `ep81_ready`And `ep81_valid` form a handshake signal. Each `ep81_ready` occurrence of a periodic high indicates that a byte has been successfully transmitted.
- In `ep81_ready=1` the next cycle, if the IN packet transmission is finished, the command `ep81_valid=0` is required. If the IN packet still has bytes to send, it will `ep81_data` be kept `ep81_valid=1` and updated to new bytes to be sent.
- First, let `ep81_valid=1` and hold, meanwhile holding the 0th byte of the packet on `ep81_data`.
- `ep81_ready`and `ep81_valid` form a pair of handshake signals. Each time when `ep81_ready=ep81_valid=1` , a byte is successfully transmitted.
- At the next cycle when `ep81_ready=1` , if the entire IN packet transmission is finished, let `ep81_valid=0` . If the IN packet still has bytes to send, keep `ep81_valid=1` and let `ep81_data` to be the next byte to be sent.
```verilog
@ -585,11 +605,11 @@ input wire ep84_valid, // when device want to send a data byte, asser
output wire ep84_ready, // handshakes with valid. ready=1 indicates the data byte can be accept.
```
#### OUT endpoint (0x01\~0x04) data output signal
#### OUT endpoint (0x01\~0x04) signals
The following four groups of signals correspond to four OUT endpoints and are used to receive the OUT packet of the host-to-device.
The following four groups of signals correspond to four OUT endpoints and are used to receive the OUT packet from host to device.
For example, when `ep01_valid` a cycle of high occurs, a byte in the OUT packet is received, and the byte appears `ep01_data` on the. In addition, the boundary of the packet can be detected by the `sot` signal mentioned before.
For example, when `ep01_valid=1` for one cycle, a byte of OUT packet is received, the byte appears on `ep01_data` . In addition, the boundary of different packets can be detected by the `sot` signal mentioned before.
```verilog
@ -614,7 +634,9 @@ output wire ep04_valid, // when out_valid=1 pulses, a data byte is rec
#### Debug output interface
The following signals are used to print debug information to the outside world. The debug information is a stream of ASCII code bytes and is human readable. At `debug_en=1` that time, `debug_data` a byte appears on the.
To enable Debug interface, set the parameter `DEBUG=1` . Otherwise the debug interface will not output any data.
The following signals are used to print debug information to the outside world. The debug information is a stream of printable ASCII code bytes. When `debug_en=1` , one byte appears on `debug_data` .
output wire debug_uart_tx // debug_uart_tx is the signal after converting {debug_en,debug_data} to UART (format: 115200,8,n,1). If you want to transmit debug info via UART, you can use this signal. If you want to transmit debug info via other custom protocols, please ignore this signal and use {debug_en,debug_data}.
```
In order to facilitate the use, I will also convert the `{debug_en,debug_data}` byte to bit UART output signal `debug_uart_tx`, which can be `debug_uart_tx` connected to the UART of the computer, and use the serial port assistant and other software to view the debugging information. Note that the UART should be configured with baud rate = 115200, data bits = 8, no parity bits, and stop bits = 1.
In order to facilitate the use, I will also convert the `{debug_en,debug_data}` to a UART output signal `debug_uart_tx` . You can connect the UART to PC, and use a Serial Port software (minicom, HyperTermainal, etc) to monitor the debugging information.
Note that the UART configurations are : baud rate=115200, data bits=8, no parity bits.
The following figure shows the debug data printed on the UART when my USB UVC device is plugged into the computer. As you can see, this is a descriptor enumeration process.
@ -633,9 +657,9 @@ The following figure shows the debug data printed on the UART when my USB UVC de
|**Figure**: Debugging data printed on the UART when the USB UVC device is plugged into the computer.|
> When :warning: using the debug interface, use the module parameters `DEBUG="TRUE"`. At `DEBUG="FALSE"` that time, `debug_en` 0 is maintained, and `debug_uart_tx` 1 is maintained (no debug information is output).
> :warning: Because the transmission speed of UART is slow, when a large amount of debugging information is generated, some debugging information will be discarded by UART. For example, when UVC transmits video, the information printed by UART is incomplete because of the large amount of data transmitted. Therefore, if the debugging information needs to be viewed in the process of a large amount of data communication, the UART cannot be used, but other high-speed communication methods are used to send it `{debug_en, debug_data}` to the Host-PC for viewing.
> :warning: Because the speed of UART is slow, when a large amount of debugging information is generated, some debugging information will be discarded. For example, when UVC transmits video, the information printed by UART is incomplete. If you want to view the full debugging information when large amount of USB data, you should use other high-speed communication to send `{debug_en, debug_data}` to Host-PC instead of UART.
@ -670,7 +694,9 @@ The following figure shows the debug data printed on the UART when my USB UVC de
USB 1.1 device 控制器。可在 FPGA 上实现各种 USB 设备。比如 USB扬声器和麦克风、USB摄像头、U盘、USB键盘、USB串口 。
为了在 FPGA 上实现 USB 设备,通常的技术路线是使用 USB 芯片 (例如 Cypress CY7C68013),导致电路和软件的开发成本较高。本库用 FPGA 实现一个通用的 USB 1.1 (Full Speed) device 控制器,可以像 STM32 单片机那样,用非常简单的电路来实现 USB 设备,而不依赖额外的 USB 芯片。基于此,我还在 FPGA 上实现了 USB音频、USB摄像头、U盘、USB键盘、USB-Serial (串口),它们是 USB 所规定的标准设备,因此不需要安装驱动就能即插即用。
为了在 FPGA 上实现 USB 设备,通常的技术路线是使用 USB 芯片 (例如 Cypress CY7C68013),导致电路和软件的开发成本较高。本库用 FPGA 实现一个通用的 USB 1.1 (Full Speed) device 控制器,可以像 STM32 单片机那样,用非常简单的电路来实现 USB 设备,而不依赖额外的 USB 芯片。
基于此,我还在 FPGA 上实现了 USB音频、USB摄像头、U盘、USB键盘、USB-Serial (串口),它们是 USB 所规定的标准设备,因此不需要安装驱动就能即插即用。
本库的特点:
@ -679,7 +705,7 @@ USB 1.1 device 控制器。可在 FPGA 上实现各种 USB 设备。比如 USB
output wire debug_uart_tx // debug_uart_tx is the signal after converting {debug_en,debug_data} to UART (format: 115200,8,n,1). If you want to transmit debug info via UART, you can use this signal. If you want to transmit debug info via other custom protocols, please ignore this signal and use {debug_en,debug_data}.