Skip to content
VLSI Mentor

DDR · Module 19

PHY Responsibilities

The controller decides which DDR operation should happen. The PHY makes it real at a pin boundary whose timing the controller cannot meet — and the line between them is not the same in any two implementations.

Eighteen modules have built one side of a memory system: what DRAM is, what its commands mean, what its timing permits, and how a controller turns transaction intent into a legal command stream. Module 17 ended with a controller that decides correctly. Module 18 ended with the mapping that decides what it has to work with.

None of it has yet reached a wire.

This module begins the layer that does, and it opens by fixing a boundary that gets blurred more than almost any other in the field:

The controller decides which DDR operation should happen. The PHY is responsible for making that decision real at a pin boundary whose timing the controller cannot meet and should not try to.

That sentence needs a qualification immediately, and the qualification is not a footnote — it is one of the chapter's main results. The exact line between them is implementation-dependent. Two correct DDR designs can place the same function on opposite sides of it.

1. Why a PHY Exists at All

The honest way in is to ask what happens if you try to do without one.

A memory controller is ordinary synchronous digital logic. It is written in RTL, synthesised into standard cells, placed and routed by the same flow as the rest of the SoC, and verified by simulating its clock. Everything Module 17 built is that kind of logic.

Now look at what the DRAM interface demands. Data moves on both edges of a strobe that the DRAM itself generates during a read (Chapter 6.10). That strobe arrives with a phase relationship set by board trace length, package delay and temperature — none of which the SoC knows at synthesis time. The received data must be sampled inside a window that may be a small fraction of a bit period wide. And the same wires reverse direction between reads and writes (Chapter 10.5).

2. Three Layers, Named

The DDR stack in four bands from top to bottom. The memory controller decides what should happen: it accepts transactions, maps addresses, tracks bank state, schedules commands and enforces timing legality. Below it, the controller to PHY interface is a synchronous digital contract carrying commands, addresses, write data and returning read data, together with status. Below that, the DDR PHY realises the decision at the pins: it serialises write data, deserialises read data, drives and gates the strobe, applies trained delays and owns the clocking and input output resources. At the bottom, the DRAM device responds to whatever arrives at its pins, with no knowledge of which layer above produced it.Where each decision is madeMemory Controllertransactions · address mapping · bank state · scheduling · timing legality — WHAT should happentransactions · address mapping · bank state · scheduling · timing legality — WHAT should happenController / PHY Interfacesynchronous digital contract: command, address, write data, read data, status — the HANDOVERsynchronous digital contract: command, address, write data, read data, status — the HANDOVERDDR PHYserialise · deserialise · drive and gate the strobe · trained delays · clocking · I/O — HOW it reaches the pinsserialise · deserialise · drive and gate the strobe · trained delays · clocking · I/O — HOW it reaches the pinsDRAM Deviceresponds to what arrives at its pins — it cannot see the layers aboveresponds to what arrives at its pins — it cannot see the layers above

The bottom band carries a point that is easy to skim past and shapes everything else. The DRAM sees only its pins. It has no idea whether a well-formed command came from a sophisticated scheduler or a state machine that got lucky, and no idea whether the data arriving on a write was aligned by a carefully trained delay or by accident. Every guarantee the upper layers provide has to survive as far as the pins to be worth anything.

That is why the PHY's job is not decoration on top of the controller's. The controller's correctness is only as good as the PHY's realisation of it, and §8's failure taxonomy is organised around exactly that dependency.

3. The Ownership Table

The central artefact of this chapter. Read the right-hand columns as carefully as the left.

