Physical

USB3 Physical-Layer modules

class sol_usb.gateware.usb.usb3.physical.USB3PhysicalLayer(*args, src_loc_at: int = 0, **kwargs)

Abstraction encapsulating the USB3 physical layer hardware.

Performs the lowest-level PHY interfacing, including scrambling/descrambling.

Variables:
  • sink (USBRawSuperSpeedStream(), input stream) – Data stream accepted from the Link layer; contains raw data to be transmitted.

  • source (USBRawSuperSpeedStream(), output stream) – Data stream generated for transit to the Link layer; contains descrambled data accepted from the SerDes.

  • enable_scrambling (Signal(), input) – When asserted, scrambling/descrambling will be enabled.

Alignment

Code for USB3 physical-layer encoding.

class sol_usb.gateware.usb.usb3.physical.alignment.RxWordAligner(*args, src_loc_at: int = 0, **kwargs)

Receiver word alignment.

Uses the location of COM signals in the data stream to re-position data so that the relevant commas always fall in the data’s LSB (little endian).

static word_meets_alignment_criteria(data, ctrl)

Returns true iff the given data and control appear to be correctly aligned.

class sol_usb.gateware.usb.usb3.physical.alignment.RxPacketAligner(*args, src_loc_at: int = 0, **kwargs)

Receiver word re-alignment.

Intended to perform a post-descramble (re)-alignment to ensure that we remain aligned to words even if the other side does not maintain word alignment. Many links will work without this; but the USB3 specification does not guarantee that word-alignment will always be maintained.

This unit corrects alignment if the link does not maintain this property.

static word_meets_alignment_criteria(data, ctrl)

Returns true iff the given data and control appear to be correctly aligned.

Coding

Code for USB3 physical-layer encoding.

sol_usb.gateware.usb.usb3.physical.coding.K(x, y)

Converts K/control codes to bytes

Does not result in 8b10b data; requires explicit encoding. See the USB3 / PCIe specifications for more information.

sol_usb.gateware.usb.usb3.physical.coding.D(x, y)

Converts D/data codes to bytes.

Does not result in 8b10b data; requires explicit encoding. See the USB3 / PCIe specifications for more information.

class sol_usb.gateware.usb.usb3.physical.coding.NamedSymbol(name, value, description='', is_data=False)

Simple encapsulation of a USB3 symbol, with simple metadata.

value_const(*, repeat=1)

Returns this symbol’s data value as an Torii const.

ctrl_const(*, repeat=1)

Returns this symbol’s ctrl value as an Torii const.

sol_usb.gateware.usb.usb3.physical.coding.get_word_for_symbols(*target_symbols)

Returns a pair of Torii constants containing the data and ctrl values for the given symbols.

sol_usb.gateware.usb.usb3.physical.coding.stream_matches_symbols(stream, *target_symbols, include_ready=False)

Returns an Torii conditional that evaluates true when a stream contains the given four symbols.

Notes:
  • The given conditional evaluates to False when stream.valid is falsey.

  • Assumes the stream is little endian, so the bytes of the stream would read SYM3 SYM2 SYM1 SYM0.

sol_usb.gateware.usb.usb3.physical.coding.stream_word_matches_symbol(stream, word_number, *, symbol)

Returns an Torii conditional that evaluates true if the given word of a stream matches the given symbol.

CTC

Code for handling SKP ordered sets on the transmit and receive path.

SKP ordered sets are provided in order to give some “padding data” that can be removed in order to handle differences in transmitter/receiver clock rates – a process called “clock tolerance compensation” (CTC). The actual insertion and removal of SKP ordered sets for CTC is handled by the PHY – but it only adds and removes sets where it needs to to compensate for clock differences.

It’s up to us to insert and remove additional ordered sets.

class sol_usb.gateware.usb.usb3.physical.ctc.CTCSkipRemover(*args, src_loc_at: int = 0, **kwargs)

Clock Tolerance Compensation (CTC) receive buffer gateware.

It’s functionally impossible to precisely synchronize the clocks for two independent systems – every specification has to allow for some difference in frequency between the system’s clocks (the “clock tolerance”)

