Skip to content

UCIe · Module 7

Lane Concepts

What a UCIe lane is and how lanes become modules — physical resource versus logical identity, good/enabled/trained state, the mapping table with its uniqueness and stability invariants, module readiness, spare lanes and repair, and lane-level debug method.

Chapter 7.2 followed one bit across one conductor. One conductor carries a very small amount of the traffic a chiplet boundary needs, so UCIe gets its bandwidth the only way a short dense channel allows: many conductors in parallel, each running modestly.

That sounds like it should be simple. It is not, and the reason is the subject of this chapter. A parallel interface is not a bundle of independent wires — it is a set of physical resources that must together reconstruct an ordered logical word at the far end. Which means somewhere there is state that says this logical position is carried by that physical conductor, and that state has to be built, agreed with the peer, validated, frozen, and — when a conductor fails — rebuilt.

Get that state wrong and the link trains perfectly, reports zero errors, and corrupts every single transfer. This chapter is about getting it right.

1. The One-Sentence Model

A lane is a physical transport resource. A logical data position is an architectural identity. Mapping state is what connects the two — and because it is state, it can be built, repaired, and got wrong.

The instinct to fight is that logical lane 3 "is" physical lane 3. It usually is not, and even when it happens to be, depending on it is the bug. Package routing may reverse the order because that is what routed cleanly. Repair may substitute a spare for a failed conductor. The two dies may be oriented differently on the package. Every one of those is a legitimate physical decision made by someone who was not thinking about your data ordering, and the mapping table is what absorbs them.

The payoff, stated up front: logical lane identity survives physical change. A conductor can fail and be replaced without anything above the PHY knowing, because identity lives in a table rather than in the copper.

2. What a UCIe Lane Is

Verified against UCIe's own description of the PHY's physical organisation.

A UCIe module provides:

  • N single-ended, unidirectional, full-duplex data lanesN = 16 for the standard package, N = 64 for the advanced package;
  • one single-ended Valid lane, which frames the data;
  • one Track lane;
  • a differential forwarded clock per direction;
  • four lanes for sideband signalling.

Several things follow immediately, and they are the ones people get wrong.

A data lane is unidirectional. Transmit lanes and receive lanes are separate physical resources. A "x16 module" has 16 lanes in each direction, not 16 shared. Full-duplex is a property of having both sets, not of any lane being bidirectional.

A lane is single-ended, so one lane is one conductor — Chapter 7.2 §3 explained why, and the consequence here is that "lane count" and "conductor count" are the same number for data.

Data lanes are not the whole module. Valid, Track, the forwarded clock, and the sideband are additional physical resources with their own roles. When Chapter 6.1 said that a module's connection footprint drives package feasibility, this is what it was counting — the data lanes are the majority but not the total.

Valid and clock are shared across the module's data lanes. This is why a module is a unit rather than an arbitrary collection: the lanes inside one module share framing and timing infrastructure, so they succeed or fail together in ways that lanes in different modules do not. §11 makes that structural fact into a readiness rule.

3. Physical Resource, Logical Identity

Now the distinction the chapter is built on.

A physical lane is a conductor with a driver at one end and a receiver at the other, a position in the bump map, a route through the package, and health that can change. It is a resource.

A logical lane is a position in the data structure being transported — which slice of the word, in which order, reconstructed where at the far end. It is an identity.

They are connected by a table, and keeping them separate buys four things:

  • Routing freedom. The package can route lanes in whatever order is physically convenient, including reversed, and the PHY absorbs it.
  • Repair. A failed physical resource can be replaced by a spare, and the logical structure is unchanged.
  • Orientation independence. Two dies bonded facing each other naturally present their lanes in opposite order; something has to reconcile that, and mapping is that something.
  • Layer discipline. Nothing above the PHY needs to know any of it — the Module 5 rule, and Chapter 7.1 §16's evidence-versus-conclusions boundary, applied at lane granularity.

UCIe assigns exactly these jobs to the PHY: lane repair and lane reversal are listed among the physical layer's responsibilities, alongside training, scrambling, and clock forwarding.

