Skip to content
VLSI Mentor

DDR · Module 6

ODT — On-Die Termination Control

ODT is a control input selecting whether a device presents termination. Which device should terminate depends on which way data is flowing — and the one rule that never varies is that a driver must not terminate its own output.

Chapter 4.3 §3 established why on-die termination exists: a memory bus carries several attached devices, every attachment reflects, and at rising rates reflections no longer settle between transfers. Moving the terminating resistance onto the die put it at the receiver — and, critically, made it controllable.

This chapter is about the signal that controls it.

The distinction in the title is the chapter's first point. ODT is not termination. It is an input that selects whether a device's termination is presented. The resistance, its value, its calibration and its electrical effect are analog and belong to Modules 19 to 22. What belongs here is the control contract: who asserts it, for which device, during which operation, and what the controller must decide.

And the decision is less obvious than it looks, because which device should terminate depends on which way the data is flowing.

1. A Control Signal, Not a Resistor

It is worth being precise about the division, because the chapter's boundaries depend on it.

Inside the DRAM device there is a termination network — transistors configured to present a resistance to the data lines, with the value selected by mode-register configuration and, from DDR3 onward, calibrated against an external precision reference.

The ODT input decides whether that network is presented. Asserted, the device terminates; deasserted, it does not.

So ODT is a one-bit control over an analog resource, and the split is exactly the controller-versus-PHY division Chapter 6.1 §8 introduced: the controller decides whether, and the device's analog circuitry realises what.

Everything analog is out of scope here and stays out. No resistance values, no impedance matching, no reflection behaviour, no signal-integrity analysis. §4's RTL models the policy — which ranks should be told to terminate for a given access — and models no termination whatsoever.

2. Direction Decides

Here is the part that is genuinely non-obvious.

Termination is wanted at the receiving end. Its job is to absorb the signal so it does not reflect, and the place that matters is where the signal arrives.

But on a bidirectional bus, the receiving end changes.

On a write, the controller drives and the DRAM receives. The termination that matters is at the DRAM end.

On a read, the DRAM drives and the controller receives. The termination that matters is at the controller end — in the PHY, which has its own termination and is not controlled by this signal at all.

On a write the controller drives the data bus and the DRAM receives, so termination is wanted at the DRAM end and the target rank is told to terminate. On a read the DRAM drives and the controller receives, so the termination that matters is in the controller's own PHY, and the driving rank must not terminate its own output. Non-target ranks may terminate in either direction depending on the system's topology.Writecontroller drivesDRAM receivesterminate at DRAMTarget ODT assertedcontroller decidesReadDRAM drivesController receivesPHY terminatesDriver never terminatesthe invariant rulesosodirection12
Figure 1 — the receiving end changes with direction, and a driver must not terminate itself.

One rule never varies, across every generation and every topology:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   A DEVICE THAT IS DRIVING MUST NOT TERMINATE ITS OWN OUTPUT.

Why it is invariant: a driver terminating its own output is loading itself, fighting its own drive strength, and wasting energy doing it. There is no configuration in which it is correct.

Everything else is policy. Whether non-target ranks terminate, and with what strength, depends on how many ranks are present, the module form and the topology — which is why the tables are device-specific and why §4's model makes them parameters rather than constants.

3. It Is Per-Rank, and It Is the Controller's Job

Chapter 4.3 §3 identified the consequence that matters most: making termination controllable made it the controller's responsibility.

ODT is per rank. Each rank has its own ODT input, so the controller decides independently for each one, for each access.

And the decision must be made in advance. Chapter 6.5 §4 established that a column command commits the data bus to a transfer beginning a fixed interval later, and the termination must be correct when the data arrives, not when the command was issued. So ODT assertion is scheduled the same way the data window is — which makes it another thing the controller must know a full latency interval ahead.