To compensate, high speed serial protocols inject ‘filler’ bytes called “SKP ordered sets”, which can be safely discarded. This allows the slower clock to catch up to the faster one. [USB 3.2r1: 6.4.3].

Our PHY handles the core clock tolerance compensation inside of its own clock domain; removing these filler sets whenever removing them helps to keep the receiver and transmitter’s clocks in sync. This leaves behind the sets whose removal would not directly help with CTC.

This module removes those leftovers before data leaves the physical layer.

Variables:
  • sink (USBRawSuperSpeedStream(), input stream) – The stream from which SKP ordered sets should be removed.

  • source (USBRawSuperSpeedStream(), output stream) – The relevant stream with SKP ordered sets removed. Note that past this point, stream.valid can and will sometimes be false.

  • skip_removed (Signal(), output) – Strobe that indicates that a SKP ordered set was removed.

class sol_usb.gateware.usb.usb3.physical.ctc.CTCSkipInserter(*args, src_loc_at: int = 0, **kwargs)

Clock Tolerance Compensation (CTC) Skip insertion gateware.

See the CTCSkipRemover for a description of CTC and its general operation.

Our PHY handles the core clock tolerance compensation inside of its own clock domain; adding Skip sets whenever adding them helps to keep the transmitter’s elastic buffer from running low on data. However, we still need to add in our own Skip ordered sets so the other side of the link has enough to perform its own CTC adjustments.

This module adds ordered sets, per the USB standard.

Variables:
  • sink (USBRawSuperSpeedStream(), input stream) – The stream into which SKP ordered sets should be inserted.

  • source (USBRawSuperSpeedStream(), output stream) – The relevant stream with SKP ordered sets inserted.

  • can_send_skip (Signal(), input) – Controls when SKPs can be inserted. This should be asserted when we’re transmitting logical idle.

  • sending_skip (Signal(), output) – Indicates that we’re currently sending only SKP characters; and thus our scrambler should not advance.

Layer

USB3 physical-layer abstraction.

class sol_usb.gateware.usb.usb3.physical.layer.USB3PhysicalLayer(*args, src_loc_at: int = 0, **kwargs)

Abstraction encapsulating the USB3 physical layer hardware.

Performs the lowest-level PHY interfacing, including scrambling/descrambling.

Variables:
  • sink (USBRawSuperSpeedStream(), input stream) – Data stream accepted from the Link layer; contains raw data to be transmitted.

  • source (USBRawSuperSpeedStream(), output stream) – Data stream generated for transit to the Link layer; contains descrambled data accepted from the SerDes.

  • enable_scrambling (Signal(), input) – When asserted, scrambling/descrambling will be enabled.

LFPS

Low-frequency periodic signaling gateware.

LFPS is the first signaling to happen during the initialization of the USB3.0 link.

LFPS allows partners to exchange Out Of Band (OOB) controls/commands and consists of bursts where a ‘slow’ clock is generated (between 10M-50MHz) for a specific duration and with a specific repeat period. After the burst, the transceiver is put in electrical idle mode (same electrical level on P/N pairs while in nominal mode P/N pairs always have an opposite level):

Transceiver level/mode: _ = 0, - = 1 x = electrical idle |-_-_-_-xxxxxxxxxxxxxxxxxxxx|-_-_-_-xxxxxxxxxxxxxxxxxxxx|… |<burst> |<burst> |... |<-----repeat period------->|<-----repeat period------->|

A LFPS pattern is identified by a burst duration and repeat period.

To be able generate and receive LFPS, a transceiver needs to be able put its TX in electrical idle and to detect RX electrical idle.

class sol_usb.gateware.usb.usb3.physical.lfps.LFPSTransceiver(*args, src_loc_at: int = 0, **kwargs)

Low-Frequency Periodic Signaling (LFPS) Transceiver

Transmits and receives the LPFS sequences required for a USB 3.0 link.

Variables:
  • drive_electrical_idle (Signal(), output) – Held high when our PHY should be either in Electrical Idle, or transmit LFPS waveforms.

  • send_signaling (Signal(), output) – Held high when our PHY should be transmitting LFPS square waves.

  • signaling_received (Signal(), input) – Should be asserted when our PHY is receiving LFPS square waves.

  • send_polling (Signal(), input) – Strobe. When asserted, begins Polling LFPS.

  • cycles_sent (Signal(16), output) – Incremented every time an LFPS cycle is completed.

  • polling_detected (Signal(), output) – Strobes high when Polling LFPS is detected.

  • reset_detected (Signal(), output) – Strobes high when Reset LFPS is detected.