Four logical lanes numbered zero to three sit above five physical lane resources numbered zero to four. Physical lane one has failed and physical lane four is a spare. Logical zero maps to physical zero, logical one to physical two, logical two to physical three, and logical three to physical four. All five physical resources belong to one module, which also carries valid, track, forwarded clock, and sideband resources.Logical 0identityLogical 1identityLogical 2identityLogical 3identityPhys 0goodPhys 1failedPhys 2goodPhys 3goodPhys 4spare, goodOne moduledata lanes, plus Valid, Track, forwarded clock, and sideband12
Figure 1 — why identity and resource must be separate. Four logical lanes are carried by five physical resources, one of which has failed. The mapping is not the identity function: physical 1 is unusable, so logical 1 shifts onto physical 2 and each later identity shifts onward, with the spare absorbing the displacement. Nothing above the PHY changes — still four logical lanes in the same order. The module contains every physical resource, healthy or not, plus the Valid, Track, forwarded-clock, and sideband resources its data lanes share.

4. Three Facts About a Lane, Not One

A single lane_up bit cannot express what the PHY needs to know. At least three independent facts exist about every physical lane:

good — the physical resource passed the health checks training applied to it. A measurement. It can change while the link is up, because a lane can degrade.

enabled — configuration has chosen to use it. A decision. It changes only in a quiesced state, because changing the set of lanes carrying data would alter the structure underneath in-flight traffic.

trained — this lane has completed whatever per-lane establishment the link requires. A milestone. Distinct from good because a lane can be electrically healthy and simply not yet have been through the process.

They combine in every meaningful way, and each combination is a real situation:

goodenabledtrainedSituation
111in use
10healthy spare, or excluded because the configured width is narrower
00failed and correctly excluded — the desired outcome after repair
01bug: transmitting on a dead conductor (§8)
110training incomplete — legal during bring-up, a bug after it

Two rows deserve emphasis. good=1, enabled=0 is normal, not an anomaly — spare lanes and narrower-than-maximum configurations both produce it, and code that treats every healthy lane as one that must be used gets both wrong. And good=0, enabled=1 is the classic defect, with the distinctive silicon signature §8 describes.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative PHY RTL — not UCIe normative signal naming.
localparam int NUM_PHYS_LANES    = 17;   // 16 data + 1 spare, illustratively
localparam int NUM_LOGICAL_LANES = 16;
 
typedef struct packed {
  logic good;      // measurement: passed physical health checks
  logic enable;    // decision:    configuration chose to use it
  logic trained;   // milestone:   per-lane establishment complete
} lane_state_t;
 
lane_state_t lane_state_q [NUM_PHYS_LANES];
 
logic [NUM_PHYS_LANES-1:0] lane_usable;
 
always_comb
  for (int p = 0; p < NUM_PHYS_LANES; p++)
    lane_usable[p] = lane_state_q[p].good &
                     lane_state_q[p].enable &
                     lane_state_q[p].trained;

Architecture. Physical resources have independent health, and configuration has independent intent. Collapsing them loses the ability to distinguish "broken" from "deliberately unused", which is exactly the distinction repair and width configuration both depend on.

State. Three bits per physical lane. The array is sized by physical lanes, which is deliberately larger than the logical count — the spare has state too.

Cycle behaviour. good is written by training and updated by monitoring, and can change at any time. enable is written by configuration in a quiesced state only. trained is set as training completes per lane and cleared on retrain. lane_usable is combinational over all three.

Contract. The mapping builder (§5) consumes lane_usable when constructing the table. The transmit and receive datapaths consume the mapping, not this vector — they should never index lane state directly, because that would couple the datapath to health.

Failure. With one lane_up bit, a healthy spare is indistinguishable from a lane in use, so repair cannot find a replacement; and a failed lane is indistinguishable from a deliberately disabled one, so diagnostics report the wrong thing.

DV. Cover all five rows of the table above. The fourth row must be impossible by assertion (§8); the second and fifth must be reachable by coverage, because they are legal states that under-tested code paths depend on.

5. The Mapping Table

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative PHY RTL — not UCIe normative signal naming.
localparam int PHYS_IDX_W = $clog2(NUM_PHYS_LANES);
 
// Index = logical lane identity.  Value = physical lane resource carrying it.
logic [PHYS_IDX_W-1:0] logical_to_physical_q [NUM_LOGICAL_LANES];

Architecture. Package routing, orientation, and repair all disturb the correspondence between identity and resource. The table is where those disturbances are absorbed so that nothing above sees them.

State. One physical index per logical lane. Real flip-flops on the die — this is hardware, not a build-time constant and not documentation. It is written after training and after any repair.

