Core USB 2.0 Device Gateware
The LUNA gateware library provides a flexible base USB Device model, which is designed to provide the basis for creating both application-specific and general-purpose USB hardware.
USB devices are created using two core components:
A
USBDevice
instance, which provides hardware that handles low-level USB communications, and which is designed to be applicable to all devices; andOne or more endpoint interfaces, which handle high-level USB communications – and provide the logic the tailors the device to its intended application.
The USBDevice
communicates with low-level transciever hardware via the FPGA-friendly USB Transceiver
Macrocell Interface (UTMI). Translators can be used to transparently adapt the FPGA interface to other
common bus formats; including the common ULPI low-pin-count variant of UTMI.
Conceptual Components
The USBDevice
class contains the low-level communications hardware necessary to implement a USB device;
including hardware for maintaining device state, detecting events, reading data from the host, and generating
responses.
Token Detector
The Token Detector detects token packets from the host; and is responsible for:
Detecting start of frame packets, which are used to maintain consistent timing across USB devices.
Detecting the start of USB transactions.
Identifying the device and endpoint to which each transaction is addressed.
As each USB transaction starts with a token packet; it is implicitly the Token Detector’s responsiblity
to notify endpoint interfaces of imminent incoming data (OUT
transactions) and requests for data (IN
transactions).
Handshake Detector
The Handshake Detector detects handshake packets from the host; and is responsible for identifying the host’s response to packets from the device – indicating whether the host successfully received a packet sent from the device.
Data Packet Receiver
The Data Packet Receiver is responsible for receiving data packets from the device – including
the payloads of both OUT
and SETUP
transactions – and translating them to a simple data stream.
The Data Receiver handles error detection; and thus validates the checksums of each packet using the Data CRC Unit.
Device State Manager
The Device State Manager is responsible for storing global device state – primarily, the device’s current address and configuration. The device state manager accepts changes to the device’s address/configuration from each endpoint interface; and automatically resets the relevant parameters when a USB reset is received.
Handshake Generator
The Handshake Generator provides a simple, strobe-based interface that allows endpoints to easily emit handshake packets – allowing the device to acknowledge packets (ACK), issue stalls (STALL) , and to rate limit communications (NAK/NYET).
Data Packet Transmitter
The Data Packet Generator is responsible for generating outgoing USB packets from simple data streams; including emitting data packet IDs, sending data, and appending data CRCs. This class automatically appends the required data CRC-16s.
Data CRC Unit
The Data CRC Unit is shared among the packet receiver and packet generator; and handles computing the CRC-16 for USB data streams.
Interpacket Timer
The Interpacket Timer is responsible for maintaining maximum and minimum interpacket delays; ensuring that the device can correctly provide bus turnover times; and knows the window in which handshake packets are expected to arrive.
Reset/Suspend Sequencer
The Reset/Suspend Sequencer is responsible for detecing USB reset and suspend events; and where applicable, participating in the USB reset protocol’s high-speed detection handshake.
The sequencer:
Detects USB resets; and communicates to the Device State Manager that it should return the device to an un-addressed, un-configured state.
Performs the high speed detection handshake, which allows the device to switch to High Speed operation; and thus is necessary for the device to operate at high speed.
Manages the high-speed terminations; as part of the reset-handshake and suspend protocols.
Detects the periods of inactivity that indicate the device is being suspended; and automatically disengages high-speed terminations while the device is in suspend.
usb2.device
Components
Contains the organizing hardware used to add USB Device functionality
to your own designs; including the core USBDevice
class.
- class luna.gateware.usb.usb2.device.USBDevice(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Core gateware common to all LUNA USB2 devices.
The
USBDevice
module contains the low-level communications hardware necessary to implement a USB device; including hardware for maintaining device state, detecting events, reading data from the host, and generating responses.This class can be instantiated directly, and used to build a USB device, or can be subclassed to create custom device types.
To configure a
USBDevice
from a CPU or other wishbone master, seeUSBDeviceController
; which can easily be attached using its attach method.- Parameters:
bus ([UTMI interface, ULPI Interface]) – The UTMI or ULPI PHY connection to be used for communications.
handle_clocking (bool, Optional) – True iff we should attempt to connect up the usb clock domain to the PHY automatically based on the clk signals’s I/O direction. This option may not work for non-simple connections; in which case you will need to connect the clock signal yourself.
- connect
Held high to keep the current USB device connected; or held low to disconnect.
- Type:
Signal(), input
- low_speed_only
If high, the device will operate at low speed.
- Type:
Signal(), input
- full_speed_only
If high, the device will be prohibited from operating at high speed.
- Type:
Signal(), input
- frame_number
The current USB frame number.
- Type:
Signal(11), output
- microframe_number
The current USB microframe number. Always 0 on non-HS connections.
- Type:
Signal(3), output
- sof_detected
Pulses for one cycle each time a SOF is detected; and thus our frame number has changed.
- Type:
Signal(), output
- new_frame
Strobe that indicates a new frame (not microframe) is detected.
- Type:
Signal(), output
- reset_detected
Asserted when the USB device receives a bus reset.
- Type:
Signal(), output
- # State signals.
- suspended
High when the device is in USB suspend. This can be (and by the spec must be) used to trigger the device to enter lower-power states.
- Type:
Signal(), output
- tx_activity_led
Signal that can be used to drive an activity LED for TX.
- Type:
Signal(), output
- rx_activity_led
Signal that can be used to drive an activity LED for RX.
- Type:
Signal(), output
- add_control_endpoint()
Adds a basic control endpoint to the device.
Does not add any request handlers. If you want standard request handlers;
add_standard_control_endpoint
automatically adds standard request handlers.- Return type:
Returns the endpoint object for the control endpoint.
- add_endpoint(endpoint)
Adds an endpoint interface to the device.
- Parameters:
endpoint (Elaborateable) – The endpoint interface to be added. Can be any piece of gateware with a
EndpointInterface
attribute calledinterface
.
usb2.packet
Components
Contains the gatware module necessary to interpret and generate low-level USB packets.
- class luna.gateware.usb.usb2.packet.DataCRCInterface
Bases:
Record
Record providing an interface to a USB CRC-16 generator.
- start
Strobe that indicates that a new CRC computation should be started.
- Type:
Signal(), input to CRC generator
- crc
The current CRC-16 value; updated with each sent or received byte.
- Type:
Signal(), output from CRC generator
- class luna.gateware.usb.usb2.packet.HandshakeExchangeInterface(*, is_detector)
Bases:
Record
Record that carries handshakes detected -or- generated between modules.
- ack
When connected to a generator, pulsing this strobe will trigger generating of an ACK. When connected to a detector, this strobe will be pulsed when an ACK is detected from the host.
- Type:
Signal()
- nak
When connected to a generator, pulsing this strobe will trigger generating of an NAK. When connected to a detector, this strobe will be pulsed when an NAK is detected from the host.
- Type:
Signal()
- stall
When connected to a generator, pulsing this strobe will trigger generation of a STALL. Unused in a detector, currently.
- Type:
Signal()
- nyet
When connected to a generator, pulsing this strobe will trigger generation of a NYET. Unused in a detector, currently.
- Type:
Signal()
- Parameters:
is_detector (bool) – If true, this will be considered an interface to a detector that identifies handshakes. Otherwise, this will be considered an interface to a generator that accepts handshake requests.
- class luna.gateware.usb.usb2.packet.InterpacketTimerInterface
Bases:
Record
Record providing an interface to our interpacket timer.
See [USB2.0: 7.1.18] and the USBInterpacketTimer gateware for more information.
- start
Strobe that indicates when the timer should be started. Usually started at the end of an Rx or Tx event.
- Type:
Signal(), input to timer
- tx_allowed
Strobe that goes high when it’s safe to transmit after an Rx event.
- Type:
Signal(), output from timer
- tx_timeout
Strobe that goes high when the transmit-after-receive window has passed.
- Type:
Signal(), output from timer
- rx_timeout
Strobe that goes high when the receive-after-transmit window has passed.
- Type:
Signal(), output from timer
- attach(*subordinates)
Attaches subordinate interfaces to the given timer interface.
- Parameters:
subordinates ([InterpacketTimerInterface, Signal]) – Each
InterpacketTimerInterface
is provided will be fully connected to a given timer interface. EachSignal
provided will be interpreted as a timer reset, and added to the list of all resets.
- class luna.gateware.usb.usb2.packet.TokenDetectorInterface
Bases:
Record
Record providing an interface to a USB token detector.
- pid
The Packet ID of the most recent token.
- Type:
Signal(4), detector output
- address
The address associated with the relevant token.
- Type:
Signal(7), detector output
- endpoint
The endpoint indicated by the most recent token.
- Type:
Signal(4), detector output
- new_token
Strobe asserted for a single cycle when a new token packet has been received.
- Type:
Signal(), detector output
- ready_for_response
Strobe asserted for a single cycle one inter-packet delay after a token packet is complete. Indicates when the token packet can be responded to.
- Type:
Signal(), detector output
- frame
The current USB frame number.
- Type:
Signal(11), detector output
- new_frame
Strobe asserted for a single cycle when a new SOF has been received.
- Type:
Signal(), detector output
- is_in
High iff the current token is an IN.
- Type:
Signal(), detector output
- is_out
High iff the current token is an OUT.
- Type:
Signal(), detector output
- is_setup
High iff the current token is a SETUP.
- Type:
Signal(), detector output
- is_ping
High iff the current token is a PING.
- Type:
Signal(), detector output
- class luna.gateware.usb.usb2.packet.USBDataPacketCRC(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Gateware that computes a running CRC-16.
By default, this module has no connections to the modules that use it.
These are added using
add_interface
; this module supports an arbitrary number of connection interfaces; seeadd_interface()
for restrictions.- rx_data
Receive data input; can be carried directly from a UTMI interface.
- Type:
Signal(8), input
- rx_valid
Receive validity signal; can be carried directly from a UTMI interface.
- Type:
Signal(), input
- tx_data
Transmit data input; can be carried directly from a UTMI interface.
- Type:
Signal(8), input
- tx_valid
When high, the tx_data input is used to update the CRC.
- Type:
Signal(), input
- Parameters:
initial_value ([int, Const]) – The initial value of the CRC shift register; the USB default is used if not provided.
- add_interface(interface: DataCRCInterface)
Adds an interface to the CRC generator module.
Each interface can reset the CRC; and can read the current CRC value. No arbitration is performed; it’s assumed that no more than one interface will be computing a running CRC at at time.
- Parameters:
interface (DataCRCInterface) – The interface to be added; accepts control signals from other modules, and brings CRC output to them. This method can be called multiple times to generate multiplpe CRCs.
- class luna.gateware.usb.usb2.packet.USBDataPacketDeserializer(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Gateware that captures USB data packet contents and parallelizes them.
- data_crc
Connection to the CRC generator.
- Type:
- new_packet
Strobe that pulses high for a single cycle when a new packet is delivered.
- Type:
Signal(), output
- packet_id
The packet ID of the captured PID.
- Type:
Signal(4), output
- packet
Packet data for a the most recently received packet.
- Type:
Signal(max_packet_size), output
- length
The length of the packet data presented on the packet[] output.
- Type:
Signal(range(0, max_packet_length +1)), output
- Parameters:
utmi (UTMIInterface, or equivalent) – The UTMI bus to observe.
max_packet_size (int) – The maximum packet (payload) size to be deserialized, in bytes.
create_crc_generator (bool) – If True, a submodule CRC generator will be created. Excellent for testing.
- class luna.gateware.usb.usb2.packet.USBDataPacketGenerator(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Module that converts a FIFO-style stream into a USB data packet.
Handles steps such as PID generation and CRC-16 injection.
As a special case, if the stream pulses last (with valid=1) without pulsing first, we’ll send a zero-length packet.
- data_pid
The data packet number to use. The potential PIDS are: 0 = DATA0, 1 = DATA1, 2 = DATA2, 3 = MDATA; the interface is designed so that most endpoints can tie the MSb to zero and then perform PID toggling by toggling the LSb.
- Type:
Signal(2), input
- crc
Interface to our data CRC generator.
- Type:
- stream
Stream input for the raw data to be transmitted.
- Type:
USBInStreamInterface
- tx
UTMI-subset transmit interface
- Type:
UTMITransmitInterface
- Parameters:
standalone (bool) – If True, this unit will include its internal CRC generator. Perfect for unit testing or debugging.
- class luna.gateware.usb.usb2.packet.USBDataPacketReceiver(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Gateware that converts received USB data packets into a data-stream packets.
It’s important to note that packet payloads are mostly directly carried over from UTMI. Since USB data is received -prior- to its CRC, one cannot know if a packet is valid until after it has been compeltely received. As a result, this interface will generate data of unknown validity, followed by a strobe on either
packet_complete
orcrc_mismatch
. The receiving interface must be prepared to handlecrc_mismatch
by discarding the received data.- data_crc
Connection to the CRC generator.
- Type:
- timer
Connection to our interpacket timer.
- stream
Stream that carries captured packet data.
- Type:
USBOutDataStream, output
- active_pid
The PID of the data currently being received.
- Type:
Signal(4), output
- packet_id
The packet ID of the most recently captured PID. Becomes valid simultaneous to a strobe on
packet_complete
orcrc_mismatch
.- Type:
Signal(4), output
- packet_complete
Strobe that pulses high when a new packet is delivered with a valid CRC.
- Type:
Signal(), output
- crc_mismatch
Strobe that pulses high when the given packet has a CRC mismatch; and thus the data received this far should be discarded.
- Type:
Signal(), output
- ready_for_response
Strobe that indicates that an inter-packet delay has passed since
packet_complete
, and thus we’re now ready to respond with a handshake.- Type:
Signal(), output
- Parameters:
utmi (UTMIInterface, or equivalent) – The UTMI bus to observe.
max_packet_size (int) – The maximum packet (payload) size to be deserialized, in bytes.
standalone (bool) – Debug value. If True, a submodule CRC generator will be created.
speed (USBSpeed) – USBSpeed signal or constant that specifies our speed in standalone mode.
- class luna.gateware.usb.usb2.packet.USBHandshakeDetector(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Gateware that detects handshake packets.
- detected
Strobes that indicate which handshakes we’re detecting.
- Parameters:
utmi ([UTMIInterface, UTMITranslator]) – The UTMI interface to listen on.
- ACK_PID = 2
- NAK_PID = 10
- NYET_PID = 6
- STALL_PID = 14
- class luna.gateware.usb.usb2.packet.USBHandshakeGenerator(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Module that generates handshake packets, on request.
Attributes:
- issue_ack: Signal(), input
Pulsed to generate an ACK handshake packet.
- issue_nak: Signal(), input
Pulsed to generate a NAK handshake packet.
- issue_stall: Signal(), input
Pulsed to generate a STALL handshake.
- tx: UTMITransmitInterface
Interface to the relevant UTMI interface.
- class luna.gateware.usb.usb2.packet.USBInterpacketTimer(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Module that tracks inter-packet timings, enforcing spec-mandated packet gaps.
Ports other than
speed
are added dynamically via :method:add_interface`.- speed
The device’s current operating speed. Should be a USBSpeed enumeration value – 0 for high, 1 for full, 2 for low.
- Type:
Signal(2), input
- add_interface(interface: InterpacketTimerInterface)
Adds a connection to a user of this module.
This module performs no multiplexing; it’s assumed only one interface will be active at a time.
- Parameters:
interface (InterpacketTimerInterface) – The InterPacketTimer interface to add to our module.
- class luna.gateware.usb.usb2.packet.USBTokenDetector(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Gateware that parses token packets and generates relevant events.
- interface
The interface that contains token detection events, and information about detected tokens.
- Type:
- speed
Carries a
USBSpeed
constant identifying the device’s current operating speed.- Type:
Signal(2), input
- address
If :parameter:
filter_by_address
is true, this is an input that filters our event detector so it only reports tokens directed at a given address. Iffilter_by_address
is false, this is an output that contains the address of the most recent token.- Type:
Signal(7), input -or- output
- Parameters:
utmi (UTMIInterface) – The UTMI bus to observe.
filter_by_address (bool) – If true, this detector will only report events for the address supplied in the address[] field.
- SOF_PID = 5
- TOKEN_SUFFIX = 1
usb2.reset
Components
Gateware that handles USB bus resets & speed detection.
- class luna.gateware.usb.usb2.reset.USBResetSequencer(*args, src_loc_at=0, **kwargs)
Bases:
Elaboratable
Gateware that detects reset signaling on the USB bus.
- low_speed_only
If set, the device will be forced to operate as a low-speed device.
- Type:
Signal(), input
- prevent_high_speed
If set, the device will be prohibited from entering high-speed states; and will thus act like it’s a full speed device (low_speed_only = 0).
- Type:
Signal(), input
- bus_busy
Hold-off signal that indicates that driving the bus should be delayed.
- Type:
Signal(), input
- vbus_connected
Indicates that the device is connected to VBUS. When this is de-asserted, the device will be held in perpetual bus reset, and reset handshaking will be disabled.
- Type:
Signal(), input
- line_state
The UTMI linestate signals; used to read the current state of the USB D+ and D- lines.
- Type:
Signal(2), input
- bus_reset
- Strobe; pulses high for one cycle when a bus reset is detected. This signal indicates that the
device should return to unaddressed, unconfigured, and should not longer be in High Speed mode.
- Type:
Signal(), output
- suspended
Held high while the USB device should be in suspend. This technically indicates that the device should drop down to consuming suspend current (<= 2.5mA), but very few devices are compliant with this requirement. Either way, a polite device might reduce its power consumption while in suspend.
- Type:
Signal(), output
- current_speed
A USBSpeed value that indicates the current operating speed. Used both to drive our device’s knowledge of operating speed and to drive our PHY’s speed selection.
- Type:
Signal(2), output
- operating_mode
The current UTMI operating mode. Used to select whether we’re driving the USB bus directly; or whether we’re letting the PHY handle NRZI/bit-stuffing.
- Type:
Signal(2), output
- termination_select
Determines the bus termination mode. In LS/FS, this determines the presence of our presence-detect pull-up. In HS mode, this determines whether the USB high-speed termination is present (0), or whether we’re in chirp mode (1).
- Type:
Signal(), output, default=1
- tx
– Our UTMI transmit interface; used to drive chirp signaling onto the bus.
- Type:
UTMITransmitInterface, output stream