FunctionControllerPHYDRAMImplementation-dependent?Detail owned by
Accept upstream transactionyesnonono17.5
Address mappingyesnonoyes — some platforms map above the controllerModule 18
Bank-state trackingyesnono5.2
Command scheduling and arbitrationyesnonono17.1, 17.4
Timing-legality enforcementyesnonoyes — some timing is enforced jointlyModules 1314
Refresh policyyesnonoyes — some devices self-manage part of it17.3
Command / address launch at the pinsnoyesnono19.3
Write-data serialisationnoyesnoyes — ratio varies19.2
Read-data deserialisationnoyesnoyes — ratio varies19.2
Write strobe generationnoyesnono19.4
Read strobe generationnonoyesno6.10
Strobe gating on receivenoyesnono19.4
Adjustable delay elementsnoyesnono19.5
Discovering trained valuesvariesvariesnostrongly — firmware, controller or PHY-internalModule 21
Read-data capturenoyesnonoModule 20
Data-bus turnaround managementyes (spacing)yes (direction)yes19.3, Module 22
ODT controlyes (decides)yes (applies)yes (terminates)yesModule 22
Output-driver calibration (ZQ)yes (invokes)yes (performs)yes by generation7.7
Electrical I/OnoyesyesnoModule 22
Transaction completionyesnonono17.5 §8

4. The PHY's Internal Paths

Zooming into the third band. Four paths, and they are not variations on one another.

Inside the DDR PHY, showing four distinct paths and the modules that own their detail. From the controller interface on the left, a command and address path carries the scheduled command through launch alignment to the command and address pins, and is unidirectional toward the DRAM. A write path takes wide slow controller words through serialisation and strobe generation to the data pins. A read path runs the other way: data and strobe arrive from the DRAM, pass through a gate that decides when the incoming strobe is allowed through, then an abstract capture block, then deserialisation back to wide controller words. A fourth group, clocking and trained settings, feeds all three paths with clocks and with opaque delay values. Each path is labelled with the chapter or module that owns its detail: serialisation and deserialisation in chapter nineteen point two, alignment in nineteen point three, gating in nineteen point four, trained settings in nineteen point five, capture in module twenty, and the discovery of trained values in module twenty-one.Controller interfacesynchronous contractCommand / address19.3 — launch alignmentCA pinsone direction onlyWrite path19.2 — serialiseStrobe generate19.4 — PHY drives itDQ / DQS pinsbidirectionalReceive gate19.4 — when to listenCAPTUREModule 20 opens thisRead path19.2 — deserialiseClocking19.2 — rate domainsTrained settings19.5 holds · M21 finds12

The command/address path is unidirectional and the data path is not. That single asymmetry produces most of the PHY's complexity: a one-way path needs launching, while a two-way path needs launching, direction management, gating and capture.

The box marked CAPTURE stays closed in this module. Everything else on the drawing is opened by a chapter of Module 19; that one is Module 20's. The discipline is deliberate — §8's taxonomy depends on being able to say “the fault is at the capture layer” as a distinct claim.

5. What Cannot Be Written in Portable RTL

§1 argued this from a failing example. Here it is as a list, because it is the sharpest way to see what the PHY is.

StructureWhy portable RTL cannot express itWhat actually provides it
Sub-cycle adjustable delayRTL has no notion of a fraction of a bit periodtechnology-specific delay cell, configured post-manufacture
Data-rate serialiser at the pincannot be closed against a data-rate path in the fabrichardened I/O serialiser
Strobe-domain capture flopclocked by a signal the design does not generatededicated capture circuitry in the I/O cell
Clock multiplication and phase generationa frequency relationship, not a logic functionPLL / DLL resource
Termination and drive strengthelectrical parameters, not logic valuesI/O cell with calibrated legs (Module 22)
Sensing the correct sampling pointrequires measuring a physical margincalibration hardware plus an algorithm (Module 21)

6. The Handover

The controller and the PHY meet at a synchronous digital contract. What crosses it, in architectural terms:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  controller  ---->  PHY        command, address, rank/chip select
                                write data, write mask
                                direction / turnaround intent

  PHY  ---->  controller        read data, with framing
                                interface status and readiness