Cycle behaviour. Written when the map is committed (§7). Read every cycle data moves, on both the transmit and receive datapaths. It must be stable while data is in flight; §7 is entirely about that requirement.

Contract. The transmit datapath uses it to place logical slices onto physical lanes; the receive datapath uses it — or its inverse — to reconstruct. The two dies must agree, which is what the sideband parameter exchange establishes before the mainband carries anything.

Failure. A table that disagrees between the two ends delivers every bit intact and reassembles the word wrongly. §12 develops this signature; it is the single most characteristic failure in PHY integration.

Note the direction. Indexing by logical and storing physical is the natural direction for the transmitter, which starts with a logical word and needs to know where to put each slice. The receiver has the opposite problem, which is §6.

6. The Reverse Direction

The receiver holds a vector of physical lane samples and must produce a logical word. Two ways to get there, and the choice is a genuine microarchitecture decision rather than a matter of taste.

Option A — index the forward table. For each logical lane, read the physical index and select that physical lane's data:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — receive reconstruction using the forward table directly.
always_comb
  for (int l = 0; l < NUM_LOGICAL_LANES; l++)
    rx_word[l*LANE_W +: LANE_W] =
        rx_phys_data[ logical_to_physical_q[l] ];

Each logical position drives a multiplexer selecting among all physical lanes. Cost: NUM_LOGICAL_LANES multiplexers, each NUM_PHYS_LANES wide, in the receive datapath — and that is a wide, timing-critical path in a design whose whole premise is many parallel lanes.

Option B — store an explicit reverse table. Maintain physical_to_logical_q alongside the forward one, so the receiver reads a destination index per physical lane.

Forward table onlyExplicit reverse table
Storageone tabletwo tables
RX datapathwide mux per logical laneoften better structured for placement
Update complexityone writetwo writes that must stay consistent
Consistency risknonetwo sources of truth can disagree
Timingmux depth on a critical pathshorter path, more state

The trade is area and consistency risk against timing. A wide link at a high rate frequently forces Option B, because the multiplexer depth in Option A does not close timing. But Option B adds a real hazard: two tables that can disagree, updated at different moments, with a window between the writes in which the design is internally inconsistent.

If you choose Option B, the invariant must be checked, not assumed:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — the two tables must be exact inverses over the mapped set.
generate
  for (genvar L = 0; L < NUM_LOGICAL_LANES; L++) begin : g_inverse
    a_map_inverse : assert property (
      @(posedge phy_clk) disable iff (!rst_n)
        map_committed |->
          (physical_to_logical_q[ logical_to_physical_q[L] ] == L[LOG_IDX_W-1:0])
    ) else $error("Reverse map inconsistent for logical lane %0d.", L);
  end
endgenerate

The bug this catches is the update window: a repair rewrites the forward table and the reverse table one cycle apart, and a transfer lands in between. Every bit is healthy and the word is scrambled — and it happens exactly once, at a repair event, which is the hardest kind of bug to reproduce.

7. Mapping Has a Lifetime

The map is state, and state has a lifetime. Getting the lifetime wrong is a more damaging bug than getting the map wrong, because a wrong map fails consistently and a map that changes fails intermittently.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative PHY RTL — not UCIe normative signal naming.
// The candidate map is built during training; the active map is committed once,
// at a boundary where no data is in flight, and then frozen.
always_ff @(posedge phy_clk or negedge rst_n) begin
  if (!rst_n) begin
    for (int l = 0; l < NUM_LOGICAL_LANES; l++)
      active_lane_map_q[l] <= l[PHYS_IDX_W-1:0];     // identity at reset
    map_committed_q <= 1'b0;
  end else if (commit_lane_map && datapath_quiesced) begin
    active_lane_map_q <= candidate_lane_map;
    map_committed_q   <= 1'b1;
  end else if (leave_active) begin
    map_committed_q   <= 1'b0;
  end
end

Architecture. A transfer is striped across lanes and takes more than one cycle to move through the pipeline. If the map changes partway, the earlier part of the transfer was placed by one map and the later part by another, and the receiver — using whichever map it has — reconstructs neither.

State. The active map, a candidate map built during training, and a commit flag. Note datapath_quiesced in the commit condition: the commit is gated not only on wanting to change but on there being nothing in flight.

Cycle behaviour. The active map changes on exactly one cycle, and only at a quiesced boundary. At reset it is the identity map — a safe default that is also, per §9, a dangerous thing to rely on.

