Source code for jitxlib.protocols.ethernet.mdi.mdi1000base_t

"""MDI - Media Dependent Interface

This module defines the MDI bundle and associated constraint functions
for the 1000Base-T Ethernet standard.

Create a 1000Base-T MDI Constraint and apply it to a simple topology
>>> class EthernetCircuit(Circuit):
...     def __init__(self):
...         self.ethernet_jack = EthernetJack(), EthernetJack()
...         eth0 = ethernet_jack[0].require(MDI1000BaseT)
...         eth1 = ethernet_jack[1].require(MDI1000BaseT)
...         self.mdiconstraint = MDI1000BaseT.Constraint()
...         with self.mdiconstraint.constrain_topology(eth0, eth1) as (src, dst):
...             self += src >> dst

Create a 1000Base-T MDI Constraint and apply it to a complex topology
>>> class EthernetCircuit(Circuit):
...     def __init__(self):
...         self.ethernet_jack = EthernetJack(), EthernetJack()
...         eth0 = ethernet_jack[0].require(MDI1000BaseT)
...         eth1 = ethernet_jack[1].require(MDI1000BaseT)
...         self.mdiconstraint = MDI1000BaseT.Constraint()
...         self.esd_pool = ESDPool(2)
...         with self.mdiconstraint.constrain_topology(eth0, eth1) as (src, dst):
...             for p in range(4):
...                 protected = self.esd_pool.require(DualPair)
...                 self += src.TP[p] >> protected.A >> protected.B >> dst.TP[p]
"""

from __future__ import annotations
from dataclasses import dataclass
from typing import Sequence

from jitx.container import Container
from jitx.net import DiffPair, Port, Provide
from jitx.si import (
    ConstrainReferenceDifference,
    DiffPairConstraint,
    DifferentialRoutingStructure,
    SignalConstraint,
    Topology,
)
from jitx.toleranced import Toleranced
from jitx import current


[docs] class MDI1000BaseT(Port): TP = DiffPair(), DiffPair(), DiffPair(), DiffPair()
[docs] @dataclass class Standard: skew = Toleranced(0, 1.6e-12 / 2) "Intra pair skew - Allowable delay difference as a `Toleranced` value in Seconds." loss = 12 "Max allowable power loss limit in dB." impedance = Toleranced.percent(95, 15) "The expected differential impedance for the differential pairs in Ohms" pair_to_pair_skew = Toleranced(0, 330e-12 / 2) "Allowable inter-pair delay difference as a `Toleranced` value in Seconds."
[docs] class Constraint(SignalConstraint["MDI1000BaseT"]): diffpair_constraint: DiffPairConstraint inter_skew: Toleranced def __init__( self, standard: MDI1000BaseT.Standard | None = None, structure: DifferentialRoutingStructure | None = None, ): std = standard or MDI1000BaseT.Standard() if not structure: structure = current.substrate.differential_routing_structure( std.impedance ) self.diffpair_constraint = DiffPairConstraint( skew=std.skew, loss=std.loss, structure=structure ) self.inter_skew = std.pair_to_pair_skew
[docs] def constrain(self, src: MDI1000BaseT, dst: MDI1000BaseT): super().constrain(src, dst) for s, d in zip(src.TP, dst.TP, strict=True): self.diffpair_constraint.constrain(s, d) self.add( ConstrainReferenceDifference( Topology(src.TP[0].p, dst.TP[0].p), (Topology(s, d) for s, d in zip(src.TP, dst.TP, strict=True)), ).timing_difference(self.inter_skew) )
[docs] class Provide(Container): """Construct provider for a 1000Base-T connection. This constructs a provider for a 1000Base-T (Gigabit) MDI interface. This includes creating the appropriate option mappings for swapping the differential pairs. >>> self += MDI1000BaseT.Provide( ... [self.C.TXRX1A, self.C.TXRX1B, self.C.TXRX1C, self.C.TXRX1D] ... ) """ def __init__(self, diffpairs: Sequence[DiffPair] | Sequence[tuple[Port, Port]]): """Constructor for the MDI 1000Base-T Pin Assignment Provider. This provider constructs the diff-pair assignments for 1000Base-T connection including the valid swaps for the A/B and C/D pairs. Args: diffpairs: User can provide the diff-pair ports for the provider one of two forms: 1. A sequence of `DiffPair` ports, one for each of the four pairs. 2. A sequence of tuples where each tuple contains the positive and negative signal port for each differential pair. The order of each pair is `(P, N)`. """ assert len(diffpairs) == 4 self.options = Provide(MDI1000BaseT) @self.options.one_of def bundle_swaps(bundle: MDI1000BaseT): pair_maps = ( (0, 1, 2, 3), # Straight Through (1, 0, 2, 3), # A/B swapped (0, 1, 3, 2), # C/D swapped (1, 0, 3, 2), # A/B & C/D swapped ) straight = (0, 1, 2, 3) def get_P(pair: DiffPair | tuple[Port, Port]) -> Port: if isinstance(pair, DiffPair): return pair.p else: return pair[0] def get_N(pair: DiffPair | tuple[Port, Port]) -> Port: if isinstance(pair, DiffPair): return pair.n else: return pair[1] mapP = [ [ (bundle.TP[a].p, get_P(diffpairs[b])) for a, b in zip(swapped, straight, strict=True) ] for swapped in pair_maps ] mapN = [ [ (bundle.TP[a].n, get_N(diffpairs[b])) for a, b in zip(swapped, straight, strict=True) ] for swapped in pair_maps ] return [a + b for a, b in zip(mapP, mapN, strict=True)]