An industry-standard interface exists for this boundary. The DDR PHY Interface (DFI) specification defines signals, timing and programmable parameters for transferring control information and data between a memory controller and a PHY. It was developed as a multi-company industry standard rather than a JEDEC device specification — the two are different kinds of document, and only the latter constrains the DRAM.

The DFI-relevant fact worth carrying into Chapter 19.2 is its frequency-ratio concept: DFI defines the relationship between the controller and PHY reference clocks and supports 1:1, 1:2 and 1:4 controller-to-PHY ratios, so that a controller may run at half or quarter the PHY's rate. That is the standardised expression of the width-versus-rate trade 19.2 is built on — and it is the reason this module never invents a ratio of its own.

What this chapter does not do is reproduce DFI's signal set. Signal names, widths and semantics are version-specific and belong to the specification; a tutorial that paraphrases them from memory produces a plausible-looking interface that matches nothing. The block below therefore models a generic command handover with explicitly-named signals of its own, and says so.

7. Calibration Is Not One Thing

A terminology trap worth clearing before Chapter 19.5, because two different things share the word.

ZQ calibration is a DRAM-side activity: the device calibrates its own output-driver and termination characteristics against a reference resistor. Chapter 7.7 owns it, including the important detail that its result is not directly observable to the controller, and that DDR5 changed how it is invoked.

PHY calibration is a PHY-side activity: the PHY establishes its own delay settings, gate positions and sampling points so that it can transmit and receive correctly against this particular board and device. Chapter 19.5 owns its lifecycle; Module 21 owns the algorithms.

They are different mechanisms, on different sides of the interface, producing different state, invoked differently. A system can have a perfectly calibrated DRAM output driver and a completely mis-trained PHY receiver, and the symptoms will not resemble each other. §8's taxonomy separates them into distinct rows for exactly that reason.

8. A Failure Taxonomy Across Six Modules

The practical payoff of the ownership table: when a DDR interface misbehaves, the first question is which layer, and the answer determines which module's knowledge applies.

LayerTypical symptom shapeDistinguishing evidenceOwned by
A — Controller logicillegal command, wrong address, starvationprotocol checker flags a violation; the command stream is wrong before it leavesModule 17
B — Controller/PHY interfacedata present but wrong order, lost handshake, framing offcontroller-side word and PHY-side beat sequence disagreethis module, 19.2
C — PHY digital datapathlane swap, beat reversal, ownership errorfault is deterministic and rate-independentthis module, 19.219.4
D — Capture / timingcorruption that worsens with rate or temperaturelower data rate works; specific lanes marginalModule 20
E — Training / calibrationworks after warm reset, fails cold; one lane onlyfailure correlates with bring-up, not traffic19.5 lifecycle, Module 21 algorithms
F — Signal integritypattern-dependent errors, worse on long tracesdepends on data pattern and board positionModule 22

The rate test is the single most useful discriminator, and it is worth knowing precisely what it does and does not prove. If the interface works at a lower data rate and fails at full rate, layers A, B and C are largely exonerated — digital ordering bugs do not care about frequency. It points at D, E or F. It does not say which of the three, and treating “fails only at speed” as proof of a signal-integrity problem skips two layers that are more likely and cheaper to check.

9. The Command Handover Block