Contract. The transmit and receive datapaths read active_lane_map_q and are entitled to assume it does not move under them. The training and repair logic owns candidate_lane_map and must not touch the active one.

Failure — and be precise about the shape. Suppose a transfer occupies four cycles and the map changes after cycle two. Lanes placed in cycles 0 and 1 used the old map; cycles 2 and 3 used the new one. The receiver has one map. The reconstructed word is a mixture that never existed at the source, and — this is the cruel part — it looks exactly like data corruption, so every instinct sends you to the channel. It happens once, at whatever event triggered the remap, and never reproduces on demand.

DV.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — the active map may not change while the link is active.
property p_lane_map_stable_while_active;
  @(posedge phy_clk) disable iff (!rst_n)
    (phy_state_q == PHY_ACTIVE) |=> $stable(active_lane_map_q);
endproperty
 
a_lane_map_stable_while_active :
  assert property (p_lane_map_stable_while_active)
  else $error("Lane map changed while the link was ACTIVE.");

Evaluated on every ACTIVE cycle and requiring stability on the next, this chains into stability across the whole active period — the same structural point Chapter 7.2 §10 made about calibration. And in the testbench, trigger a remap during traffic on purpose and confirm the commit is deferred rather than taken.

8. Two Mapping Invariants Worth Their Weight

Every mapped lane must be usable.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — a logical lane may only be mapped onto a usable physical lane.
generate
  for (genvar L = 0; L < NUM_LOGICAL_LANES; L++) begin : g_map_usable
    a_mapping_targets_usable_lane : assert property (
      @(posedge phy_clk) disable iff (!rst_n)
        (phy_state_q == PHY_ACTIVE) |-> lane_usable[ active_lane_map_q[L] ]
    ) else $error("Logical lane %0d mapped to unusable physical lane %0d.",
                  L, active_lane_map_q[L]);
  end
endgenerate

Physical fact encoded: which conductors actually work in this assembly. Bug caught: the good=0, enabled=1 row of §4's table — a mapping built from a stale health vector, or a repair that updated good and forgot to rebuild the map. Silicon symptom: the bit positions carried by that logical lane are wrong on every transfer, deterministically, while every other position is perfect. Why the ACTIVE qualification: during training the map is legitimately provisional, and an unqualified assertion would fire on correct behaviour and get waived.

No two logical lanes may share a physical lane.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — the mapping must be injective over the logical set.
generate
  for (genvar A = 0; A < NUM_LOGICAL_LANES; A++) begin : g_uniq_a
    for (genvar B = A + 1; B < NUM_LOGICAL_LANES; B++) begin : g_uniq_b
      a_mapping_unique : assert property (
        @(posedge phy_clk) disable iff (!rst_n)
          map_committed_q |->
            (active_lane_map_q[A] != active_lane_map_q[B])
      ) else $error("Logical lanes %0d and %0d both mapped to physical %0d.",
                    A, B, active_lane_map_q[A]);
    end
  end
endgenerate

Why duplication is uniquely nasty. If logical 5 and logical 9 both map to physical 5, then physical 9 carries nothing, and logical 9 receives a copy of logical 5's data. The result is plausible-looking — it is real data, correctly received, in the wrong place. Nothing is corrupted at the bit level, no error counter moves, and integrity checks fail with no indication of why. Random traffic testing does not reliably expose it, because the failure looks like data.

Where duplication comes from: almost always a repair algorithm. Building a map by walking healthy lanes and assigning identities is easy to get right; building it incrementally, by shifting assignments past a newly failed lane, is easy to get wrong at the boundary. This assertion is the cheapest possible guard against a class of bug that is otherwise very expensive.

Note the cost: the nested generate produces N(N−1)/2 assertions, which for 64 logical lanes is over two thousand. That is acceptable in simulation and normally excluded from synthesis, but it is a real compile-time cost worth knowing about. A cheaper equivalent — building a one-hot coverage vector and checking $countones — trades diagnostic precision for compile time, and either choice is defensible.

9. The Wrong Version

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// WRONG architectural assumption — identity mapping.
assign physical_lane = logical_lane;

This is correct if and only if the package routed lanes in order, the two dies present their lanes in the same order, no repair has occurred, no reversal was applied, and no lane was excluded. It is a conjunction of five conditions, none of which the RTL controls.