This is where Chapter 4.3's "new failure mode" lives. A wrong ODT policy produces a system that is functionally correct and electrically marginal: every bit arrives, every command works, and the margin is smaller than it should be. Nothing fails a functional test. The symptom is Chapter 4.2 §10's hardest class — works at reduced rate, marginal at full rate, no error anywhere.

4. RTL — Termination Policy

Engineering problem

For each access, decide which ranks should be told to terminate, given the access's direction and target. Enforce the one invariant rule, and make the policy parameters explicit so a change of topology is a parameter change rather than a rewrite.

Classification

SYNTHESIZABLE RTL — a policy model.

What it represents: the per-rank, per-direction assertion decision, and the driver-must-not-terminate invariant.

What it explicitly does not represent, and this is most of the subject: no termination. No resistance, no impedance, no reflections, no signal integrity, no calibration, no mode-register values, no strength selection. The RTL decides a bit; the analog network the bit controls is entirely outside anything RTL can express, and Modules 19 to 22 own it.

It also does not encode any device's actual policy table. The parameters below are the shape of a policy, and real tables are device- and topology-specific. Do not use these defaults for anything.

Interface contract

access_valid, access_rank and access_is_write describe the committed transfer. odt is the per-rank assertion bundle. odt_illegal reports the invariant being violated.

State

None for the decision — it is a function of the current access. Saturating counters for telemetry.

Combinational behaviour

The whole policy.

Sequential behaviour

Telemetry only.

How to simulate

vlog odt_policy.sv tb_odt_policy.sv then vsim -c tb_odt_policy -do "run -all".