One responsibility: the digital contract by which the controller hands a scheduled command to the PHY, and the PHY accepts ownership of launching it.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────
// phy_command_stage
//
// CLASSIFICATION
//   Synthesizable educational RTL. Sequential. One responsibility: the
//   controller-to-PHY command handover -- acceptance, ownership, and
//   the gating of that acceptance on interface readiness.
//
//   It is a GENERIC contract. It is NOT an implementation of DFI or of
//   any other standard interface; signal names here are this module's
//   own and are not a paraphrase of any specification.
//
// WHAT IT DOES NOT MODEL
//   - No command legality. Chapter 13.1 owns the legality layers and
//     Chapter 17.1 owns the commit that produced this command. A PHY
//     cannot repair an illegal command and this block does not try.
//   - No scheduling, queueing or arbitration (Module 17).
//   - No physical launch. cmd_launch is an abstract handoff toward the
//     command/address path; pin timing, slew, drive and the actual
//     CA signalling are outside this model entirely.
//   - No data path. Chapter 19.2 owns serialisation.
//   - No training, no delay elements, no calibration algorithm. The
//     readiness input is produced by Chapter 19.5's lifecycle; how the
//     settings behind it were found is Module 21's subject.
//   - No clock-domain crossing. Everything here is in ONE domain; §11
//     explains why a real PHY's domain structure is not modelled.
// ─────────────────────────────────────────────────────────────────────
module phy_command_stage #(
  parameter int CMD_W  = 4,
  parameter int ADDR_W = 24,
  parameter int CS_W   = 2
) (
  input  logic               clk,
  input  logic               rst_n,

  // ── From the controller. Chapter 17.1's commit produced this; here
  //    it is offered across the interface and may be refused.
  input  logic               ctrl_cmd_valid,
  input  logic [CMD_W-1:0]   ctrl_cmd,
  input  logic [ADDR_W-1:0]  ctrl_addr,
  input  logic [CS_W-1:0]    ctrl_cs,
  output logic               ctrl_cmd_ready,

  // ── From Chapter 19.5's lifecycle. NOT the same as !rst_n: reset
  //    release is the first of several steps before traffic is legal,
  //    and conflating them is §12's misconception.
  input  logic               phy_operational,

  // ── Toward the command/address path. Abstract: this is a handoff
  //    to logic that will launch it, not a pin.
  output logic               cmd_launch,
  output logic [CMD_W-1:0]   launch_cmd,
  output logic [ADDR_W-1:0]  launch_addr,
  output logic [CS_W-1:0]    launch_cs,
  input  logic               launch_taken,

  // ── Observability.
  output logic               busy,
  output logic               err_accept_while_not_operational
);

  // ── Zero-width operands have no meaning at this interface.
  if (CMD_W  < 1) $fatal(1, "phy_command_stage: CMD_W must be >= 1");
  if (ADDR_W < 1) $fatal(1, "phy_command_stage: ADDR_W must be >= 1");
  if (CS_W   < 1) $fatal(1, "phy_command_stage: CS_W must be >= 1");

  logic                held;
  logic [CMD_W-1:0]    h_cmd;
  logic [ADDR_W-1:0]   h_addr;
  logic [CS_W-1:0]     h_cs;

  // ── THE CONTRACT, stated once.
  //    Producer : the controller.  Consumer : this stage.
  //    Transfer : ctrl_cmd_valid && ctrl_cmd_ready, on the rising edge.
  //    Readiness depends on downstream capacity and on the interface
  //    being operational -- it never depends on ctrl_cmd_valid, so no
  //    combinational loop can form through this block.
  assign ctrl_cmd_ready = phy_operational && (!held || launch_taken);

  assign busy = held;

  // ── A command accepted while the interface is not operational is a
  //    controller error, surfaced rather than silently launched into a
  //    PHY that cannot carry it.
  assign err_accept_while_not_operational =
      ctrl_cmd_valid && ctrl_cmd_ready && !phy_operational;

  // ── The launch offer. Combinational from held state: the stage
  //    presents what it owns and waits to be taken.
  assign cmd_launch  = held;
  assign launch_cmd  = h_cmd;
  assign launch_addr = h_addr;
  assign launch_cs   = h_cs;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      held   <= 1'b0;
      h_cmd  <= '0;
      h_addr <= '0;
      h_cs   <= '0;
    end else begin
      // ── Release first, then capture. Written in this order so that a
      //    same-cycle take-and-accept is a clean handover rather than a
      //    dropped command: the slot frees and is immediately refilled.
      if (held && launch_taken) held <= 1'b0;

      if (ctrl_cmd_valid && ctrl_cmd_ready) begin
        held   <= 1'b1;
        h_cmd  <= ctrl_cmd;
        h_addr <= ctrl_addr;
        h_cs   <= ctrl_cs;
      end
    end
  end