It is also the reset default in §7's code, deliberately, because you need some starting point. The distinction that matters:

Identity mapping is a legitimate initial value. It is never a legitimate assumption.

The failure is the worst kind — it works. It works in simulation, where the testbench connects lane n to lane n. It works on the first board, where the package happened to route in order. It fails on the second package revision, or on a part where a lane was repaired, or when a die is bonded in the mirrored orientation. And when it fails, it fails as total deterministic corruption on a link that trains cleanly and reports no errors — which sends every instinct to the channel.

10. Striping and Reconstruction

Making the abstraction concrete. On the transmit side, a wide logical word is sliced across logical lanes and then placed onto physical ones:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — logical striping, then mapping onto physical resources.
localparam int LANE_W = 8;   // bits per lane per transfer, illustratively
 
logic [NUM_LOGICAL_LANES*LANE_W-1:0] tx_word;
logic [LANE_W-1:0]                   tx_phys_data [NUM_PHYS_LANES];
 
always_comb begin
  // Unmapped physical resources drive a defined value rather than X.
  for (int p = 0; p < NUM_PHYS_LANES; p++)
    tx_phys_data[p] = '0;
 
  for (int l = 0; l < NUM_LOGICAL_LANES; l++)
    tx_phys_data[ active_lane_map_q[l] ] = tx_word[l*LANE_W +: LANE_W];
end

Architecture. The logical word has an order the protocol above depends on. Physical resources have positions the package assigned. Striping defines the first; mapping reconciles it with the second.

State. None here — this is combinational placement over the registered map.

Cycle behaviour. Evaluated every transfer cycle. Note the default-assignment loop first: without it, a physical lane that no logical lane maps to would be unassigned, inferring a latch in a combinational block and driving X in simulation. Spare lanes make this a live concern rather than a theoretical one, since a spare is unmapped whenever it is not in use.

Contract. The receive side must apply the exact inverse. That is not an assumption to make — it is a property to negotiate over the sideband and then assert (§8).

Failure. Slicing with the wrong bit ordering — LANE_W mismatched between the ends, or the slice direction reversed — produces byte- or nibble-swapped data that looks like corruption and is arithmetic.

The receive side inverts it, as in §6:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — reconstruction using the same committed map.
always_comb
  for (int l = 0; l < NUM_LOGICAL_LANES; l++)
    rx_word[l*LANE_W +: LANE_W] = rx_phys_data[ active_lane_map_q[l] ];

The symmetry is the point. Two combinational blocks, one map, exact inverses. Everything above sees tx_word go in and rx_word come out with the same structure, and nothing above knows which conductor carried what.

11. From Lanes to Modules

Lanes do not exist loose. They are grouped into modules, and per §2 a module is not an arbitrary grouping — its data lanes share a Valid lane and a forwarded clock. That shared infrastructure is what makes the module the meaningful unit.

UCIe defines module widths per package class and has extended the set across revisions: the original x16 (standard package) and x64 (advanced package) physical layer interfaces were joined by an x32 module for the advanced package in UCIe 1.1, and an x8 module (degraded x4) for the standard package. Modules aggregate: UCIe provides for multi-module configurations in groups of 2 or 4 modules, applicable to both standard and advanced packages.

Module width is a packaging decision encoded into the PHY architecture. The advanced package supports 64 lanes per module because its bump pitch and routing density permit that many conductors in the available area; the standard package supports 16 for the same reason in reverse. Chapter 6.1 derived the geometry; this is where it becomes structure.

Module-level state follows the same three-fact discipline as lanes:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative PHY RTL — not UCIe normative signal naming.
localparam int NUM_MODULES = 4;
 
logic [NUM_MODULES-1:0] module_present_q;   // physically instantiated and routed
logic [NUM_MODULES-1:0] module_enable_q;    // configuration chose to use it
logic [NUM_MODULES-1:0] module_trained_q;   // completed training

Architecture. A design may instantiate several modules and a given package or SKU may route fewer; configuration may use fewer still; and training may succeed on some and fail on others. Three independent facts, three masks — the same pattern Module 6 established for dies, layers, and bond segments, now at module granularity.

State. One bit per module per fact. present is fixed by the package and discovered at bring-up; enable is configuration; trained is an outcome.

Cycle behaviour. present settles at bring-up and does not change. enable changes only when quiesced. trained is set as each module completes and cleared on retrain — and note that modules do not train in lockstep, which is exactly the situation §13's degradation handles.