Expected result: on a write the target rank's ODT asserts; on a read it does not; non-target behaviour follows the parameters; and odt_illegal never asserts for any legal parameterisation.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// ODT POLICY.  Classification: SYNTHESIZABLE RTL -- a POLICY model.
//
// Decides which ranks are TOLD to terminate for a given access. It is a
// one-bit-per-rank decision over an analog resource.
//
// WHAT THIS DOES NOT REPRESENT -- WHICH IS MOST OF THE SUBJECT:
// no termination. No resistance, no impedance, no reflections, no signal
// integrity, no ZQ calibration, no mode-register strength selection. The
// RTL decides a BIT; the analog network that bit controls is entirely
// outside what RTL can express (Modules 19-22).
//
// IT ALSO ENCODES NO DEVICE'S ACTUAL POLICY TABLE. The parameters below
// are the SHAPE of a policy. Real tables depend on rank count, module form,
// topology and speed grade, and are specified per device. DO NOT USE THESE
// DEFAULTS FOR ANYTHING.
//
// THE ONE INVARIANT, true in every generation and topology:
//   A DEVICE THAT IS DRIVING MUST NOT TERMINATE ITS OWN OUTPUT.
// A driver terminating itself loads itself, fights its own drive strength,
// and wastes energy doing it. There is no configuration where it is right.
//
// GENERATION: DDR2, DDR3, DDR4 have a dedicated ODT pin. DDR5 does not --
// termination control moved into command encoding alongside CS_n.
// ─────────────────────────────────────────────────────────────────────────
module odt_policy #(
  parameter int NUM_RANKS = 2,
  // POLICY PARAMETERS -- the shape, not any device's table.
  // Target rank terminates on a write: it is the receiver.
  parameter bit TERM_TARGET_ON_WRITE = 1'b1,
  // Non-target ranks terminate on a write. Topology-dependent: helpful in
  // some arrangements, wasteful in others.
  parameter bit TERM_OTHERS_ON_WRITE = 1'b0,
  // Non-target ranks terminate on a read, while the target drives.
  parameter bit TERM_OTHERS_ON_READ  = 1'b1,
  parameter int ACC_W = 16,
  parameter int RK_W  = (NUM_RANKS <= 1) ? 1 : $clog2(NUM_RANKS)
) (
  input  logic                 clk,
  input  logic                 rst_n,

  // Describes the COMMITTED transfer, not the command. Chapter 6.5
  // established that direction is fixed at command time and the data
  // arrives a fixed interval later -- termination must be correct when the
  // DATA arrives, so this is scheduled, not reactive.
  input  logic                 access_valid,
  input  logic [RK_W-1:0]      access_rank,
  input  logic                 access_is_write,

  output logic [NUM_RANKS-1:0] odt,
  // The invariant violated: a rank that is driving has been told to
  // terminate. Should be impossible by construction below; asserted anyway
  // because the rule matters more than this implementation of it.
  output logic                 odt_illegal,
  output logic                 rank_invalid,

  output logic [ACC_W-1:0]     cnt_write_term,
  output logic [ACC_W-1:0]     cnt_read_term
);

  // ── COMPILE-TIME legality.
  if (NUM_RANKS < 1) begin : g_nr
    initial $fatal(1, "odt_policy: NUM_RANKS must be >= 1");
  end

  // ── Range check, using Chapter 5.1's generate pattern rather than a
  //    width cast that truncates for power-of-two counts.
  logic rank_bad;
  if (NUM_RANKS >= (1 << RK_W)) begin : g_rk_full
    assign rank_bad = 1'b0;
  end else begin : g_rk_check
    assign rank_bad = ({1'b0, access_rank} >= (RK_W+1)'(NUM_RANKS));
  end
  assign rank_invalid = access_valid && rank_bad;

  logic active;
  assign active = access_valid && !rank_bad;

  // ── The policy.
  //
  //    THE READ CASE IS THE ONE TO STUDY. On a read the target rank is
  //    DRIVING, so it is never told to terminate -- that is the invariant,
  //    and it is enforced structurally here by the `r != access_rank` test
  //    rather than by a check applied afterwards.
  always_comb begin
    odt = '0;
    if (active) begin
      for (int r = 0; r < NUM_RANKS; r++) begin
        if (RK_W'(r) == access_rank) begin
          // Target rank: terminates on a write (it receives), never on a
          // read (it drives).
          odt[r] = access_is_write && TERM_TARGET_ON_WRITE;
        end else begin
          // Non-target ranks: topology-dependent either way.
          odt[r] = access_is_write ? TERM_OTHERS_ON_WRITE
                                   : TERM_OTHERS_ON_READ;
        end
      end
    end
  end

  // ── The invariant, checked rather than assumed. On a read the target
  //    drives; if its ODT is asserted, the policy is wrong regardless of
  //    how it was derived.
  assign odt_illegal = active && !access_is_write && odt[access_rank];

  logic [ACC_W:0] w_sum, r_sum;
  always_comb begin
    w_sum = {1'b0, cnt_write_term} + (ACC_W+1)'(1);
    r_sum = {1'b0, cnt_read_term}  + (ACC_W+1)'(1);
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      cnt_write_term <= '0;
      cnt_read_term  <= '0;
    end else if (active && (odt != '0)) begin
      // Termination costs energy whenever it is presented, so counting how
      // often it is asserted is a real power metric -- and a policy that
      // terminates far more often than the traffic warrants is a finding.
      if (access_is_write) begin
        cnt_write_term <= w_sum[ACC_W] ? {ACC_W{1'b1}} : w_sum[ACC_W-1:0];
      end else begin
        cnt_read_term <= r_sum[ACC_W] ? {ACC_W{1'b1}} : r_sum[ACC_W-1:0];
      end
    end
  end

endmodule

Cycle-by-cycle example

NUM_RANKS = 2, defaults:

CycleAccessodt[0]odt[1]Why
0write rank 010target receives; others off by parameter
1read rank 001target drives — must not terminate
2write rank 101target receives
3read rank 110target drives; other terminates
4none00no committed transfer

Cycles 1 and 3 are the chapter. The rank being accessed has its ODT off, and the rank not being accessed has it on. That inversion is counter-intuitive and correct: the accessed rank is driving, and a driver must not terminate its own output.

An engineer debugging this who assumes "ODT follows the access" will read cycle 3 as a bug. It is the policy working.

Waveform expectation

§5. Watch the target rank's ODT invert between writes and reads.

Synthesis implication

A decoder and some gates — negligible. In a real controller the decision is computed alongside the data-window scheduling of Chapter 6.5 §4, because the assertion must be timed to the data rather than to the command, and that timing is the genuinely hard part. This block decides what; when is a scheduling problem this model does not address.

Corner cases

NUM_RANKS == 1 makes the non-target branch unreachable, so the policy reduces to "terminate on writes, not on reads" — which is correct for a single-rank system and is worth checking because the parameter sweep is degenerate there. An invalid rank produces all ODT deasserted, which is the safe failure: no termination is electrically suboptimal, while terminating a driving rank is actively wrong. TERM_OTHERS_ON_READ = 0 with one rank produces no termination on reads at all, which some topologies genuinely want.

Debugging clues

If odt_illegal ever asserts, the target-versus-other branch is inverted — check the RK_W'(r) == access_rank comparison. If termination follows the access rank on reads, the same inversion is present in the opposite direction and the system will be electrically marginal with no functional symptom. If ODT is asserted on cycles with no transfer, active is not gating the decode. If the counters show termination asserted on nearly every cycle, the policy is being driven by commands rather than by committed transfers — a common integration error that leaves termination on far longer than needed and costs energy continuously.

Limitations

No termination modelled at all, as the header says at length. No timing — when ODT should assert and deassert relative to the data window is a real and difficult scheduling problem this block does not touch. No strength selection, no calibration, no mode registers. No DDR5 behaviour, where there is no pin. And the policy parameters are a shape, not a device's table.

5. The Inversion, in Cycles

odt_policy — termination assertion inverting with direction

10 cycles
Ten cycles with two ranks. On writes the targeted rank has its on-die termination asserted because it is receiving. On reads the targeted rank has its termination deasserted because it is driving, and the non-targeted rank terminates instead. Cycles with no committed transfer assert no termination at all.rank 0 accessedrank 0 accessedrank 1 accessedrank 1 accessedwrite: target terminateswrite: target terminatesread: target does NOTread: target does NOTother rank terminatesother rank terminatesCKaccess_validaccess_rank00--11--0--1--is_writeodt[0]odt[1]odt_illegalcnt_read_term0011122333t0t1t2t3t4t5t6t7t8t9
Figure 2 — on reads the accessed rank's termination is off; the other rank's is on.

Compare cycles 0 and 1. Both target rank 0. On the write, odt[0] is asserted. On the read, odt[0] is deasserted and odt[1] is asserted instead — the rank not being accessed is the one terminating.

This is the single most confusing thing about ODT, and it is entirely explained by §2: the accessed rank is driving on a read, and a driver must not terminate its own output.

odt_illegal is flat at zero throughout, which is what a correct policy looks like. A trace where it ever rises is a policy inversion, and the symptom on real hardware would be marginal signal quality with no functional failure at all.

Cycles 2, 5, 7 and 9 have no committed transfer and assert no termination. Termination costs energy whenever presented, so leaving it on between transfers is a real and measurable waste — and §4's counters exist to make it visible.

Representative educational cycles. Real ODT assertion is timed relative to the data window with device-specific lead and lag, which this figure does not model.

6. Three Assertions Worth Writing

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// VERIFICATION-ONLY, inside odt_policy.

// P1 -- THE INVARIANT. A driving rank never terminates its own output.
// True in every generation and every topology, unlike everything else in
// this block, which is policy.
property p_driver_never_terminates;
  @(posedge clk) disable iff (!rst_n)
    (access_valid && !rank_invalid && !access_is_write)
      |-> !odt[access_rank];
endproperty
assert property (p_driver_never_terminates);

// P2 -- and the derived flag agrees with the condition, so a status output
// cannot disagree with the thing it reports.
property p_illegal_flag_exact;
  @(posedge clk) disable iff (!rst_n)
    odt_illegal == (access_valid && !rank_invalid
                    && !access_is_write && odt[access_rank]);
endproperty
assert property (p_illegal_flag_exact);

// P3 -- no termination without a committed transfer. Termination costs
// energy while presented, so asserting it on idle events is not merely
// untidy -- it is continuous waste, and it is a common integration error
// when ODT is driven from commands rather than from committed transfers.
property p_no_odt_when_idle;
  @(posedge clk) disable iff (!rst_n)
    !access_valid |-> (odt == '0);
endproperty
assert property (p_no_odt_when_idle);

// P4 -- the target terminates on a write, when the policy says so. The
// companion that stops P1 and P3 being satisfied by a design that never
// asserts anything.
property p_target_terminates_on_write;
  @(posedge clk) disable iff (!rst_n)
    (access_valid && !rank_invalid && access_is_write
     && TERM_TARGET_ON_WRITE) |-> odt[access_rank];
endproperty
assert property (p_target_terminates_on_write);

P1 is the only property here that is universally true, and that is worth stating explicitly: everything else in this block is policy and could legitimately differ between systems. A verification engineer working on a real controller should expect to parameterise most of these checks against the system's actual ODT table — and should refuse to parameterise P1, because no table makes a driver terminating itself correct.

Knowing which of your properties are invariants and which are configuration is a skill worth naming. A property list that mixes them without distinction gets weakened wholesale the first time a configuration changes, taking the invariants with it.

What none of them prove. Nothing about termination working — no resistance, no impedance match, no reflection behaviour, and no digital assertion in any simulation reaches any of it. Nothing about when ODT is asserted relative to the data window, which is the genuinely difficult part. Nothing about calibration, which is DDR3's ZQ mechanism. A green regression on this block says the policy logic is self-consistent and says nothing whatsoever about whether the bus is well terminated.

7. What DDR5 Did

DDR5 removed the dedicated ODT pin. Termination control moved into command encoding alongside CS_n — the same mechanism that absorbed CKE.

Chapter 6.6 §7 predicted this, and the prediction is worth checking against the criteria it set out.

Is the function per-device? Yes — termination applies to a specific rank, and CS_n is already the per-device selector.

Does its state change infrequently relative to the command rate? Mostly. A termination setting persists across a transfer and changes at direction and target changes, not on every beat. It can afford a command slot.

Could it have been encoded earlier? In principle. What changed is that the pressure to remove pins grew while the cost of encoding fell — and Chapter 4.6 established that DDR5's design repeatedly converts dedicated mechanisms into encoded ones.

The architectural consequence is the same as CKE's and worth restating. In DDR4 a controller asserts ODT on a wire, independently of its command stream. In DDR5 it issues a command — scheduled, occupying a command-bus event, competing with reads and writes for bandwidth.

And ODT is asserted more often than power-state transitions are, which makes the bandwidth consideration more real here than it was for CKE. A controller ported from DDR4 without budgeting command slots for termination control will under-provision its command scheduling, and the symptom is reduced achievable throughput with nothing malfunctioning.

8. Common Misconceptions

"ODT asserted means the device is terminated, so assert it on the device you are accessing." Wrong model: termination follows the access. Why it is tempting: it is the obvious reading of a per-rank control, and it is correct for writes. Consequence: on reads it tells the driving rank to terminate its own output — which loads the driver, fights its drive strength, wastes energy, and produces worse signal quality than no termination at all. Nothing fails functionally, so the fault survives every functional test and appears as marginality at rate. Correct model: termination is wanted at the receiving end, and the receiving end changes with direction. On a write the DRAM receives, so the target terminates. On a read the DRAM drives, so the target must not — and the controller's own PHY provides the termination that matters. Prevention: for any access, ask which end is receiving. That is where termination belongs.

"ODT is the termination." Wrong model: the signal and the resistance are the same thing. Why it is tempting: the name is "on-die termination" and the signal is the only part visible from the digital side. Consequence: expecting RTL or digital simulation to say something about termination quality, and conflating "ODT is asserted correctly" with "the bus is well terminated". They are unrelated claims — the first is policy logic and the second depends on resistance values, calibration and topology. Correct model: ODT is a one-bit control over an analog network whose value is set by mode registers and, from DDR3, calibrated against an external reference. The controller decides whether; the device's analog circuitry realises what. Prevention: ask what units the property has. Assertion is a bit; termination is ohms.

"DDR2 and DDR3 ODT are equivalent because both have the pin." Wrong model: the presence of the signal implies equivalent capability. Why it is tempting: the pin and its control semantics genuinely are similar. Consequence: assuming a DDR2 system's realised termination matches its selected value. It does not — DDR2 has no calibration mechanism, so the on-die resistance drifts with process, voltage and temperature. Chapter 4.4 §1 established that DDR3 added ZQ calibration against an external precision reference precisely because that drift stopped fitting in the margin. Correct model: selectable is not calibrated. DDR2 offers values; DDR3 onward makes the realised value traceable to an external reference. Prevention: ask what the on-die value is referenced to. If the answer is "the process", it is not calibrated.

"DDR5 dropped ODT." Wrong model: the capability was removed. Why it is tempting: the pin is genuinely gone from the signal list. Consequence: a design that makes no provision for termination control at all, and — more subtly — a controller that budgets no command bandwidth for it. Termination is more necessary at DDR5 rates, not less. Correct model: DDR5 dropped the dedicated pin. Termination control moved into command encoding alongside CS_n, exactly as CKE did. The function is unchanged and is now a scheduled command competing for bus events. Prevention: distinguish "the pin is gone" from "the function is gone". In this module that distinction has now applied to CKE, to the RAS#/CAS#/WE# trio, and to ODT.

9. Debugging — Functionally Perfect, Electrically Marginal

Symptom. A memory interface passes every functional test. At full rate it shows occasional errors; at reduced rate it is clean. No pattern in the data, no correlation with addresses, no errors reported by any integrity mechanism.

This is the hardest symptom class in the interface, and Chapter 4.2 §10 established the discipline for it: decide which layer owns the symptom before engaging with the analog layer, because that is where the expensive equipment and the long weeks are.

Mechanism 1 — ODT policy inverted on reads. Inspect: whether the accessed rank's ODT is asserted during reads. Expected evidence: the target rank terminating while driving. Discriminator: check ODT against direction for the accessed rank. This is first because it is a configuration read costing nothing, because it is the counter-intuitive case engineers get wrong, and because it produces exactly this symptom — a driver fighting its own termination degrades margin without breaking function.

Mechanism 2 — ODT policy wrong for the populated configuration. Inspect: the policy against the actual rank count and module form. Expected evidence: a policy derived for a different population — often a single-rank policy applied to a dual-rank system. Discriminator: does the symptom depend on population? Chapter 4.3 §10's first mechanism, and the discriminator is the same: vary what is populated.

Mechanism 3 — ODT timing, not ODT policy. Inspect: when ODT asserts and deasserts relative to the data window. Expected evidence: correct per-rank assertion that arrives too late or ends too early, so part of the burst is unterminated. Discriminator: is the corruption positional within a burst? Chapter 5.4 §10's lesson applies — head-corrupt or tail-corrupt points at a window boundary, while uniform corruption points at policy. Policy and timing are different faults and this question separates them.

Mechanism 4 — termination is uncalibrated or calibration failed. Inspect: whether ZQ calibration ran and succeeded, and whether the symptom moves with temperature. Expected evidence: margin varying with operating conditions. Discriminator: does it track temperature? On DDR2 this is expected behaviour rather than a fault, because there is no calibration; on DDR3 and later it means calibration was skipped, failed, or is not being maintained — Chapter 4.4 §11's territory.

Mechanism 5 — not termination at all. Inspect: whether the errors are on the data path or the command path. Expected evidence: wrong accesses rather than wrong data. Discriminator: is data wrong, or is the access wrong? Chapter 6.1 §10's discrimination — a command-path margin problem has an entirely different investigation and a much larger blast radius.

Discrimination, cheapest first. Read the ODT policy against direction for the accessed rank — a configuration read, and it resolves the most likely cause outright. Then vary the population. Then ask whether corruption is positional within a burst, which splits timing from policy. Then check calibration and temperature.

The reasoning lesson. A fault that degrades margin without breaking function cannot be found by any functional test, so the entire test suite passing is not evidence of anything — and the instinct to trust a green regression is exactly what makes this class expensive. The productive move is to stop looking for a failure and start looking for a configuration that is wrong in a way that would not fail. ODT policy is the canonical example: every bit arrives, every command works, and a driver is quietly fighting its own termination. Ask what could be misconfigured such that nothing would break — it is a short list, and it is where these faults live.

10. Interview Reasoning

"What does the ODT signal actually control?" Whether a device presents its on-die termination network to the data lines. It is a one-bit control over an analog resource: the resistance value is set by mode-register configuration and, from DDR3 onward, calibrated against an external precision reference, while the ODT input simply decides whether that network is connected. So it sits exactly on the controller-versus-PHY boundary — the controller decides whether to terminate, and the device's analog circuitry realises what the termination is. Nothing about termination quality is visible from the digital side.

"Which rank should terminate during a read?" Not the one being read. That rank is driving, and a driver must not terminate its own output — it would load itself, fight its own drive strength and waste energy doing it. That rule is invariant across every generation and topology. Termination is wanted at the receiving end, and on a read the receiver is the controller, whose PHY has its own termination that this signal does not control. Non-target ranks may be told to terminate depending on the topology, which is why the target rank's ODT is often deasserted while another rank's is asserted — a pattern that looks like a bug and is the policy working correctly.

"Why is a wrong ODT policy hard to find?" Because it produces a system that is functionally perfect and electrically marginal. Every bit arrives, every command works, and the margin is smaller than it should be — so no functional test fails, and the whole regression suite passing is not evidence of anything. The symptom is the hardest class in the interface: clean at reduced rate, occasional errors at full rate, no pattern in the data and no integrity mechanism reporting. The productive approach is to stop looking for a failure and start looking for a configuration that is wrong in a way that would not break anything, and ODT policy on reads is the canonical entry on that list.

"Do DDR2 and DDR3 ODT differ?" In an important way. Both have a dedicated ODT pin with similar control semantics, but DDR2 has no mechanism to calibrate the on-die resistance against a precision reference, so what the device actually presents drifts with process, voltage and temperature while the selected value stays the same. DDR3 added ZQ calibration against an external reference resistor precisely because that drift stopped fitting inside the timing margin as rates rose. So "selectable" and "calibrated" are different claims, and assuming a DDR2 system realises its selected termination value is a mistake.

"DDR5 has no ODT pin. What replaced it, and what does that cost a controller?" Termination control moved into command encoding alongside CS_n, the same way CKE's power-down control did — both are per-device functions, and CS_n was already the per-device selector. The cost is architectural: in DDR4 the controller asserts ODT on a wire independently of its command stream, while in DDR5 it issues a command that is scheduled, occupies a command-bus event, and competes with reads and writes for bandwidth. That matters more for ODT than it did for CKE because termination changes far more often than power states do, so a controller ported without budgeting command slots for it will under-provision command scheduling, and the symptom is reduced achievable throughput with nothing malfunctioning.

11. Engineering Exercise

Educational policy parameters; no device's ODT table is implied.

1. A two-rank system reads from rank 0. Which rank's ODT should be asserted, and why does the answer feel wrong? Rank 1's, potentially — and not rank 0's. It feels wrong because rank 0 is the one being accessed. Rank 0 is driving, and a driver must not terminate its own output; termination belongs at the receiving end, which is the controller.

2. A controller asserts ODT on the accessed rank for both reads and writes. What will testing show? Nothing. Every functional test passes — data is correct, commands work, no errors. The fault is a margin degradation on reads, where the driving rank fights its own termination. It will appear as marginality at full rate, long after the functional suite has signed off.

3. §4's model asserts no ODT when access_valid is low. Why does that matter beyond tidiness? Termination dissipates energy whenever it is presented. Leaving it asserted between transfers is continuous waste, and it is a common integration error when ODT is driven from commands rather than from committed transfers — the assertion then persists far longer than the data window it exists to serve.

4. Which of §6's properties would you expect to parameterise for a real system, and which would you refuse to? P3 and P4 are policy and would legitimately differ with topology — a system might terminate non-target ranks differently, or not at all. P1 is an invariant and must never be parameterised: no ODT table makes a driver terminating itself correct. Knowing which of your properties are invariants matters, because a property list that mixes them gets weakened wholesale at the first configuration change.

5. A DDR2 system's termination was selected correctly and the interface is still marginal when hot. Fault or expected? Expected, to a degree. DDR2 has no ODT calibration, so the realised resistance drifts with temperature while the selected value does not change. The same symptom on DDR3 or later means calibration was skipped, failed, or is not being maintained — which is a fault, because the mechanism exists.

6. Estimate the command-bandwidth consequence of DDR5 encoding ODT rather than wiring it. Termination changes at direction changes and target changes — far more often than power-state transitions. Each change now consumes a command-bus event that a DDR4 controller got for free on a dedicated wire. A controller that budgets command slots only for reads, writes, activates and refresh will find its achievable throughput lower than projected, with no malfunction to point at — and the fix is scheduling capacity, not signal integrity.

12. Summary

ODT is a control signal, not termination. It is one bit per rank selecting whether a device presents its on-die termination network. The controller decides whether; the device's analog circuitry realises what — and the value, its calibration and its electrical effect are entirely outside anything RTL or digital simulation can express.

Direction decides who should terminate, because termination is wanted at the receiving end and a bidirectional bus changes ends. On a write the DRAM receives, so the target rank terminates. On a read the DRAM drives, so the target must not — the controller's own PHY provides the termination that matters, and non-target ranks may terminate depending on topology.

One rule never varies: a device that is driving must not terminate its own output. A driver terminating itself loads itself, fights its own drive strength and wastes energy. Everything else is policy, and real policy tables are device- and topology-specific.

The consequence is that the accessed rank's ODT is often deasserted while another rank's is asserted — which looks like a bug and is the policy working.

And a wrong policy produces the hardest fault class available: functionally perfect, electrically marginal. No functional test fails, so a green regression is not evidence. The productive move is to look for a configuration that is wrong in a way that would not break anything.

Termination must be correct when the data arrives, not when the command was issued, so ODT assertion is scheduled alongside the data window — another thing the controller must know a latency interval ahead.

DDR2 has ODT without calibration; DDR3 added ZQ calibration against an external reference because the drift stopped fitting the margin. Selectable is not calibrated.

And DDR5 removed the pin, moving termination control into command encoding alongside CS_n — the same mechanism that absorbed CKE and, before it, the RAS#/CAS#/WE# trio. The function is unchanged; it is now a scheduled command competing for bus events, and because termination changes far more often than power states do, the command-bandwidth cost is real.

13. What Comes Next

Chapter 6.8 takes a signal at the opposite end of the spectrum — one that could not be encoded, and never will be.

RESET# must work when the device's state is unknown, when the command path cannot be trusted, and potentially when no clock is running. A signal that establishes the conditions under which commands are meaningful cannot itself be a command — which is Chapter 6.1's thesis stated as a constraint rather than an observation.

It is also the module's clearest example of a discipline every synchronous designer needs: asynchronous assertion with synchronous release, and why that asymmetry is not optional.

Return to DDR2 for why on-die termination exists at all, DDR3 for the calibration DDR2 lacked, or Ranks for the shared bus termination protects. Module 22 owns signal integrity. The full path is on the DDR tutorials index.

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.