endmodule

Simulating it. Hold phy_operational low and drive ctrl_cmd_valid: ctrl_cmd_ready stays low and nothing is accepted — the interface refuses traffic before it is usable. Raise phy_operational, and the first command is accepted and appears on launch_* the following cycle. Hold launch_taken low and offer a second command: ctrl_cmd_ready stays low, the held command is unchanged, and the controller must wait. §10's trace walks this.

Synthesis. One holding register of CMD_W + ADDR_W + CS_W bits plus a valid flag — for the defaults, thirty-one bits. Nothing here is a timing concern, and nothing here is technology-specific, which is precisely why it is the part a digital designer writes and the structures in §5 are not.

10. The Handover, Cycle by Cycle

EDUCATIONAL TIMING — cycle numbers show ordering only. No pin timing, no CA bus timing, and no relationship to any device parameter is implied.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  cyc  operational  ctrl_valid  ctrl_ready  accepted  held  launch  taken
  ───  ───────────  ──────────  ──────────  ────────  ────  ──────  ─────
   0        0            1           0         no      0      0       0
   1        0            1           0         no      0      0       0
   2        1            1           1        YES      0      0       0
   3        1            1           0         no      1      1       0
   4        1            1           0         no      1      1       0
   5        1            1           1        YES      1      1       1
   6        1            0           1         no      1      1       1
   7        1            0           1         no      0      0       0

Three cycles carry the lesson.

Cycles 0–1. The controller is offering a command and the PHY is refusing it. Reset was released before cycle 0 — rst_n is high throughout — but phy_operational is low, so nothing is accepted. Reset release and readiness are different events, separated here by two cycles and in a real system by a great deal more (Chapter 19.5).

Cycles 3–4. A command is held, offered on launch_*, and not yet taken. ctrl_cmd_ready is low, so the controller's next command waits. The held operands do not change — and must not, because the downstream path is reading them.

Cycle 5. launch_taken and a new acceptance occur in the same cycle. The slot is released and refilled on one edge. This is the case the always_ff ordering in §9 exists to make correct, and §11's P4 asserts it: a simultaneous take-and-accept must neither drop the incoming command nor extend the outgoing one.

11. What the Assertions Prove

phy_command_stage has its own clk and rst_n, so these may sit inside the module or in a bind unit.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ── P1. No acceptance before the interface is operational. The
//    property that separates reset release from readiness, which §12
//    lists as the module's most consequential misconception.
property p_no_accept_before_operational;
  @(posedge clk) disable iff (!rst_n)
    (ctrl_cmd_valid && ctrl_cmd_ready) |-> phy_operational;
endproperty
a_no_accept_before_operational: assert property (p_no_accept_before_operational);

// ── P2. A held command is immutable until it is taken. If the
//    operands change underneath a downstream path that is reading
//    them, the launched command is not the accepted one.
property p_held_command_stable;
  @(posedge clk) disable iff (!rst_n)
    (held && !launch_taken)
      |=> (held && $stable(launch_cmd) && $stable(launch_addr)
                && $stable(launch_cs));
endproperty
a_held_command_stable: assert property (p_held_command_stable);

// ── P3. Ownership is not silently overwritten: a new command may be
//    accepted only into a free slot, or into one being freed this
//    cycle. Catches the classic "accept whenever valid" bug, which
//    loses the held command without any error indication.
property p_no_overwrite;
  @(posedge clk) disable iff (!rst_n)
    (ctrl_cmd_valid && ctrl_cmd_ready) |-> (!held || launch_taken);
endproperty
a_no_overwrite: assert property (p_no_overwrite);