Contract. The link-width logic in Chapter 7.4 consumes all three to determine what width is actually achievable, as opposed to configured.

Failure. Enabling a module the package did not route drives training into nothing: it runs, times out, retries, and consumes bring-up time producing an error that is not an error.

DV.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — an enabled module must be physically present.
property p_enabled_module_is_present;
  @(posedge phy_clk) disable iff (!rst_n)
    (module_enable_q & ~module_present_q) == '0;
endproperty
 
a_enabled_module_is_present :
  assert property (p_enabled_module_is_present)
  else $error("Module enabled but not present: en=%b present=%b",
              module_enable_q, module_present_q);

12. Module Readiness Is a Mask Comparison

A clean and instructive bug:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// WRONG — one working lane does not make a module operational.
assign module_ready = |lane_good;

The reduction OR asks "is any lane good?". That is almost never the question. A module transports a structured word striped across a defined set of lanes; if one of them is missing, the word cannot be reconstructed. One good lane out of sixteen is not a degraded module — it is a broken one that reports ready.

The correct form compares against what the configuration actually requires:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — a module is ready when every lane its configuration requires
// is usable. Not "some lanes work"; "the required set works".
logic [NUM_MODULES-1:0] module_ready;
 
always_comb
  for (int m = 0; m < NUM_MODULES; m++)
    module_ready[m] = module_present_q[m] &&
                      module_enable_q[m]  &&
                      module_trained_q[m] &&
                      ((required_lane_mask[m] & usable_lane_mask[m])
                        == required_lane_mask[m]);

Architecture. Readiness is a statement about a set, and the set is determined by the configured width — which is why required_lane_mask is a mask rather than a count. A repaired module may use a different set of physical lanes than a pristine one while requiring the same number, and a count comparison would accept the wrong lanes being present.

State. None — combinational over registered masks.

Cycle behaviour. Re-evaluated whenever any input mask changes, including when a lane degrades during operation. That is the point: readiness can be withdrawn, and this expression withdraws it automatically.

Contract. The link FSM gates ACTIVE on module readiness; Chapter 7.4's active-width logic consumes it to decide what width is achievable.

Failure. With the reduction OR, the link declares ready with most of its lanes dead, training completes, the Adapter sends, and every transfer is corrupt. Everything reports healthy — which is the worst possible combination.

DV. Force each individual required lane bad in turn and confirm readiness deasserts every time. A test that only removes all lanes passes with the buggy version.

13. Degradation Is Defined Behaviour

Verified: UCIe supports a degraded operating mode in which only half of a module is active when a failure is detected on the other half — which is what the x16/x8 and x64/x32 pairings mean. And at the multi-module level, if any module fails to train during initialisation, the physical layer can degrade the multi-module configuration to the next permitted configuration, including down to module 0.

Two levels of graceful degradation, and both are architecture rather than accident:

  • Within a module — half the lanes, when the other half has a failure.
  • Across modules — fewer modules, when one fails to train.

The engineering point is that these are permitted configurations, not arbitrary widths. You cannot degrade to thirteen lanes because thirteen happened to work. The set of legal fallbacks is defined, which is what makes the outcome interoperable between two dies from different vendors — and it is why Chapter 7.4's requested-versus-active width distinction exists.

14. Spare Lanes and Repair

Chapter 6.6 §9 argued that as interfaces get denser, the ability to lose part of one without losing the product becomes a yield requirement. Lane repair is that ability, and mapping is what makes it invisible.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — physical resources exceed logical identities, so a failure can
// be absorbed without changing the logical structure.
localparam int NUM_LOGICAL_LANES = 16;   // what the architecture transports
localparam int NUM_PHYS_LANES    = 17;   // what the package provides

Architecture. Providing more physical resources than logical identities means a failure costs a spare rather than the link. The number of spares is a yield-versus-area decision made with the packaging team, not an RTL choice.

The invariant that matters is not "no lane failed" — it is that the logical structure survived:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative — every logical lane has exactly one usable physical target.
// Stronger than the per-lane checks: it says the logical width is intact.
property p_logical_width_preserved;
  @(posedge phy_clk) disable iff (!rst_n)
    (phy_state_q == PHY_ACTIVE) |->
      (mapped_usable_count == NUM_LOGICAL_LANES);
endproperty

