UCIe · Module 28
“UCIe Replaces PCIe”
Why the sentence mixes protocol semantics with physical deployment scope — the word 'PCIe' names two different things, the minimal counterexample that kills the belief in one diagram, and the RTL that follows when a protocol engine is allowed to read the training state of the link underneath it.
Someone says it in an architecture meeting and nobody objects, because everyone in the room half-agrees. The sentence is not quite wrong — it is a category error, and the category error has a cost measured in RTL.
1. The Belief
"UCIe is the new PCIe for inside the package. Eventually it replaces PCIe."
The word doing the damage is replaces. It presupposes that PCIe and UCIe are the same kind of thing, competing for one slot — and that presupposition is where every downstream error comes from, not from any fact about either technology.
This chapter's replacement model (§7) is not "UCIe doesn't replace PCIe." That correction is true and useless. It is: separate semantic protocol ownership from physical deployment scope, compare equivalent stack layers, and then ask which boundary the system is standardising. That model tells you what to do; the negation does not.
2. Why a Competent Engineer Believes It
Five reasons, none of them careless.
"PCIe" is used for two different things and always has been. An engineer says "we'll put PCIe on that edge" meaning the electrical link, and "the driver enumerates PCIe devices" meaning the protocol and its software model. Both usages are correct and universal. The shorthand is the bug — and it is a bug in the vocabulary, not in the speaker.
The stack diagrams look alike. A layered picture with a protocol layer, a link layer and a physical layer describes both, and similar diagrams invite the inference that similar things are being compared.
UCIe maps PCIe. The UCIe Consortium's own public material lists among its initial focus areas "Protocol: CXL/PCIe for near-term volume attach" (§5). So PCIe genuinely does appear inside a UCIe context — and it is a short, wrong step from "PCIe runs over UCIe" to "UCIe is where PCIe went."
Marketing shorthand describes extension, and extension sounds like succession. "Bringing the PCIe/CXL ecosystem into the package" is accurate and easily heard as "moving the PCIe ecosystem into the package."
And the single-board mental model carries over. On a board there really is one interconnect per link, so "which one wins?" is the right question there. Inside a package with a different physical channel, it is the wrong question — and nothing in an engineer's prior experience flags the change.
3. The Hidden Assumption
Stated plainly, so it can be tested:
That "PCIe" names one indivisible thing — that its transaction semantics and its electrical/deployment scope are inseparable, so adopting a new physical interconnect necessarily displaces the protocol that used to ride the old one.
Two sub-assumptions hide inside it.
A — that a protocol's semantics travel with its wires. If true, carrying PCIe semantics over a different physical layer would be impossible, or would make it not PCIe. The existence of protocol mapping is the direct refutation.
B — that the two technologies address the same boundary. If true, exactly one can occupy it. They address different boundaries — a package-internal die-to-die boundary and a platform-level device attachment — and a system routinely has both at once (§7).
4. The Root-Cause Tree
How the belief propagates from a sentence into a bug.
| Level | What happens |
|---|---|
| belief | "UCIe replaces PCIe" |
| ↓ hidden assumption A | protocol semantics are inseparable from the physical layer |
| ↓ hidden assumption B | both technologies compete for the same boundary |
| ↓ architecture decision | the protocol engine is designed as one unit with its transport — no clean semantic/transport contract, because none seemed necessary |
| ↓ RTL decision | the semantic engine reads transport state directly: training state, lane count, attempt number (§10) |
| ↓ DV decision | the checker tracks transport attempts as if they were transactions (27.3 §10) |
| ↓ observed failure | after a transport recovery, an operation is executed twice |
| ↓ misleading symptom | "the link is corrupting data" — because the link event is the visible one |
| ↓ first divergence | the cycle a transport event was allowed to create a semantic operation (§10) |
| ↓ corrected model | §7 — semantic identity is owned above the transport and survives every attempt |
The tree's shape is the module's thesis. A misconception is a locally true idea applied at the wrong architectural scope — here, "the protocol and the link are one thing", which is a perfectly serviceable simplification on a board with one PCIe link (§8) and false the moment semantics and transport are separable.
5. Sourcing and Scope
6. Layer Normalisation
23.1 established the rule this chapter applies: a fair comparison starts by making sure the two things occupy the same architectural layer. Applied here, the comparison the belief makes is between a layer on one side and a whole stack on the other.
| Question | Answer |
|---|---|
| Can the top rows meet? | Yes — the Consortium lists "Protocol: CXL/PCIe" among its focus areas (§5) |
| Does that make the PHY rows the same? | No. Mapping semantics onto a transport says nothing about the transport |
| Do the bottom rows describe the same boundary? | No — "within a package" versus a board/system channel |
| So what is the sentence comparing? | a protocol's identity against a physical scope — two different axes |
Three readings.
The comparison the belief makes is diagonal. It takes PCIe's semantic identity — the thing engineers mean when they say a device is "a PCIe device" — and compares it against UCIe's physical scope. Nothing at all follows from a diagonal comparison, which is why the argument feels unresolvable when two engineers have it.
When you normalise, the interesting question changes shape. "Which replaces which?" becomes "which boundary is this system standardising, and which semantics is it carrying across it?" — and that question has a concrete answer for any given design.
And a mapping is a relationship, not an identity. Protocol P runs over transport T means the semantic layer was preserved and the transport was substituted. It does not mean P became T, and it does not mean P disappeared from anywhere else.
7. The Minimal Counterexample
The smallest system where the belief predicts one thing and reality produces another.
Build it. One package containing two dies joined by an in-package die-to-die link, carrying PCIe-style transaction semantics between them. Outside the package, the platform still attaches an ordinary PCIe device — an NVMe drive, a NIC — over a board-level PCIe link.
| If "UCIe replaces PCIe" were true | What is actually the case |
|---|---|
| the external device link should be redundant or transitional | it is neither; it addresses a boundary the in-package link does not reach |
| PCIe semantics should be displaced | they are carried, which is the opposite of displaced |
| one of the two links should be removable | removing either removes a capability |
| the two should be substitutable | neither can occupy the other's channel |
Both exist at once, permanently, and each is doing something the other cannot.
Three readings, and the third is why this counterexample is the one to remember.
The system contains PCIe semantics twice, over two different transports. Once mapped across the package-internal boundary, once over the board-level link. That is not a contradiction; it is what "protocol mapping" means — and it is impossible to describe using a vocabulary in which the two are competitors.
The counterexample does not require any product to exist. It is an argument about categories, and it holds for any package with an internal die-to-die boundary and an external device attachment. A candidate can draw it in fifteen seconds (§16).
And it identifies the error precisely rather than just contradicting the belief. The belief is not false about a fact; it is a claim about categories that the categories do not support. Once the two axes are separated — semantics and scope — there is nothing left of the sentence to argue about.
8. When the Belief Is Locally Useful
The kernel of truth, because a correction that admits none is just a contradiction.
| The simplification | Where it holds | Where it breaks |
|---|---|---|
| "PCIe means one thing" | a single board-level link — semantics and transport are 1:1 there, and the shorthand is exact | as soon as semantics are separable from transport |
| "one interconnect per boundary wins" | choosing a board-level link — you do pick one | a package adds a second, different boundary |
| "the new standard displaces the old" | generational succession within one boundary — a rate or revision step | across boundaries, where there is nothing to succeed |
Two readings.
The first row is why experienced engineers hold the belief more firmly than beginners. Someone with fifteen years of board-level design has used "PCIe" to mean both things thousands of times without error, because at that boundary the two really are 1:1. The habit is reinforced by a career of it being correct.
And the third row is the honest limit of the correction. Succession is real — a newer revision does displace an older one within a boundary. The belief takes a true intra-boundary rule and applies it across boundaries, which is §4's tree in one sentence: a locally true idea at the wrong scope.
9. Architectural Consequence
What an architect holding this belief decides incorrectly.
| Decision | What the belief produces | What the correct model produces |
|---|---|---|
| link selection | "pick one" — a false either/or | which boundary, then which transport for it |
| protocol layer design | coupled to its transport, because they seemed inseparable | a semantic layer with a transport contract beneath it |
| reliability ownership | unexamined — "PCIe handles it" | named once, explicitly (27.1 §7 B3) |
| software model | assumes the enumeration model follows the transport | the software model follows the semantics |
| external I/O planning | under-planned — expected to shrink | planned on its own boundary |
| verification boundary | one combined protocol-plus-transport testbench | separable layers, separately checkable |
Three readings.
Row 2 is the decision that produces §10's RTL, and it is invisible at the time it is made. Nobody writes down "the protocol engine may depend on transport state" — it simply happens, because no contract said otherwise, and it is discovered when someone tries to substitute the transport.
Row 3 is the most expensive. "PCIe handles reliability" is a statement about a stack, and in a mapped configuration the question "which layer provides it here?" has to be asked again. Assumed-once reliability becomes either two retry layers or none — and 27.5 §4 shows both being found at integration.
And row 6 is where the belief costs schedule rather than correctness. A combined testbench cannot substitute the transport, so the day a second transport appears, the entire environment is re-verified rather than re-targeted.
10. RTL Consequence — Wrong Layering
The semantic layer's transaction record, done correctly, so the contrast is visible.
// ILLUSTRATIVE. A transport-neutral semantic request. Nothing here names a
// transport, which is the property being demonstrated: the same record can be
// carried by any transport that honours the contract in §11.
typedef struct packed {
logic [ID_W-1:0] sem_id; // SEMANTIC identity — stable for the operation's life
logic [GEN_W-1:0] generation; // which use of that identifier
logic [OP_W-1:0] op;
logic [ADDR_W-1:0] address;
logic needs_completion;
} semantic_req_t;Now the engine an architect builds after concluding that the protocol and its transport are one thing.
// WRONG. ILLUSTRATIVE. The semantic engine reads transport state directly to
// decide whether an operation exists. Every line is individually defensible —
// "don't issue while the link is down" is good engineering — and together they
// make the semantic layer a function of the transport.
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
op_live_q <= '0;
next_sem_id_q <= '0;
end else begin
// BUG 1: existence of a semantic operation is gated on PHY training state.
if (phy_training_state == PHY_ACTIVE && req_valid && (phy_lane_count >= 4)) begin
op_live_q[next_sem_id_q] <= 1'b1;
next_sem_id_q <= next_sem_id_q + 1'b1;
end
// BUG 2: a TRANSPORT event creates a SEMANTIC operation. A retry allocates
// a brand-new semantic id, so one operation becomes two.
if (transport_retry_fire) begin
op_live_q[next_sem_id_q] <= 1'b1;
next_sem_id_q <= next_sem_id_q + 1'b1;
end
// BUG 3: a transport-layer recovery clears semantic state unilaterally,
// and restarts identifier allocation while the peer still holds the
// old identifiers.
if (phy_training_state == PHY_RETRAIN) begin
op_live_q <= '0;
next_sem_id_q <= '0;
end
end
endArchitecture. A semantic engine whose inputs include phy_training_state, phy_lane_count and transport_retry_fire. The dependency points the wrong way — upward from transport into semantics.
State. op_live_q and the identifier allocator. Both are semantic state, and all three bugs let a transport event write them.
Event. Three transport events reach semantic state: training-state changes, retry firing, and retrain.
Contract. The consumer above assumes a semantic operation is created once, by a request, and lives until it completes. This engine creates operations on transport events and destroys them on transport events.
Failure — the timeline. A request is accepted; its first transport attempt fails.
| Cycle | Semantic layer | Transport | Peer | Observable |
|---|---|---|---|---|
| 40 | request accepted → sem_id = 7, live | attempt 1 sent | begins work on 7 | normal |
| 51 | waiting | attempt 1 fails | still working on 7 | a transport event |
| 52 | transport_retry_fire → allocates sem_id = 8, live | attempt 2 sent | — | one request, two live operations |
| 60 | 7 and 8 both outstanding | — | working | the peer sees a second operation |
| 73 | — | — | completes original 7 | response for 7 arrives |
| 74 | retires 7 | — | — | looks normal |
| 90 | — | — | completes 8 | a second completion for one request |
| 91 | retires 8 — but the requester asked once | — | — | the operation was performed twice |
And if the operation was a write, it was applied twice, with every integrity check passing.
Root cause. BUG 2 is the load-bearing one. A retry is a new attempt at the same operation; this code makes it a new operation. That is the wrong mental model expressed in four lines — and it follows naturally from believing the protocol and its transport are one thing, because in that view a new transport attempt is a new thing happening.
BUG 3 is the same error in the other direction. A transport recovery clears semantic obligations the peer still holds (26.5 §9) — and restarting the allocator means identifier 7 is handed out again while the peer is still using it.
DV/debug. The reported symptom is "the link is duplicating transactions", because the transport event is the visible one and the duplication follows it. The link is innocent. The discriminator is a peer-side count of semantic operations received per request issued — if the requester issued one and the peer received two, the duplication happened above the transport, not in it.
11. Corrected — the Contract Boundary
// CORRECT. ILLUSTRATIVE. The semantic engine sees FOUR things and nothing else:
// an accepted request, a completion, a fault class, and the active semantic
// configuration. Training state, lane count and attempt number are absent by
// design — that absence IS the layering.
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
op_live_q <= '0;
next_sem_id_q <= '0;
end else begin
// Creation: ONE event, and it is a semantic one.
if (req_valid && req_ready) begin
op_live_q[alloc_id] <= 1'b1;
op_gen_q[alloc_id] <= gen_ctr_q;
next_sem_id_q <= next_sem_id_q + 1'b1;
end
// Retirement: a completion that matches a LIVE entry AND its generation.
// A late completion from a previous use of the id cannot retire the
// current occupant.
if (cmpl_valid && op_live_q[cmpl_id] && (op_gen_q[cmpl_id] == cmpl_gen))
op_live_q[cmpl_id] <= 1'b0;
// A transport recovery does NOTHING here. The obligation is semantic and
// outlives every transport attempt; retention is a contract decision that
// must match the peer's (27.5 §8).
end
end
// MANDATORY. English: a transport retry never creates a semantic operation.
// This is BUG 2 expressed as a property, and it is the single assertion that
// makes the layering enforceable rather than merely intended.
a_retry_creates_no_operation: assert property (
@(posedge clk) disable iff (!rst_n)
transport_retry_fire |-> !(req_valid && req_ready)
);
// MANDATORY. English: a live operation's semantic identity never changes.
// Catches any path that re-derives identity from a transport event —
// the general form of BUG 2 (25.5 §11).
a_sem_id_stable: assert property (
@(posedge clk) disable iff (!rst_n)
(op_live_q[chk] && $past(op_live_q[chk]))
|-> (op_gen_q[chk] == $past(op_gen_q[chk]))
);
// MANDATORY. English: a transport recovery does not clear a live semantic
// obligation. Catches BUG 3 — the unilateral clear the peer never hears about.
a_recovery_preserves_operations: assert property (
@(posedge clk) disable iff (!rst_n)
(transport_recovery_done && op_live_q[chk]) |=> op_live_q[chk]
);Architecture. The corrected engine's input list is the interesting part. Accepted request, completion, fault class, active configuration — and nothing about lanes, training or attempts. Substituting the transport now changes nothing above this line, which is the property the belief cost us.
State. Live bits plus generation. The generation exists precisely so that identity survives transport events — it distinguishes uses of an identifier without the transport ever touching it.
Event. Creation on req_valid && req_ready (27.2 §6). Retirement requires live and in-generation. Transport events reach neither.
Contract. The transport owes: deliver or report a fault, and do not invent or destroy semantic operations. The semantic layer owes: identity stable for the operation's life, and no dependence on how delivery was achieved.
Failure. The residual risk is 27.5 §8's: the peer may hold the opposite retention policy. a_recovery_preserves_operations encodes our answer — and the contract must record that the peer's matches. An assertion is not agreement.
DV/debug. These three properties are simulation-suitable and a_retry_creates_no_operation is a natural formal target — small state, and it is the exact bug. The corroborating evidence is a coverage bin on retries occurring while an operation is live, without which the property has never been evaluated (27.3 §18 I1).
12. DV Consequence
The misconception infects the testbench, and there it is harder to see because the testbench agrees with the design.
| DV mistake the belief produces | Consequence |
|---|---|
| the checker tracks transport attempts as transactions | a retry reads as a duplicate; real duplicates read as normal |
| the scoreboard keys on an attempt-scoped identifier | correlation breaks across any retry |
| the predictor models the transport too | it makes the same wrong assumption as the DUT (27.3 §7) |
| recovery tests run with the pipeline drained | §10's timeline is never constructed |
| the environment cannot swap transports | a combined stack must be re-verified, not re-targeted |
Two readings.
Row 3 is the dangerous one and it is a direct descendant of the belief. If the protocol and transport are one thing, a reference model naturally models both — and then a transport-driven semantic error is reproduced identically in the expected stream. The scoreboard confirms the bug.
And row 4 is the coverage hole that makes all of this survivable to silicon. §10's failure requires a retry while an operation is live. A drained recovery test never constructs it, and the bin will be empty — which is a 27.3 §16 finding stated as a cross.
13. Debug Consequence
| Stage | With the misconception | With the correct model |
|---|---|---|
| symptom | an operation executed twice; data corrupted | same |
| first hypothesis | "the link duplicated a packet" | "where was the second operation created?" |
| where the team looks | transport, PHY, link integrity, the peer's link layer | the allocation path |
| evidence gathered | CRC counters, retrain counts, lane margin — all clean | issued-vs-received semantic counts |
| time lost | days, because the transport looks guilty and is not | — |
| first divergence | — | the cycle a transport event wrote semantic state |
| conclusion | "intermittent link problem" | a four-line RTL fix |
Three readings.
The misconception does not just cause the bug; it also chooses the wrong place to look for it. A transport event is visibly correlated with the failure — the retry happens, then the duplicate appears — and correlation plus a wrong model produces a confident, wrong hypothesis.
Every transport-side measurement comes back clean, and that should be the tell. CRC clean, retrain counts nominal, margin fine, and data still wrong is the signature of something delivered correctly and created incorrectly (21.6 §14).
And the discriminator is one comparison (27.6 §13): semantic operations issued at the requester versus received at the peer. One issued, two received, means the second was manufactured above the transport — and no amount of link analysis will ever show that.
14. Which Review Gate This Corrupts
| Gate | How the belief corrupts it |
|---|---|
| 27.1 Architecture | B2/B3 unanswered — layer responsibilities and reliability ownership are assumed to come with "PCIe" |
| 27.2 RTL | A1 traceability finds no decision to trace, because none was recorded |
| 27.3 Verification | B1 — a predictor that models the transport shares the DUT's error |
| 27.5 Integration | the retention row is never written, because retention looked like a transport detail |
And the architecture gate is where it is cheapest to catch, by a wide margin. 27.1 §7's question B5 — "what must this block NOT assume about the peer?" — surfaces the whole thing in one answer: an engineer holding this belief cannot answer it, because in their model there is no separable peer contract to have assumptions about.
15. Whiteboard Question
"Show me where PCIe semantics stop and the die-to-die transport begins — and mark what survives a transport recovery."
What a weak answer does. Draws one stack, points somewhere in the middle, and describes layers without saying what each owns.
What a strong answer does. Draw the two columns of §6. Then draw a horizontal line and say what crosses it in each direction. Downward: an operation with a stable semantic identity. Upward: delivery, or a fault class. Nothing else.
Then mark the survival set explicitly, because that is the half that gets skipped: semantic identity, generation, the outstanding obligation and the configuration epoch survive a transport recovery; retransmission state and training state do not (26.5 §8).
And the sentence that finishes it: "the reason this line matters is that everything above it must be unchanged if I substitute the transport — and if I can't substitute the transport without changing it, the line is in the wrong place." That is a testable definition of correct layering, not a description of one.
16. Interview Ladder
15 seconds. "They're not competitors — they address different boundaries. PCIe is a platform-level protocol and interconnect; UCIe is an in-package die-to-die interconnect that can carry PCIe semantics. A system usually has both."
60–90 seconds. Add the two meanings: "the confusion comes from 'PCIe' being used for both the protocol and the physical link. Those separate here." Add the mapping: "the Consortium's public material lists CXL/PCIe protocol mapping among its focus areas — so PCIe semantics can be carried across a package-internal boundary. That doesn't put a PCIe PHY between the dies." Add the counterexample: "and the external device link is still there — if UCIe replaced PCIe, that link would be redundant, and it isn't."
Senior follow-up you should expect: "So if PCIe runs over UCIe, what's actually different?" Answer at the layer: "the semantics are preserved and the transport is substituted. What changes is the physical boundary and who owns delivery guarantees — which is a question you have to re-ask in a mapped configuration rather than inherit."
The closing sentence, source-qualified: "UCIe changes the die-to-die transport boundary; it doesn't make the platform-level roles PCIe fills disappear."
Four weak answers, and precisely what is incomplete about each.
| Weak answer | What is missing |
|---|---|
| "UCIe is faster PCIe" | compares a rate across two different channel types — and rate was never the distinction (23.1 §13) |
| "UCIe replaces PCIe inside modern systems" | "inside" is doing unexamined work; the in-package boundary did not previously have a standardised PCIe link to replace |
| "PCIe over UCIe means a PCIe PHY between the dies" | conflates the mapped layer with the layer underneath it — mapping preserves semantics, not electricals |
| "If UCIe supports PCIe, they're the same stack" | support is a relationship, not an identity — the whole point of a mapping is that the stacks differ below the mapped layer |
17. How to Remember the Correct Model
One sentence, and it generalises past this chapter.
Name the boundary before you name the technology.
Applied here: which boundary — package-internal die-to-die, or platform-level device attachment? Then: which semantics is being carried across it? Two questions, and the original sentence dissolves because it never specified a boundary at all.
The memory hook for the failure mode is shorter still: a retry is a new attempt, not a new operation. If you remember only one thing from §10, it is that four-line bug — because it is what the misconception looks like once it reaches hardware.
18. Understanding Check
19. Summary
Six things.
The word replaces is the error (§1). It presupposes the two are the same kind of thing competing for one slot — and every downstream mistake comes from that presupposition rather than from any fact.
The hidden assumption is that "PCIe" names one indivisible thing (§3) — semantics and physical scope fused. Protocol mapping is the refutation.
Normalise the layers before comparing (§6). The belief compares semantic identity against physical scope — a diagonal comparison, which is why the argument never resolves.
The counterexample fits on a napkin (§7): a package-internal link carrying PCIe semantics, plus an external PCIe device link that is still necessary. The system contains PCIe semantics twice, over two transports.
In RTL it becomes four lines (§10): if (transport_retry_fire) allocate a new semantic identifier — one request, two operations, a write applied twice with every check passing. And the transport-side evidence is all clean, which sends debug the wrong way for days.
And the replacement model is a procedure, not a negation (§17): name the boundary before you name the technology, then ask which semantics cross it. A retry is a new attempt, not a new operation.