// ── P4. The simultaneous case of §10's cycle 5. A take and an accept
//    in one cycle must leave the stage held -- with the NEW command.
//    Written on the following cycle because that is when the effect of
//    both events is observable.
property p_simultaneous_take_and_accept;
  @(posedge clk) disable iff (!rst_n)
    (held && launch_taken && ctrl_cmd_valid && ctrl_cmd_ready)
      |=> held;
endproperty
a_simultaneous_take_and_accept: assert property (p_simultaneous_take_and_accept);

// ── P5. Readiness never depends on the offer. A ready that waits for
//    valid is the combinational loop Chapter 17.5 §2 forbids, and it
//    is easy to introduce while "optimising" the expression above.
property p_ready_independent_of_valid;
  @(posedge clk) disable iff (!rst_n)
    ctrl_cmd_ready == (phy_operational && (!held || launch_taken));
endproperty
a_ready_independent_of_valid: assert property (p_ready_independent_of_valid);

// ── Covers. Each names a case the properties are otherwise checking
//    in an empty space.
c_refused_before_ready: cover property (@(posedge clk) disable iff (!rst_n)
                          ctrl_cmd_valid && !phy_operational);
c_stalled_launch:       cover property (@(posedge clk) disable iff (!rst_n)
                          held && !launch_taken);
c_take_and_accept:      cover property (@(posedge clk) disable iff (!rst_n)
                          held && launch_taken && ctrl_cmd_valid && ctrl_cmd_ready);

What they prove. That the handover is a genuine ownership transfer: nothing is accepted before the interface can carry it, nothing held is mutated, nothing is overwritten, and the simultaneous case behaves.

What they do not prove — and the gap is the whole point of this module. Nothing here establishes that the command is legal; that is 13.1's and 17.1's contract, and a PHY cannot repair an illegal command. Nothing establishes that the command reaches the DRAM correctly — that depends on launch alignment (19.3), on the physical CA path, and on electrical margin (Module 22), none of which is in this model. And nothing establishes anything at all about timing at the pins: every cycle number in §10 is an ordering label.

Vacuity note. P4's antecedent requires four conditions simultaneously and a random testbench will produce it rarely; c_take_and_accept exists so that a passing P4 can be distinguished from an unexercised one. The same applies to P1 and c_refused_before_ready — if the stimulus never offers a command before readiness, P1 has checked nothing.

12. Corner Cases

SituationCorrect behaviourFailure if mishandled
ctrl_cmd_valid while phy_operational lowrefused; nothing accepteda command launched into an unusable interface
reset released, readiness not yet assertedstill refusedthe module's central misconception, in hardware
held and launch_taken lowoperands frozen; ready lowdownstream reads a mutating command
take and accept in one cycleslot refilled; held stays highthe incoming command is dropped, or the outgoing one repeats
launch_taken asserted while held lowignoreda phantom launch acknowledged
phy_operational drops while a command is heldheld command survives; no new acceptancea launch abandoned with no record
CS_W = 1legal — single chip selectzero-width vector
back-to-back accepts with immediate takesone command per cycle sustaineda needless bubble every other cycle
reset while heldslot cleareda stale command launched after reset release

The row about phy_operational dropping mid-flight deserves a note. This block keeps the held command and simply stops accepting new ones, which is the conservative choice. A real PHY that loses readiness mid-operation has a more serious problem than one command's fate, and what should happen is a system-level decision rather than a detail this block should invent.

13. DV — Checking a Contract, Not a Datapath

There is no data transformation here, so the independent model is not a datapath model. It is a queue of ownership events.