where mapped_usable_count counts logical lanes whose mapped physical target is usable. Combined with §8's uniqueness assertion, this says: every logical lane is mapped, each to a distinct physical lane, and each of those works. That conjunction is the complete correctness condition for the mapping, and it is worth being able to state in one sentence.

The mental model to keep:

Logical lane identity survives physical repair because mapping is state. A conductor died; the architecture did not notice. That is what the indirection bought.

And the corollary that catches people out: spare lanes do not widen the link. Seventeen physical lanes carrying sixteen logical ones is a sixteen-lane link with a spare, not a seventeen-lane link. Bandwidth is set by the logical width.

The repair algorithm — how a failure is detected, how a replacement is chosen, how the two ends agree — is training and initialisation work, and Module 8 owns it. What belongs here is the structure that makes it possible.

15. Failure Signatures

The diagnostic table for lane-level problems. Each column is a different investigation.

SymptomLane physically marginalMap mismatch TX/RXDead lane still enabledModule config mismatch
Reproducibilityintermittentdeterministicdeterministicdeterministic
Scopeone lane's bit positionsevery transfer, all positionsone logical position, alwaysa whole module's share
Temperature / voltageerror rate changesno effectno effectno effect
Data patternsome patterns worseuniformuniformuniform
Link rateworse when fasterunchangedunchangedunchanged
Error countersincrementing on that lanemay be zeromay be zerozero
Retrainmay recover, then degradeno effectmay repair, then workno effect
First place to lookchannel, PDN, calibrationboth ends' mapsgood vs enablemodule masks, width

Three discriminators do most of the work:

  1. Deterministic or intermittent? Intermittent and environment-sensitive is physics (Chapter 7.2 §12). Deterministic is arithmetic, and arithmetic lives in the three right-hand columns.
  2. How much is wrong? Every position wrong points at the map or the ordering. One position wrong points at that logical lane's target. A contiguous block wrong points at a module.
  3. Does a retrain change anything? Retraining rebuilds health and may repair, so a lane fault can respond to it. A map mismatch and a module misconfiguration will not — the same wrong thing is rebuilt.

16. Configuration Coverage

Assertions prove invariants held in the configurations you ran; coverage says which configurations you ran.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Illustrative lane and module coverage — not UCIe-defined.
covergroup cg_lane_cfg @(posedge phy_clk iff map_committed_q);
 
  cp_failed_lane_count : coverpoint failed_lane_count {
    bins none    = {0};
    bins one     = {1};
    bins several = {[2 : NUM_PHYS_LANES-NUM_LOGICAL_LANES]};
    bins beyond  = {[NUM_PHYS_LANES-NUM_LOGICAL_LANES+1 : NUM_PHYS_LANES]};
  }
 
  cp_remap_active : coverpoint remap_active;          // is the map non-identity?
  cp_module_count : coverpoint active_module_count {
    bins one = {1}; bins two = {2}; bins four = {4};
  }
  cp_degraded     : coverpoint module_degraded;       // half-width fallback in use
 
  // Was a remapped configuration ever exercised on a degraded module?
  x_remap_by_degraded : cross cp_remap_active, cp_degraded;
  x_remap_by_modules  : cross cp_remap_active, cp_module_count;
 
endgroup

Why these bins. failed_lane_count is binned around the number of spares, because the interesting boundaries are zero failures, within repair capacity, and beyond repair capacity — that last bin must be reachable, since exceeding repair capacity is a defined outcome that has to be tested. remap_active matters because the identity map is the case that works with buggy code, so a regression that only ever runs identity mappings has verified nothing about mapping at all.

Why the crosses. Remapping on a pristine full-width link is the easy case. Remapping on a degraded, multi-module configuration exercises the interaction between two independent fallback mechanisms, and interactions between fallbacks are where the code is least travelled and the reasoning least careful.

17. Debugging Lane-Level Corruption

