USB¶
USB Device Tri-FIFO¶
This is a three-FIFO USB device. It presents one FIFO each for IN
, OUT
, and
SETUP
data. This allows for up to 16 IN
and 16 OUT
endpoints
without sacrificing many FPGA resources.
USB supports four types of transfers: control, bulk, interrupt, and isochronous. This device does not yet support isochronous transfers, however it supports the other types of transfers.
Interrupt and Bulk Transfers¶
Interrupt and bulk transfers are similar from an implementation standpoint – they differ only in terms of how often they are transmitted.
These transfers can be made to any endpoint, and may even be interleaved. However,
due to the nature of TriEndpointInterface
any attempt by the host to interleave
transfers will result in a NAK
, and the host will retry later when the buffer
is empty.
IN Transfers¶
To make an IN
transfer (i.e. to send data to the host), write the data to
IN_DATA
. This is a FIFO, and each write to this endpoint will advance the
FIFO pointer automatically. This FIFO is 64 bytes deep. USB DATA
packets
contain a CRC16 checksum, which is automatically added to any IN
transfers.
TriEndpointInterface
will continue to respond NAK
until you arm the buffer.
Do this by writing the endpoint number to IN_CTRL.EPNO
. This will tell the device
that it should send the data the next time the host asks for it.
Once the data has been transferred, the device will raise an interrupt and you can begin re-filling the buffer, or fill it with data for a different endpoint.
To send an empty packet, avoid writing any data to IN_DATA
and simply write
the endpoint number to IN_CTRL.EPNO
.
The CRC16 will be automatically appended to the end of the transfer.
OUT Transfers¶
To respond to an OUT
transfer (i.e. to receive data from the host), enable
a particular endpoint by writing to OUT_CTRL.EPNO
with the OUT_CTRL.ENABLE
bit set. This will tell the device to stop responding NAK
to that particular
endpoint and to accept any incoming data into a 66-byte FIFO, provided the FIFO
is empty.
Once the host sends data, an interrupt will be raised and that particular endpoint’s
ENABLE
will be set to 0
. This prevents any additional data from entering
the FIFO while the device examines the data.
The FIFO will contain two extra bytes, which are the two-byte CRC16 of the packet. You can safely discard these bytes. Because of this, a zero-byte transfer will be two-bytes, and a full 64-byte transfer will be 66 bytes.
To determine which endpoint the OUT
packet was sent to, refer to
OUT_STATUS.EPNO
. This field is only updated when a successful packet is received,
and will not change until the OUT
FIFO is re-armed.
The OUT
FIFO will continue to respond to the host with with NAK
until the
OUT_EV_PENDING.DONE
bit is cleared.
Additionally, to continue receiving data on that particular endpoint, you will need
to re-enable it by writing the endpoint number, along with the OUT_CTRL.ENABLE
to OUT_CTRL
.
Control Transfers¶
Control transfers are complicated, and are the first sort of transfer that the host uses. Such transfers have three distinct phases.
The first phase is the SETUP
phase, where the host sends an 8-byte SETUP
packet. These SETUP
packets must always be acknowledged, so any such packet
from the host will get loaded into the SETUP
FIFO immediately, and an interrupt
event raised. If, for some reason, the device hasn’t drained this SETUP
FIFO from a previous transaction, the FIFO will be cleared automatically.
Once the SETUP
packet is handled, the host will send an IN
or OUT
packet. If the host sends an OUT
packet, then the OUT
buffer must be
cleared, the OUT.DONE
interrupt handled, and the OUT_CTRL.ENABLE
bit
must be set for the appropriate endpoint, usually EP0. The device will not
accept any data as long as these three conditions are not met.
If the host sends an IN
packet, the device will respond with NAK
if
no data has queued. To queue data, fill the IN_DATA
buffer, then write
0
to IN_CTRL
.
You can continue to fill the buffer (for IN
packets) or drain the buffer
and re-enable the endpoint (for OUT
packets) until the host has finished
the transfer.
When the host has finished, it will send the opposite packet type. If it
is making IN
transfers, it will send a single OUT
packet, or if it
is making OUT
transfers it will send a single IN
packet.
You must handle this transaction yourself.
Stalling an Endpoint¶
When the host sends a request that cannot be processed – for example requesting
a descriptor that does not exist – the device must respond with STALL
.
Each endpoint keeps track of its own STALL
state, though a SETUP
packet
will clear the STALL
state for the specified endpoint (usually EP0).
To set or clear the STALL
bit of an IN
endpoint, write its endpoint number
to IN_CTRL.EPNO
with the IN_CTRL.STALL
bit either set or clear. If
this bit is set, then the device will respond to the next IN
packet from the
host to that particular endpoint with STALL
. If the bit is clear, then
the next IN
packet will be responded to with ACK
and the contents of
the IN
FIFO.
To stall an OUT
endpoint, write to OUT_CTRL.EPNO
with the OUT_CTRL.STALL
bit set. To unstall, write to OUT_CTRL.EPNO
with the OUT_CTRL.STALL
bit
cleared. Note that OUT_CTRL.ENABLE
should not be set at the same time as
OUT_CTRL.STALL
, as this will cause a conflict.
USB Wishbone Bridge¶
This bridge provides a transparent bridge to the target device’s Wishbone bus over USB. It can operate without interfering with the device’s USB stack. It is simple enough to be able to work even if the USB stack is not enumerated, though the host may not cooperate.
USB Wishbone Debug Protocol¶
The protocol transfers four bytes a time in big-endian (i.e. USB) order. It uses SETUP packets
with the special type (0x43) as an attention word. This is then followed by an OUT
packet.
To read data from the device, set the top bit of the bRequestType, followed by an IN
packet.
Register Listing for USB¶
Register |
Address |
---|---|
USB_ADDRESS¶
Address: 0xe0004800 + 0x4 = 0xe0004804
Sets the USB device address, in order to ignore packets going to other devices on the bus. This value is reset when the host issues a USB Device Reset condition.
Field |
Name |
Description |
---|---|---|
[6:0] |
ADDR |
Write the USB address from USB |
USB_NEXT_EV¶
Address: 0xe0004800 + 0x8 = 0xe0004808
In
eptri
, there are three endpoints. It is possible for an IRQ to fire and have all three bits set. Under these circumstances it can be difficult to know which event to process first. Use this register to determine which event needs to be processed first. Only one bit will ever be set at a time.
Field |
Name |
Description |
---|---|---|
[0] |
IN |
|
[1] |
OUT |
|
[2] |
SETUP |
|
[3] |
RESET |
|
USB_SETUP_DATA¶
Address: 0xe0004800 + 0xc = 0xe000480c
Data from the last
SETUP
transactions. It will be 10 bytes long, because it will include the CRC16. This is a FIFO, and the queue is advanced automatically.
Field |
Name |
Description |
---|---|---|
[7:0] |
DATA |
The next byte of |
USB_SETUP_CTRL¶
Address: 0xe0004800 + 0x10 = 0xe0004810
Controls for managing how to handle
SETUP
transactions.
Field |
Name |
Description |
---|---|---|
[5] |
RESET |
Write a |
USB_SETUP_STATUS¶
Address: 0xe0004800 + 0x14 = 0xe0004814
Status about the most recent
SETUP
transactions, and the state of the FIFO.
Field |
Name |
Description |
---|---|---|
[3:0] |
EPNO |
The destination endpoint for the most recent SETUP token. |
[4] |
HAVE |
|
[5] |
PEND |
|
[6] |
IS_IN |
|
[7] |
DATA |
|
USB_SETUP_EV_STATUS¶
Address: 0xe0004800 + 0x18 = 0xe0004818
This register contains the current raw level of the Event trigger. Writes to this register have no effect.
Field |
Name |
Description |
---|---|---|
[0] |
READY |
Level of the ready event |
[1] |
RESET |
Level of the reset event |
USB_SETUP_EV_PENDING¶
Address: 0xe0004800 + 0x1c = 0xe000481c
When an Event occurs, the corresponding bit will be set in this register. To clear the Event, set the corresponding bit in this register.
Field |
Name |
Description |
---|---|---|
[0] |
READY |
Indicates a |
[1] |
RESET |
Indicates a USB |
USB_SETUP_EV_ENABLE¶
Address: 0xe0004800 + 0x20 = 0xe0004820
This register enables the corresponding Events. Write a 0 to this register to disable individual events.
Field |
Name |
Description |
---|---|---|
[0] |
READY |
Write a 1 to enable the ready Event |
[1] |
RESET |
Write a 1 to enable the reset Event |
USB_IN_DATA¶
Address: 0xe0004800 + 0x24 = 0xe0004824
Each byte written into this register gets added to an outgoing FIFO. Any bytes that are written here will be transmitted in the order in which they were added. The FIFO queue is automatically advanced with each write. The FIFO queue is 64 bytes deep. If you exceed this amount, the result is undefined.
Field |
Name |
Description |
---|---|---|
[7:0] |
DATA |
The next byte to add to the queue. |
USB_IN_CTRL¶
Address: 0xe0004800 + 0x28 = 0xe0004828
Enables transmission of data in response to
IN
tokens, or resets the contents of the FIFO.
Field |
Name |
Description |
---|---|---|
[3:0] |
EPNO |
The endpoint number for the transaction that is queued in the FIFO. |
[5] |
RESET |
Write a |
[6] |
STALL |
Write a |
USB_IN_STATUS¶
Address: 0xe0004800 + 0x2c = 0xe000482c
Status about the IN handler. As soon as you write to IN_DATA,
IN_STATUS.HAVE
should go to1
.
Field |
Name |
Description |
---|---|---|
[0] |
IDLE |
This value is |
[4] |
HAVE |
This value is |
[5] |
PEND |
|
USB_IN_EV_STATUS¶
Address: 0xe0004800 + 0x30 = 0xe0004830
This register contains the current raw level of the Event trigger. Writes to this register have no effect.
Field |
Name |
Description |
---|---|---|
[0] |
DONE |
Level of the done event |
USB_IN_EV_PENDING¶
Address: 0xe0004800 + 0x34 = 0xe0004834
When an Event occurs, the corresponding bit will be set in this register. To clear the Event, set the corresponding bit in this register.
Field |
Name |
Description |
---|---|---|
[0] |
DONE |
Indicates that the host has successfully transferred an |
USB_IN_EV_ENABLE¶
Address: 0xe0004800 + 0x38 = 0xe0004838
This register enables the corresponding Events. Write a 0 to this register to disable individual events.
Field |
Name |
Description |
---|---|---|
[0] |
DONE |
Write a 1 to enable the done Event |
USB_OUT_DATA¶
Address: 0xe0004800 + 0x3c = 0xe000483c
Data received from the host will go into a FIFO. This register reflects the contents of the top byte in that FIFO. Reading from this register advances the FIFO pointer.
Field |
Name |
Description |
---|---|---|
[7:0] |
DATA |
The top byte of the receive FIFO. |
USB_OUT_CTRL¶
Address: 0xe0004800 + 0x40 = 0xe0004840
Controls for receiving packet data. To enable an endpoint, write its value to
epno
, with theenable
bit set to1
to enable an endpoint, or0
to disable it. Resetting the OutHandler will set allenable
bits to 0.Similarly, you can adjust the
STALL
state by setting or clearing thestall
bit.
Field |
Name |
Description |
---|---|---|
[3:0] |
EPNO |
The endpoint number to update the |
[4] |
ENABLE |
Write a |
[5] |
RESET |
Write a |
[6] |
STALL |
Write a |
USB_OUT_STATUS¶
Address: 0xe0004800 + 0x44 = 0xe0004844
Status about the current state of the OUT endpoint.
Field |
Name |
Description |
---|---|---|
[3:0] |
EPNO |
The destination endpoint for the most recent |
[4] |
HAVE |
|
[5] |
PEND |
|
USB_OUT_EV_STATUS¶
Address: 0xe0004800 + 0x48 = 0xe0004848
This register contains the current raw level of the Event trigger. Writes to this register have no effect.
Field |
Name |
Description |
---|---|---|
[0] |
DONE |
Level of the done event |
USB_OUT_EV_PENDING¶
Address: 0xe0004800 + 0x4c = 0xe000484c
When an Event occurs, the corresponding bit will be set in this register. To clear the Event, set the corresponding bit in this register.
Field |
Name |
Description |
---|---|---|
[0] |
DONE |
Indicates that an |
USB_OUT_EV_ENABLE¶
Address: 0xe0004800 + 0x50 = 0xe0004850
This register enables the corresponding Events. Write a 0 to this register to disable individual events.
Field |
Name |
Description |
---|---|---|
[0] |
DONE |
Write a 1 to enable the done Event |