Link
USB3 Link-Layer modules
- class sol_usb.gateware.usb.usb3.link.USB3LinkLayer(*args, src_loc_at: int = 0, **kwargs)
Abstraction encapsulating the USB3 link layer hardware.
Performs the lower-level data manipulations associated with transporting USB3 packets from place to place.
Command
USB Link Commands Transmitter/Receivers
- class sol_usb.gateware.usb.usb3.link.command.LinkCommandDetector(*args, src_loc_at: int = 0, **kwargs)
USB3 Link Command Detector.
This module detects USB3 link commands as they’re received on the bus.
- Variables:
sink (USBRawSuperSpeedStream, input stream) – The (aligned and descrambled) data stream captured from the physical layer.
command (Signal(4), output) – The link command; including its two-bit class and two-bit type.
command_class (Signal(2), output) – The link command’s class; equivalent to the first two bits of :attr:
command
.command_type (Signal(2), output) – The link command’s type; equivalent to the second two bits of :attr:
command
.subtype (Signal(4), output) – The link command’s subtype.
new_command (signal(), output) – Strobe; indicates that a new link command has been received, and the details of this command are ready to be read.
- class sol_usb.gateware.usb.usb3.link.command.LinkCommandGenerator(*args, src_loc_at: int = 0, **kwargs)
USB3 Link Command Generator.
This module generates link commands on the USB3 bus.
- Variables:
source (USBRawSuperSpeedStream(), output stream) – The data generated in sending our link commands.
command (Signal(4), output) – The link command; including its two-bit class and two-bit type.
subtype (Signal(4), output) – The link command’s subtype.
generate (Signal(), input) – Strobe; indicates that a link command should be generated.
done (Signal(), output) – Indicates that the link command will be complete this cycle; and thus this unit will be ready to send another link command next cycle.
CRC
CRC computation gateware for USB3.
- sol_usb.gateware.usb.usb3.link.crc.compute_usb_crc5(protected_bits)
Generates a 5-bit signal equivalent to the CRC5 check of a given 11-bits.
Intended for link command words / link control words.
- Parameters:
protected_bits (11-bit Signal()) – The 11-bit signal to generate a CRC5 for.
- Returns:
A five-bit signal equivalent to the CRC5 of the protected bits.
- Return type:
Signal(5)
- class sol_usb.gateware.usb.usb3.link.crc.HeaderPacketCRC(*args, src_loc_at: int = 0, **kwargs)
Gateware that computes a running CRC-16 for the first three words of a header packet.
- Variables:
clear (Signal(), input) – Strobe; clears the CRC, restoring it to its Initial Value.
data_input (Signal(32), input) – Data word to add to our running CRC.
advance_crc (Signal(), input) – When asserted, the current data input will be added to the CRC.
crc (Signal(16), output) – The current CRC value.
- Parameters:
initial_value (int, Const) – The initial value of the CRC shift register; the USB default is used if not provided.
- class sol_usb.gateware.usb.usb3.link.crc.DataPacketPayloadCRC(*args, src_loc_at: int = 0, **kwargs)
Gateware that computes a running CRC-32 for a data packet payload.
This CRC is more complicated than others, as Data Packet Payloads are not required to end on a word boundary. Accordingly, we’ll need to handle cases where we have an incomplete word of 1, 2, or 3 bytes.
- Variables:
clear (Signal(), input) – Strobe; clears the CRC, restoring it to its Initial Value.
data_input (Signal(32), input) – Data word to add to our running CRC.
advance_word (Signal(), input) – When asserted, the current data word will be added to our CRC.
advance_3B (Signal(), input) – When asserted, the last three bytes of the current data word will be added to our CRC.
advance_2B (Signal(), input) – When asserted, the last two bytes of the current data word will be added to our CRC.
advance_1B (Signal(), input) – When asserted, the last byte of the current data word will be added to our CRC.
crc (Signal(32), output) – The current CRC value.
next_crc_3B (Signal(32), output) – The CRC value for the next cycle, assuming we advance 3B.
next_crc_2B (Signal(32), output) – The CRC value for the next cycle, assuming we advance 2B.
next_crc_1B (Signal(32), output) – The CRC value for the next cycle, assuming we advance 1B.
- Parameters:
initial_value (int, Const) – The initial value of the CRC shift register; the USB default is used if not provided.
Data
Data Packet Payload (DPP) management gateware.
- class sol_usb.gateware.usb.usb3.link.data.DataHeaderPacket
- class sol_usb.gateware.usb.usb3.link.data.DataPacketReceiver(*args, src_loc_at: int = 0, **kwargs)
Class that monitors the USB bus for data packets, and receives them.
This class has logic redundant with our Header Packet Receiver, to simplify data packet reception. Accordingly, the header section of the data packet will be parsed here as well as in the Header Packet receiver. This simplifies our structure at the expense of an additional CRC-5 and CRC-16 unit.
This class performs the validations required at the link layer of the USB specification; which include checking the CRC-5 and CRC-16 embedded within the header, and CRC-32 of the data packet payload.
Header sequence number is not checked, here, as a sequence error will force recovery in the Header Packet Receiver.
- Variables:
sink (USBRawSuperSpeedStream(), input (monitor only)) – Stream that the USB data to be monitored.
header (HeaderPacket(), output) – The header packet accompanying the current data packet. Valid once a packet begins to be received.
new_header (Signal(), output) – Strobe; indicates that :attr:
header
has been updated.source (StreamInterface(), output stream) – A stream carrying the data received. Note that the data is not fully validated until the packet has been fully received; so this cannot be assumed
packet_good (Signal(), output) – Strobe; indicates that the packet received passed validations and can be considered good.
packet_bad (Signal(), output) – Strobe; indicates that the packet failed CRC checks, or did not end properly.
- class sol_usb.gateware.usb.usb3.link.data.DataPacketTransmitter(*args, src_loc_at: int = 0, **kwargs)
Gateware that generates a Data Packet Header, and orchestrates sending it and a payload.
The actual sending is handled by our transmitter gateware.
- Variables:
data_sink (SuperSpeedStreamInterface(), input stream) – The data stream to be send as a data packet. The length of this stream should match thee length parameter.
send_zlp (Signal(), input) – Strobe; triggers sending of a zero-length packet.
sequence_number (Signal(5), input) – The sequence number associated with the relevant data packet. Latched in once :attr:
data_sink
goes valid.endpoint_number (Signal(4), input) – The endpoint number associated with the relevant data stream. Latched in once :attr:
data_sink
goes valid.data_length (Signal(range(1024 + 1))) – The length of the data packet to be sent; in bytes. Latched in once :attr:
data_sink
goes valid.direction (Signal(), input) – The direction to indicate in the data header packet. Typically Direction.IN; but will be Direction.OUT when data is sent to the host as part of a control transfer.
address (Signal(7), input) – The current address of the USB device.
Header
Header Packet data interfacing definitions.
- class sol_usb.gateware.usb.usb3.link.header.HeaderPacket
Container that represents a Header Packet.
- get_type()
Returns the selection of bits in DW0 that encode the packet type.
- classmethod get_layout()
Computes the layout for the HeaderPacket (sub)class.
- class sol_usb.gateware.usb.usb3.link.header.HeaderQueue(*, header_type=<class 'sol_usb.gateware.usb.usb3.link.header.HeaderPacket'>)
Record representing a header, and stream-link control signals.
- Variables:
valid (Signal(), producer to consumer) – Indicates that the data in :attr:
header
is valid and ready to be consumed.header (HeaderPacket(), producer to consumer) – Contains a full set of header packet data.
ready (Signal(), consumer to producer) – Strobed by the consumer to indicate that it has accepted the given header.
- get_type()
Returns the selection of bits in the current header’s that encode the packet type.
- header_eq(other)
Connects a producer (self) up to a consumer.
- stream_eq(other)
Alias for
header_eq
that ensures we share a stream interface.
- class sol_usb.gateware.usb.usb3.link.header.HeaderQueueArbiter(*args, src_loc_at: int = 0, **kwargs)
Gateware that accepts a collection of header queues, and merges them into a single queue.
Add produces using
add_producer
.- Variables:
source (HeaderQueue(), output queue) – A single header queue that carries data from all producer queues.
- add_producer(interface: HeaderQueue)
Adds a HeaderQueue interface that will add packets into this mux.
- class sol_usb.gateware.usb.usb3.link.header.HeaderQueueDemultiplexer(*args, src_loc_at: int = 0, **kwargs)
Gateware that accepts a single Header Queue, and routes it to multiple modules.
Assumes that each type of header is handled by a separate module, and thus no two inputs will assert :attr:
ready
at the same time.Add consumers using
add_consumer
.- Variables:
sink (HeaderQueue(), input queue) – The single header queue to be distributed to all of our consumers.
- add_consumer(interface: HeaderQueue)
Adds a HeaderQueue interface that will consume packets from this mux.
Idle
Logical idle detection / polling gateware.
- class sol_usb.gateware.usb.usb3.link.idle.IdleHandshakeHandler(*args, src_loc_at: int = 0, **kwargs)
Unit that performs the USB3 idle handshake.
The Idle Handshake occurs after link training; and is the first step of post-training link initialization.
- Variables:
enable (Signal(), input) – Indicates that the idle handshake has started; which is used to create the :attr:
idle_handshake_complete
signal. It should be asserted once we enter Polling.Idle.sink (USBRawSuperSpeedStream(), input stream) – Raw post-descrambling stream from the physical layer.
idle_detected (Signal(), output) – Asserted when the last eight word-aligned symbols detected have been logical idle; identifying a completed idle handshake.
idle_handshake_complete (Signal(), output) – Asserted when we’ve seen IDLE at least once, and we’ve been enabled for at least 16 cycles, as required by the USB3 Idle Handshake [USB3.2r1: 7.5.4.10].
Layer
USB3 link-layer abstraction.
LTSSM
Link Training and Status State Machine (LTSSM) gateware.
- class sol_usb.gateware.usb.usb3.link.ltssm.LTSSMController(*args, src_loc_at: int = 0, **kwargs)
Link Training and Status State Machine
This state machine orchestrates USB bringup, link training, and power saving. It is implemented according to chapter 7.5 of the USB 3.2 specification [USB3.2r1; 7.5].
- Variables:
link_ready (Signal(), output) – Asserted when the link is ready to perform normal USB operations starting at the link layer. When de-asserted, data should not flow above the link layer.
in_usb_reset (Signal(), input) – Should be asserted whenever a USB reset is detected; including a power-on reset (e.g. the PHY has yet to start up), or LFPS warm reset signaling.
engage_terminations (Signal(), output) – When asserted, the physical layer should be applying link terminations.
invert_rx_polarity (Signal(). output) – When asserted, indicates that the physical layer should invert all received data at the I/O boundary to counter a swapped Rx differential pair.
perform_rx_detection (Signal(), output) – Asserted to request that the physical layer perform receiver detection, in which the link
enable_scrambling (Signal(), output) – Asserted when the physical layer should be performing scrambling.
- Parameters:
Ordered Sets
Link training support gateware.
- class sol_usb.gateware.usb.usb3.link.ordered_sets.TSBurstDetector(*args, src_loc_at: int = 0, **kwargs)
Simple Training Set detector; capable of detecting basic training sets.
- Parameters:
sink (USBRawSuperSpeedStream(), input stream) – The sink to monitor for ordered sets; should be fed pre-descrambler data.
detected (Signal(), output) – Strobe; pulses high when a burst of ordered sets has been received.
- class sol_usb.gateware.usb.usb3.link.ordered_sets.TSEmitter(*args, src_loc_at: int = 0, **kwargs)
Training Set Emitter
Generic Training Sequence Ordered Set generator.
This module generates a specific Training Sequence Ordered Set to the TX stream. For each start, N consecutive Ordered Sets are generated (N configured by n_ordered_sets). Done signal is assert on the last cycle of the generation. Training config can also be transmitted for TS1/TS2 Ordered Sets.
Receiver
Header Packet Rx-handling gateware.
- class sol_usb.gateware.usb.usb3.link.receiver.RawHeaderPacketReceiver(*args, src_loc_at: int = 0, **kwargs)
Class that monitors the USB bus for Header Packet, and receives them.
This class performs the validations required at the link layer of the USB specification; which include checking the CRC-5 and CRC-16 embedded within the header packet.
- Variables:
sink (USBRawSuperSpeedStream(), input (monitor only)) – Stream that the USB data to be monitored.
packet (HeaderPacket(), output) – The de-serialized form of our header packet.
new_packet (Signal(), output) – Strobe; indicates that a new, valid header packet has been received. The new packet is now available on :attr:
packet
.bad_packet (Signal(), output) – Strobe; indicates that a corrupted, invalid header packet has been received. :attr:
packet
has not been updated.expected_sequence (Signal(3), input) – Indicates the next expected sequence number; used to validate the received packet.
- class sol_usb.gateware.usb.usb3.link.receiver.HeaderPacketReceiver(*args, src_loc_at: int = 0, **kwargs)
Receiver-side Header Packet logic.
This module handles all header-packet-reception related logic for the link layer; including header packet reception, buffering, flow control (credit management), and link command transmission.
- Variables:
sink (USBRawSuperSpeedStream(), input stream [monitor only]) – Stream that carries data from the physical layer, to be monitored.
source (USBRawSuperSpeedStream(), output stream) – Stream that carries link commands from this unit down down to the physical layer.
enable (Signal(), input) – When asserted, this unit will be enabled; and will be allowed to start transmitting link commands. Asserting this signal after a reset will perform a header sequence and link credit advertisement.
usb_reset (Signal(), input) – Strobe; can be asserted to indicate that a USB reset has occurred, and sequencing should be restarted.
queue (HeaderQueue(), output stream) – Stream carrying any header packets to be transmitted.
retry_received (Signal(), input) – Strobe; should be asserted when the transmitter has seen a RETRY handshake.
retry_required (Signal(), output) – Strobe; pulsed to indicate that we should send a RETRY handshake.
link_command_sent (Signal(), output) – Strobe; pulses each time a link command is completed.
keepalive_required (Signal(), input) – Strobe; when asserted; a keepalive packet will be generated.
packet_received (Signal(), output) – Strobe; pulsed when an event occurs that should reset the USB3 ‘packet received’ timers. This does not indicate valid data is present on the output :attr:
queue
; this has its own valid signal.bad_packet_received (Signal(), output) – Strobe; pulsed when a receive error occurs. For error counting at the link level.
accept_power_state (Signal(), input) – Strobe; when pulsed, a LAU (Link-state acceptance) will be generated.
reject_power_state (Signal(), input) – Strobe; when pulsed, a LXU (Link-state rejection) will be generated.
acknowledge_power_state (Signal(), input) – Strobe; when pulsed, a LPMA (Link-state acknowledgement) will be generated.
Timers
U0 link-maintenance timers.
- class sol_usb.gateware.usb.usb3.link.timers.LinkMaintenanceTimers(*args, src_loc_at: int = 0, **kwargs)
Timers which ensure link integrity is maintained in U0.
These timers ensure that we provide enough traffic to maintain link state, and move to link recovery if we ever fail to see constant traffic.
- Our two main rules [USB3.2r1: 7.5.6.1]:
If we don’t send a link command for 10uS, we’ll need to issue a keepalive packet in order to keep our link stably in U0.
If we don’t receive a link command for 1mS, we know that the link is no longer in good condition, since the other side should have been sending keepalives to prevent this long of an idle. We’ll have to perform link recovery.
- Variables:
link_command_received (Signal(), input) – Strobe that should be asserted when a link command is received.
link_command_transmitted (Signal(), input) – Strobe that should be asserted when a link command is transmitted.
schedule_keepalive (Signal(), output) – Strobe that indicates that we’ll need to send a keepalive packet.
transition_to_recovery (Signal(), output) – Strobe that indicates that our link is no longer stable; and we’ll need to perform link recovery.
- Parameters:
ss_clock_frequency (float) – The frequency of our
ss
domain clock, in Hz.
Transmitter
Packet transmission handling gateware.
- class sol_usb.gateware.usb.usb3.link.transmitter.RawPacketTransmitter(*args, src_loc_at: int = 0, **kwargs)
Class that generates and sends header packets; with an optional payload attached.
This class generates the checks required at the link layer of the USB specification; which include checking the CRC-5 and CRC-16 embedded within the header packet, and the CRC-32 embedded within any associated payloads.
- Variables:
source (USBRawSuperSpeedStream(), output stream) – Stream that carries the generated packets.
header (HeaderPacket(), input) – The header packet to be sent. The CRC fields do not need to be valid, and will be ignored and replaced with a computed CRC. If the header packet is of type data, :attr:
data_sink
will be allowed to provide a follow-up Data Packet Payload.data_sink (SuperSpeedStreamInterface(), input stream) – If the provided :attr:
header
is a Data Header, and :attr:data_sink
is valid when the packet’s transmission is sent, this data stream will be used to provide a follow-up Data Packet Payload.generate (Signal(), input) – Strobe; indicates that a packet should be generated.
done (Signal(), output) – Indicates that the packet will be complete this cycle; and thus this unit will be ready to send another packet next cycle.
- class sol_usb.gateware.usb.usb3.link.transmitter.PacketTransmitter(*args, src_loc_at: int = 0, **kwargs)
Transmitter-side Header Packet logic.
This module handles all header-packet-transmission related logic for the link layer; including header packet generation, partner buffer tracking / flow control, and link command reception.
- Variables:
sink (USBRawSuperSpeedStream(), input stream [monitor only]) – Stream that monitors the data received on the physical layer for link commands.
source (USBRawSuperSpeedStream(), output stream) – Stream that carries our transmissions down to the physical layer.
enable (Signal(), input) – When asserted, this unit will be enabled; and will be allowed to start transmitting.
queue (HeaderQueue(), input stream) – Stream of header packets received received from the protocol layer to be transmitted.
retry_received (Signal(), output) – Strobe; pulsed high when we receive a link retry request.
retry_required (Signal(), output) – Strobe; pulsed high when we need to send a retry request.
lgo_received (Signal(), output) – Strobe; indicates that we’ve received a request to move to a new power state.
output (lgo_target; Signal(2),) – Indicates the power-state associated with a given LGO event; valid when :attr:
lgo_received
is asserted.recovery_required (Signal(), output) – Strobe; pulsed when a condition that requires link recovery occurs.