In order, cheapest and most decisive first:

  1. Is the corruption deterministic? If it varies run to run, go to Chapter 7.2 — this is margin, not mapping.
  2. Does it affect the same bit positions every time? Fixed positions are arithmetic. Note which positions: all, one, or a contiguous block (§15).
  3. Are the two ends' maps identical? Dump both. This is the single highest-yield check in PHY integration and it takes minutes.
  4. Are all mapped lanes good? Cross the map against the health vector — §8's assertion in manual form.
  5. Are disabled lanes actually excluded? A lane excluded at one end and used at the other produces exactly this.
  6. Did the map change after ACTIVE? Check for a repair or retrain event correlated with the corruption's onset. A one-off scramble at a specific moment is §7's lifetime bug.
  7. Is the module configuration identical at both ends? Different module counts or widths produce corruption over a contiguous share of the word.
  8. Is the lane order reversed? Reversal is a legitimate, supported physical arrangement — and a completely reversed map produces total corruption that is easy to spot once you look for it.
  9. Do physical error counters point at one lane? If so, go back to step 1 — that is a lane fault wearing mapping's clothes.
  10. Does lowering the rate or the temperature change anything? If yes, it was electrical after all.

Steps 1 to 3 resolve most cases and cost almost nothing. Steps 4 to 8 need PHY state visibility, which is why that visibility is an architectural requirement rather than a debug convenience.

18. Common Misconceptions

"Logical lane 3 must use physical lane 3." Only if routing, orientation, repair, and configuration all happened to preserve identity. Identity is a legitimate reset default and never a legitimate assumption (§9).

"Lane good and lane enabled mean the same thing." good is a measurement, enable is a decision. A healthy spare is good=1, enable=0, and that is normal (§4).

"If a lane trained once it is permanently usable." Health can change during operation — that is why good is monitored rather than latched, and why module readiness can be withdrawn (§4, §12).

"Lane mapping is software metadata." It is a hardware table read on the datapath every cycle data moves (§5).

"Module ready means any lane is ready." It means every lane the configuration requires is usable — a mask comparison, not a reduction OR (§12).

"Changing the lane map during ACTIVE is harmless if the new map is correct." Part of a transfer is placed by the old map and part by the new one, and the receiver has neither. It is a one-off scramble at the moment of change (§7).

"A trained link guarantees correct lane ordering." Training establishes healthy conductors. Whether both ends agree on which conductor carries which identity is a separate agreement (§9, §15).

"Spare lanes increase the link width." Seventeen physical lanes carrying sixteen logical ones is a sixteen-lane link. Bandwidth follows logical width (§14).

"Lane repair means the Protocol Layer must know which lane failed." The point of mapping is that it does not. Logical identity survives physical repair (§3, §14).

"Deterministic corruption is usually analogue noise." The opposite. Analogue problems are statistical and environment-sensitive; deterministic corruption is arithmetic (§15).

19. Understanding Check

20. Summary and What Comes Next

A UCIe data lane is a single-ended, unidirectional physical conductor. A module provides N of them per direction — 16 standard package, 64 advanced package — plus a Valid lane, a Track lane, a differential forwarded clock per direction, and four sideband lanes. Because the data lanes share framing and timing, the module is the structural unit, not the lane.

The idea the whole chapter turns on: a lane is a physical resource; a logical lane is an architectural identity; mapping state connects them. That indirection buys routing freedom, orientation independence, repair, and layer discipline — and it costs you a table that must be built, agreed with the peer, validated, and frozen.

Lane state needs three facts, not one. good is a measurement, enable is a decision, trained is a milestone; good=1, enable=0 is a normal spare and good=0, enable=1 is the classic defect. The map has two invariants — every mapped lane usable, and no two logical lanes sharing a physical one — and the second matters most because duplication delivers real data to the wrong place, moving no error counter. The map also has a lifetime: committed once at a quiesced boundary, frozen while active, because a mid-transfer change scrambles a word exactly once at the moment of the change.

Modules carry the same present / enabled / trained discipline, and module readiness is a mask comparison, not a reduction OR(required & usable) == required, so that readiness withdraws itself when a required lane degrades. Degradation is defined behaviour at both levels: half a module when half fails, fewer modules when one fails to train, always to a permitted configuration, because interoperability requires both ends to converge on a structure they were built for.

And the durable line: logical lane identity survives physical repair because mapping is state. A conductor died and the architecture did not notice — while spare lanes, note, do not widen the link.

The PHY can now turn individual physical conductors into a stable logical set. The remaining question is how many of them the system should actually use, and what that number does to bandwidth, area, die edge, power, buffering, the internal datapath, and the test plan:

  • 7.4 — Link Widths — what x8, x16, x32, and x64 really mean, raw versus useful bandwidth, requested versus active width, and why a wider link can move a bottleneck rather than remove it.

Browse the full path on the UCIe tutorials index.