Power

USB3 physical-layer abstraction.

class sol_usb.gateware.usb.usb3.physical.power.PHYResetController(*args, src_loc_at: int = 0, **kwargs)

Gateware responsible for bringing up a PIPE PHY.

Note that this gateware resides in sync, rather than one of our SuperSpeed domains, as the SuperSpeed PHY has yet to bring up its clocks.

Variables:
  • reset (Signal(), output) – Signal that drives the PHY’s reset signal.

  • phy_status (Signal(), input) – The PIPE PHY’s phy_status signal; tracks our progress in startup.

  • ready (Signal(), output) – Status signal; asserted when the PHY has started up and is ready for use.

Parameters:

sync_frequency (float) – The frequency of the sync clock domain.

class sol_usb.gateware.usb.usb3.physical.power.LinkPartnerDetector(*args, src_loc_at: int = 0, **kwargs)

Light abstraction over our PIPE receiver detection mechanism.

Primarily responsible for the power state sequencing necessary during receiver detection.

Variables:
  • request_detection (Signal(), input) – Strobe; requests that a receiver detection will be performed.

  • power_state (Signal(2), output) – Controls the PHY’s power state signals.

  • detection_control (Signal(), output) – Controls the PHY’s partner detection signal.

  • phy_status (Signal(), input) – Status signal; asserted when the PHY has completed our request.

  • rx_status (Signal(3), input) – Status signal; indicates the result of our request.

  • new_result (Signal(), output) – Strobe; indicates when a new result is ready on :attr:partner_present.

  • partner_present (Signal(), output) – High iff a partner was detected during the last detection cycle.

Parameters:

rx_status (Array(Signal(3), Signal(3))) – Read-only view of the PHY’s rx_status signal.

Scrambling

Scrambling and descrambling for USB3.

class sol_usb.gateware.usb.usb3.physical.scrambling.ScramblerLFSR(*args, src_loc_at: int = 0, **kwargs)

Scrambler LFSR.

Linear feedback shift register used for USB3 scrambling. Polynomial: X^16 + X^5 + X^4 + X^3 + 1

See [USB3.2: Appendix B]

Variables:
  • clear (Signal(), input) – Strobe; when high, resets the LFSR to its initial value.

  • advance (Signal(), input) – Strobe; when high, the LFSR advances on each clock cycle.

  • value (Signal(32), output) – The current value of the LFSR.

Parameters:

initial_value (32-bit int, optional) – The initial value for the LFSR. Optional; defaults to all 1’s, per the USB3 spec.

class sol_usb.gateware.usb.usb3.physical.scrambling.Scrambler(*args, src_loc_at: int = 0, **kwargs)

USB3-compliant data scrambler.

Scrambles the transmitted data stream to reduce EMI.

Variables:
  • clear (Signal(), input) – Strobe; when high, resets the scrambler to the start of its sequence.

  • enable (Signal(), input) – When high, data scrambling is enabled. When low, data is passed through without scrambling.

  • sink (USBRawSuperSpeedStream(), output stream) – The stream containing data to be scrambled.

  • sink – The stream containing data the scrambled output.

Parameters:

initial_value (32-bit int, optional) – The initial value for the LFSR. Optional.

class sol_usb.gateware.usb.usb3.physical.scrambling.Descrambler(*args, src_loc_at: int = 0, **kwargs)

USB3-compliant data descrambler.

This module descrambles the received data stream. K-codes are not affected. This module automatically resets itself whenever a COM alignment character is seen.

Variables:
  • enable (Signal(), input) – When high, data scrambling is enabled. When low, data is passed through without scrambling.

  • sink (USBRawSuperSpeedStream(), input stream) – The stream containing data to be descrambled.

  • source (USBRawSuperSpeedStream(), output stream) – The stream containing data the descrambled output.

Parameters:

initial_value (32-bit int, optional) – The initial value for the LFSR. Optional.