Maintain, independently of the RTL's held flag: a single-entry reference slot, filled on each observed ctrl_cmd_valid && ctrl_cmd_ready and emptied on each observed cmd_launch && launch_taken. Then assert three things the RTL never gets to state: the slot is never filled when already full, never emptied when already empty, and the operands launched are byte-identical to the operands accepted.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  COMMAND HANDOVER MISMATCH
    cycle                 : 41
    event                 : accept
    reference slot state  : FULL   (filled at cycle 38, not yet taken)
    launch_taken at 41    : 0
    RTL ctrl_cmd_ready    : 1      <- should be 0
    diagnosis  : the stage asserted ready while holding an untaken
                 command. The command accepted at 38 will be
                 overwritten and lost.
    caught by  : P3 (no overwrite)
    NOT caught by : any data comparison -- the launched command is a
                 perfectly well-formed command. It is simply not the
                 one the controller believes it issued.

The last two lines are the reason the checker tracks ownership rather than values. A lost command is not corrupt data; it is a command the DRAM never receives while the controller's model says it did — and the symptom appears later, as a bank whose state the controller has wrong.

Directed cases worth running: offer during reset; offer before readiness and confirm refusal; the take-and-accept collision of §10's cycle 5; a long stall with the controller holding valid; readiness dropping while held; and back-to-back sustained acceptance, which is the only case that exercises the ready expression's second term.

14. Debugging

Symptom: the interface works after a warm reset and fails after a cold boot. Layer E. The discriminator is what differs between the two paths: a warm reset typically leaves trained settings intact while a cold boot must establish them. If traffic is being accepted before calibration has completed, P1 is the property that would have caught it and phy_operational is the signal to inspect. Chapter 19.5 owns the lifecycle.

Symptom: commands appear to be lost — the controller's bank model disagrees with the device. Layer B. Compare the count of accepted handovers against the count of taken launches; §13's reference slot does this directly. An accept-while-held bug produces exactly this and produces no corrupt data anywhere.

Symptom: every command is late by one cycle, consistently. Not a bug in this block. Consistent, deterministic offset is the signature of launch alignment, which is Chapter 19.3's subject, and it is worth checking before suspecting anything physical.

Symptom: failures that correlate with data rate. Layers D, E or F, and §8 says the rate test cannot distinguish them. The next discriminator is which lanes — a single failing lane points at per-lane training or a board issue; all lanes failing together points at clocking or a common timing reference.

Symptom: one byte lane fails and the rest pass. Not a controller problem and almost never a scheduling problem, because the controller does not know lanes exist. Per-lane state lives in the PHY (19.4, 19.5) and per-lane physical differences live on the board (Module 22).

15. Misconceptions

“The controller and the PHY are the same block.” They are different design problems with different tooling — one is portable RTL, the other is technology-specific (§5). Clue: a block diagram with no interface between them, and an RTL model that claims to cover both.

“The PHY decides which DDR command to issue.” It launches what it is given. Module 17 decides. Consequence: a legality bug gets investigated in the wrong layer. Clue: a scheduling question raised against the PHY team.

“The PHY is just a serialiser.” Serialisation is one of four paths in §4, and the receive side needs gating, capture and trained delays that transmission does not. Clue: a PHY model with no receive-side state.

“The PHY is entirely analogue” / “the PHY is entirely RTL.” Both wrong, and in opposite directions. §5's table is the boundary: real PHYs are a mixture, which is why they are technology-specific. Clue: either a PHY treated as a black box no digital engineer can touch, or one assumed portable across processes.

“Ordinary fabric flops can implement a DDR interface.” §1's callout. Clue: always_ff @(posedge dqs).

“PHY ready means reset is deasserted.” §10's cycles 0–1 and P1. Consequence: traffic issued into an uncalibrated interface, which fails on cold boot and passes on warm. Clue: a design where phy_operational is wired to rst_n.

“The controller can compensate for a PHY timing error.” It can space commands differently; it cannot move a sampling point. Those are different mechanisms in different layers. Clue: a proposal to fix a capture problem by relaxing a controller timing parameter.

“The PHY can repair an illegal command.” It launches what it is given. Clue: an expectation that the PHY will enforce a timing rule the controller violated.

“Correct RTL guarantees a working DDR interface.” Everything in §5 is outside the RTL. A gearbox that reorders beats correctly says nothing about whether they were sampled correctly. Clue: sign-off based on simulation alone.

“Every DDR PHY has the same architecture.” §3's fourth column lists six functions whose ownership genuinely varies. Clue: an architecture diagram presented as the DDR PHY.

16. Interview Reasoning

“Why does a DDR system need a PHY at all?” Because a specific set of functions cannot be expressed in portable synchronous RTL — §5's table. The strong answer names two or three of them rather than saying “because it's fast”.

“What should the controller own and what should the PHY own?” Give the clear cases, then volunteer the implementation-dependent ones. Naming training ownership as varying is the discriminating detail.

“Why is the boundary implementation-dependent?” Because the functions are defined by what must happen, not by where it happens, and vendors partition them differently — particularly training and ODT control.

“What is the difference between ZQ calibration and PHY calibration?” §7. Different sides of the interface, different state, different invocation. Confusing them sends a debug effort to the wrong die.

“Your DDR interface works at a lower rate and fails at full rate. What does that tell you?” That layers A, B and C are largely exonerated, because digital ordering bugs are rate-independent. It does not identify which of capture, training or signal integrity is at fault — and saying so is the better answer.

“Why must PHY readiness be separate from reset release?” Because clocks must stabilise and calibration must complete before the interface can carry traffic. Conflating them produces a design that passes warm-reset testing and fails cold boot.

“What can you verify about a PHY in simulation, and what can you not?” Ordering, ownership, handshakes and framing — yes. Sampling position, margin and electrical behaviour — no. Being explicit about the second half is what separates a useful answer from a confident one.

17. Exercises

1. Classify each as controller, PHY, DRAM or implementation-dependent: refresh scheduling; strobe generation on a write; strobe generation on a read; deciding when ODT is applied; discovering a read delay value; transaction completion.

2. §3 marks six rows implementation-dependent. Pick the training row and describe two real partitions that would both be correct, and one consequence of each for the controller's interface.

3. Draw the write path from a controller-accepted transaction to the DQ pins, naming the chapter that owns each stage.

4. Do the same for the read path, and mark the one box this module does not open.

5. Construct a stimulus where phy_command_stage accepts a command and the controller's model and the DRAM's state permanently disagree. Which property catches it, and which does not?

6. ctrl_cmd_ready is phy_operational && (!held || launch_taken). Rewrite it to also require ctrl_cmd_valid and name the failure that introduces.

7. A colleague wires phy_operational to rst_n. Give the test that passes and the test that fails, and explain why that ordering is the common one.

8. Explain why an assertion proving beat order is correct says nothing about whether the eye was sampled correctly. Name the module that owns the second claim.

18. Where This Goes

The boundary is drawn and the paths are named. Four of the boxes in §4's diagram are opened by the rest of this module.

Chapter 19.2 opens the width-versus-rate conversion on both the write and read paths — why it exists, what ordering it must preserve, and why a correct gearbox is a genuine digital component with genuine bugs. 19.3 opens launch alignment: the relationship the PHY must hold between a command and the data that belongs to it. 19.4 opens strobe generation and the receive gate — the PHY's answer to a strobe that is not always driven. 19.5 opens the lifecycle that produced phy_operational, and the settings every other chapter has been consuming as opaque values.

The box marked CAPTURE stays closed until Module 20. That is not an omission — it is the next module, and this one exists to make its boundary legible.

Continue learning

Standards & specifications

Governing standard
JEDEC JESD79 (DDR SDRAM)(opens JEDEC Solid State Technology Association in a new tab)

Defines the DDR SDRAM device itself — signals, command encoding, mode registers, timing parameters and the initialisation sequence — one document per generation. Memory-controller microarchitecture, address-mapping policy, PHY training algorithms and board-level design are not specified by it.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the DDR curriculum.