Skip to content
VLSI Mentor

DDR · Module 2

The Refresh Requirement

Leakage produces a rule about the passage of time rather than about any operation. What the maintenance operation actually does, why it costs device availability, and how a digital design tracks a deadline, arbitrates it against traffic, and proves it never silently drops the obligation.

Chapter 2.2 derived a rule rather than asserting one. Charge on a passively stored node leaks through paths that cannot be closed, nothing drives the node to contest the loss, and what fails is not a flipped bit but the margin — the separation between the two states that the sensing decision depends on. The repair is therefore to re-establish the state at full strength, and it has to happen before the margin is gone.

That gives an obligation with an unusual shape:

Every location must have its state re-established at full strength within a bounded interval, or the data it holds can no longer be trusted.

This chapter is about what a system has to build to honour it. The central question:

A physical certainty has produced a requirement about the passage of time rather than about any operation. What does a digital design have to contain in order to meet a deadline — and what does meeting it cost?

Three answers, and they are the chapter. It costs device availability, because maintenance uses the same structures that serve requests. It requires logic that tracks time and can make requesters wait, because nothing else in the system knows when the deadline is approaching. And it turns an ordinary-looking design into one with a correctness property that no transaction-level check will ever detect — which is why the assertions in §9 matter more than their size suggests.

1. What the Maintenance Operation Actually Does

Before building anything, be precise about the work, because the work turns out to be something already familiar.

To re-establish a location's state you must first know what that state is. Chapter 2.1 established that nothing in the cell can tell you: the cell holds an electrical condition, and a digital value only exists once circuitry has decided. So the maintenance operation must:

  1. Connect the cell to the sensing circuitry, while the margin is still large enough for the decision to be reliable.
  2. Let the sensing circuitry resolve which of the two states it is in.
  3. Drive the resolved state back into the cell at full strength, restoring the separation that leakage had narrowed.

Read that list again and notice what it is. Steps 1 to 3 are not a special maintenance mechanism — they are what reading a DRAM location already involves. Chapter 2.5 shows why a read must connect and resolve, and 2.6 shows why it must drive the state back. Maintenance uses that same machinery.

So refresh is not a separate engine. It is the ordinary access mechanism, initiated deliberately, on locations nobody asked for, and performed for its side effect rather than for its data. The data it recovers is discarded; the point was the restoration.

Two immediate consequences, and both matter for the rest of the chapter.

It cannot be cheap, because it is a real access. Whatever an access costs the device — in occupied structures and in elapsed time — maintenance costs the same. There is no lightweight version.

It is inherently coarse. The access mechanism operates on a whole row of cells at once, for reasons 2.5 derives from the physics and Module 3 develops structurally. That is fortunate: it means one operation maintains many cells, which is the only reason the obligation is affordable at all. A per-cell maintenance requirement would be unmeetable.

2. Why It Costs Availability

The cost is not incidental, and it follows from §1 without any new assumptions.

Maintenance is an access. An access occupies the structures that serve requests — the shared sensing circuitry, the wiring, the device's control. While those structures are engaged in maintaining a row nobody asked about, they are not available to serve a request that a processor is waiting on.

So the device is periodically unavailable, and the unavailability is not request-driven. That last clause is what makes it architecturally distinctive. Every other source of delay in a memory system is caused by traffic: a queue is full because requests filled it, a row change is needed because a request wanted a different row. Maintenance delay is caused by the clock. It happens whether the system is busy or idle, and it cannot be avoided by asking for less.

Three practical consequences worth stating explicitly, because each is a place designs go wrong:

Any latency or bandwidth budget needs a term for it. A model in which the device is always available is not modelling DRAM — the point Chapter 1.4 §10 made and Chapter 1.8 turned into a variable. The term is small in proportion but it lands as occasional long stalls rather than as uniform slowness, so it shows up in the latency tail rather than the average.

Latency-sensitive designs feel it disproportionately. A workload that tolerates variable latency absorbs maintenance easily. A design with a hard deadline of its own — a real-time engine, an isochronous stream — can be broken by a rare stall that the average never reveals. This is why bounded-latency memory systems are hard, and it is a genuine reason Module 15's scheduling latitude exists.

And the obligation cannot be traded against performance. Deferring maintenance recovers availability, which makes it a tempting optimisation, and it is the one optimisation that is not available: past the deadline, data is lost. When to do the work is an engineering decision; whether to do it is not. Chapter 2.2 §11's exercise is that mistake in its natural habitat.

3. The Handoff, in Sequence

The obligation now has to become structure. Here is the interaction it implies, before any code.

A deadline timer signals that maintenance is due. The arbiter holds the requester, then starts maintenance on the device. The device reports completion, the arbiter clears the deadline in the timer, and the requester is released.Deadline timerArbiterDeviceRequestermaintenance is duehold — not nowre-establish a rowcompleteobligation retiredproceed
Figure 1 — a deadline, not a request, initiates the work; traffic is held only while the device is genuinely occupied.

Four things to read out of the figure.

The first arrow comes from a clock, not from a requester. Every other sequence diagram in this curriculum starts with something asking for something. This one starts with time passing. That is the structural novelty, and it is why the timer is an actor rather than an implementation detail.

The requester is held, not refused. It is told to wait and will be served; nothing is dropped. That makes backpressure part of the interface rather than an afterthought — the same conclusion Chapter 1.3 §6 reached from a shared port, arrived at here from a deadline.

The obligation is retired explicitly. The fifth arrow exists because the timer must learn that the work was done. A design in which the deadline clears by assumption rather than by completion is a design that can believe it is safe when it is not — the specific bug §9's second assertion exists to catch.

And the hold is scoped to the work. The requester resumes when the device is free, not when the timer next expires. Holding longer than necessary is a performance bug; holding for less time than the device is occupied is a correctness bug.

4. RTL — Tracking a Deadline

Now the digital design. This is the module's first RTL, and it is placed here rather than earlier for the reason Chapter 2.1 §7 gave: there is finally a genuine digital contract to express. Nothing below models a capacitor, a charge, or a sense amplifier.

What this models. A maintenance obligation that becomes due with the passage of time, arbitration between that obligation and normal traffic, and — the part that makes it worth writing — explicit accounting so that a dropped obligation becomes an observable signal instead of silent data loss.

What it deliberately does NOT model. Any DRAM cell, charge, leakage or sensing. Any real device timing. Any refresh command encoding, per-bank behaviour, postponement or catch-up policy (Module 15). Any addressing — it does not track which row to maintain, because selecting the next location is a scheduling matter and this chapter is about the deadline. There is no data path at all.

Interface. Normal traffic presents req_valid and is accepted when req_ready is high. The device side receives maint_start and answers with maint_done. Everything else is observability.

How to simulate it. vlog refresh_deadline_tracker.sv tb_refresh_deadline_tracker.sv then vsim -c tb_refresh_deadline_tracker -do "run -all"; with VCS vcs -sverilog refresh_deadline_tracker.sv tb_refresh_deadline_tracker.sv && ./simv; with Xcelium xrun -sv refresh_deadline_tracker.sv tb_refresh_deadline_tracker.sv.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// EDUCATIONAL DIGITAL CONTROL MODEL of a maintenance deadline.
//
// This is NOT a DRAM cell, NOT a refresh command generator, NOT a JEDEC
// refresh scheduler, and NOT a memory controller. It models one thing: an
// obligation that becomes due with time, and the accounting that proves it
// was not silently dropped.
//
// THE CYCLE COUNTS ARE PEDAGOGICAL. They are chosen to be legible in a
// ten-cycle waveform. No real device interval is implied.
module refresh_deadline_tracker #(
  // How often the obligation becomes due. Must be >= 1.
  parameter int REFRESH_INTERVAL = 8,
  // How many obligations may be outstanding at once before the design has
  // MISSED the deadline. A real device permits some latitude here; the point
  // of the parameter is that the latitude is FINITE and must be enforced.
  parameter int MAX_OWED         = 1,
  // DERIVED widths, guarded so a parameter of 1 stays legal.
  parameter int CNT_W = (REFRESH_INTERVAL <= 1) ? 1 : $clog2(REFRESH_INTERVAL + 1),
  parameter int OWE_W = (MAX_OWED <= 1) ? 1 : $clog2(MAX_OWED + 1)
) (
  input  logic             clk,
  input  logic             rst_n,

  // Normal traffic. Held, never dropped, while maintenance owns the device.
  input  logic             req_valid,
  output logic             req_ready,

  // Device-side maintenance handshake.
  output logic             maint_start,
  input  logic             maint_done,

  // ── Observability. Not decoration: §9's properties and §10's verification
  //    strategy are built on these, and a design that cannot report its own
  //    obligation cannot be shown to be meeting it. ───────────────────────
  output logic             maint_due,
  output logic [OWE_W-1:0] owed,
  output logic [CNT_W-1:0] interval_cnt,
  // STICKY. Rises if the obligation was allowed to exceed MAX_OWED -- which
  // is the moment data became untrustworthy. Making the correctness failure
  // a SIGNAL rather than silent corruption is the whole point of this model.
  output logic             deadline_missed
);

  typedef enum logic [0:0] {
    S_SERVE,   // traffic may proceed
    S_MAINT    // maintenance owns the device
  } state_e;

  state_e state;

  // ── The two events that change the accounting. Computed once, used once.
  //    `tick` is the deadline arriving; `retire` is an obligation being
  //    discharged. Both can happen in the SAME cycle, which is the subtlety
  //    the next block exists to handle correctly. ─────────────────────────
  logic tick, retire, at_limit;
  assign tick     = (interval_cnt == '0);
  assign retire   = (state == S_MAINT) && maint_done;
  assign at_limit = (owed == OWE_W'(MAX_OWED));

  assign maint_due   = (owed != '0);
  // Traffic proceeds only when nothing is owed and maintenance is not running.
  assign req_ready   = (state == S_SERVE) && !maint_due;
  // Start maintenance the cycle an obligation exists and the device is free.
  assign maint_start = (state == S_SERVE) && maint_due;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      state           <= S_SERVE;
      interval_cnt    <= CNT_W'(REFRESH_INTERVAL);
      owed            <= '0;
      deadline_missed <= 1'b0;
    end else begin
      // ── The deadline clock RUNS ALWAYS. It does not pause for maintenance
      //    and it does not pause for traffic. Time is the trigger, so a timer
      //    that stopped while the design was busy would be a timer that
      //    silently extended the deadline exactly when it mattered most.
      if (tick) interval_cnt <= CNT_W'(REFRESH_INTERVAL);
      else      interval_cnt <= interval_cnt - 1'b1;

      // ── ONE assignment to `owed`, from both events.
      //
      //    Writing this as two separate conditionals -- an increment under
      //    `if (tick)` and a decrement under `if (retire)` -- is how a real
      //    design silently drops an obligation: when a completion and an
      //    expiry land in the same cycle, the later procedural assignment
      //    wins and the new obligation is simply forgotten. Nothing fails
      //    at that moment; data is lost later, somewhere else, unreproducibly.
      owed <= owed + OWE_W'(tick && !at_limit) - OWE_W'(retire);

      // The obligation was allowed to exceed its limit. If a completion
      // lands in the same cycle it frees the slot the tick needs, so that
      // case is NOT a miss -- which is exactly why this is one expression.
      if (tick && at_limit && !retire) begin
        deadline_missed <= 1'b1;
      end

      unique case (state)
        S_SERVE: if (maint_due)  state <= S_MAINT;
        S_MAINT: if (maint_done) state <= S_SERVE;
        default:                 state <= S_SERVE;
      endcase
    end
  end

endmodule

Cycle-level behaviour. interval_cnt counts down every cycle regardless of what else is happening. When it reaches zero, an obligation is added and the counter reloads. The instant an obligation exists, req_ready falls and maint_start rises; the next edge enters S_MAINT, where traffic stays held until the device reports maint_done. That completion retires one obligation and returns to S_SERVE.

State, and why each piece exists. interval_cnt is the deadline clock. owed is the obligation count — it is a count rather than a flag because a design may legitimately owe more than one at a time, and because turning "have I forgotten something?" into arithmetic is what makes the property in §9 checkable. state separates "the device is occupied" from "work is pending", which are different facts. deadline_missed is sticky because a correctness failure that can clear itself is a correctness failure you will never catch in a regression.

The design decision that carries the lesson. The single-expression update of owed is the whole reason this model is worth reading. The naive two-conditional version is correct in every cycle where a tick and a retirement do not coincide — which is almost all of them — and wrong in the rare cycle where they do. That is the worst possible failure profile: it passes directed tests, survives review, and loses data occasionally in the field. The same lesson appeared as occupancy accounting in Chapter 1.8 §9; here the stake is not a performance counter but stored data.

Expected result. With REFRESH_INTERVAL = 8 and MAX_OWED = 1, a testbench holding req_valid high continuously should see req_ready high for eight cycles, then low while one maintenance operation runs, then high again — and deadline_missed must remain low for the whole run. Driving maint_done low forever should make deadline_missed rise shortly after the second interval expires, demonstrating that the model detects its own failure.

Expected waveform. §5 is exactly the first of those runs.

Synthesis implication. A counter, a small saturating count, a two-state machine and a sticky bit — a few tens of flip-flops and a comparator. All synthesizable. deadline_missed is the kind of status bit worth keeping in production silicon rather than treating as a simulation aid, because it converts an invisible correctness failure into something a driver can read.

Limitations, stated because they bound what conclusions the model supports. No addressing, so it does not choose what to maintain. No latitude policy — a real device permits deferral and catch-up under stated rules, which is Module 15. No in-flight request tracking, so it blocks requests rather than draining them, which a real controller would not do. No device timing. And the interval is fixed, whereas a real system adjusts its maintenance rate with temperature, for the reason Chapter 2.2 §3 gave.

Debugging observations. If req_ready never falls, check that interval_cnt is actually decrementing — a timer gated by a busy signal is the classic mistake and the comment in the code names it. If deadline_missed rises in a healthy run, compare the maintenance completion rate against the tick rate: the device is not finishing before the next deadline, which is a sizing problem rather than a logic one. If owed drifts upward over a long run with maint_done behaving, suspect that someone rewrote the single-expression update as two conditionals.

5. The Deadline, in Cycles

refresh_deadline_tracker — a deadline arrives and is discharged

10 cycles
Ten cycles of the deadline tracker with a continuously asserted request. The interval counter reaches zero, an obligation is added, request-ready falls and maintenance starts. The device is occupied for three cycles, reports completion, the obligation is retired, and requests are accepted again. The interval counter continues running throughout.device unavailabledevice unavailableinterval expiresinterval expiresowed rises; traffic heldowed rises; traffic heldmaintenance completesmaintenance completesclkreq_validinterval_cnt3210876543owed0000111100maint_startstateSERVSERVSERVSERVSERVMANTMANTMANTSERVSERVmaint_donereq_readyt0t1t2t3t4t5t6t7t8t9
Figure 2 — the deadline clock runs regardless of traffic; when it expires, maintenance takes the device and requests are held until it completes.

Cycle 3 — the deadline arrives. interval_cnt reaches zero. Nothing has requested anything; time simply passed. This is the cycle that makes the obligation different in kind from everything else in a memory system.

Cycle 4 — the obligation exists and traffic stops. owed rises to one, req_ready falls, maint_start asserts. Note that req_valid has been high continuously — the requester wants service and is being made to wait, which is the backpressure §3 predicted. Note also that interval_cnt has reloaded and is already counting again: the next deadline does not wait for this one to be discharged.

Cycles 5 to 7 — the device is occupied. The phase band marks it. Maintenance is a real access (§1), so it takes real time, and during that time the requester makes no progress. This is the availability cost of §2, visible as cycles.

Cycle 7 into 8 — the obligation is retired. maint_done arrives, owed returns to zero, and the state machine releases the device. From cycle 8 requests are accepted again.

And the thing the figure proves. Between cycles 4 and 8, a processor waiting on this memory made no progress for a reason that had nothing to do with anything it did. Maintenance delay is not caused by traffic — which is why it cannot be avoided by asking for less, and why it belongs in a latency budget as a term of its own.

6. Why This Is a Correctness Property, Not a Performance One

Worth separating sharply, because the two are managed completely differently.

A performance property degrades gracefully and is observable. If maintenance takes longer than planned, throughput drops and latency rises. Somebody notices, measures, and tunes. The system remains correct throughout.

This obligation does not degrade. Miss the deadline and the affected data is simply wrong — and wrong later, in a read that happens at some unrelated moment, in a location nobody connected to the controller's scheduling. Nothing in the failing read indicates that the cause was a maintenance deadline missed some time earlier. There is no graceful region.

Three engineering consequences follow, and they shape how this kind of requirement must be handled:

It cannot be traded off. Every other cost in a memory system can be negotiated against performance. This one cannot, which is why §2 ends with the distinction between when and whether.

It must be enforced structurally, not by convention. A design that meets the deadline because its traffic happens to leave gaps is a design that fails when traffic changes. The enforcement in §4 is that req_ready falls — the hardware makes room whether or not the traffic would have.

And it must be made observable, or it is unverifiable. This is the reason deadline_missed exists. A correctness failure with no signal is a failure that can only be discovered by its consequences, long after and far away. Converting it into a bit that a regression can check, and that silicon can report, is the difference between a property you have verified and a property you are hoping about.

7. Verification Perspective

The specific challenge here is that the property is temporal and global, and a conventional transaction-level environment is blind to it.

Why a scoreboard does not catch it. A scoreboard compares read data against expected data. If a deadline is missed, no transaction is mishandled — every read and write is serviced exactly as requested. The corruption appears later, in a location the missing maintenance was supposed to cover, and only if the test happens to read it, at a condition where the margin actually failed. That is detection by coincidence.

So verify the mechanism, not the consequence. The deadline is tracked by real logic with observable state, which means it can be asserted directly — which is what §9 does. The generalisable principle: when a requirement concerns elapsed time rather than an operation, assert the timing mechanism rather than sampling for the damage.

Stimulus that actually exercises it. Continuous back-to-back traffic with no idle gaps, so the design is maximally pressured to defer. Traffic that stops abruptly and resumes, to catch a timer wrongly gated by activity. A maintenance completion arriving in the same cycle as an interval expiry — the coincidence §4's single-expression update exists for, and one that random stimulus hits rarely enough to be worth directing. Back-to-back deadlines with a slow device. Reset asserted with an obligation outstanding.

Invariants worth stating as checks. An obligation is only ever created by an interval expiry. An obligation is only ever retired by a completion. owed never exceeds its limit. Maintenance never starts while it is already running. Traffic is never accepted while the device is occupied by maintenance.

Coverage worth asking for. Maximum observed owed; maximum observed interval between successive completions; count of requests held by maintenance; and whether the tick-and-retire coincidence was ever hit. That last one deserves a cover property of its own, because a regression that never produced it has not tested the design's most subtle line.

And a corner worth thinking about carefully. What may a system assume about stored data immediately after reset? Reset clears the tracker, but it does not restore any cell — so a design that comes out of reset and assumes its memory is intact is making a claim the hardware does not support. The honest contract is that data written before a reset is not guaranteed across it unless the system was specifically built to maintain it.

8. Common Misconceptions

"Refresh is a performance feature." Wrong model: maintenance is overhead that a better design would reduce or remove. Engineering consequence: it gets treated as negotiable. Under load pressure, someone defers it to recover bandwidth — the exact reasoning Chapter 2.2 §11 dismantles. Observable failure: rare, non-reproducible corruption of cold data, worse when hot and worse under sustained load. Passes qualification, appears in the field. Correct model: it is a correctness obligation with a hard deadline. Scheduling it well is an engineering problem; skipping it is data loss. Prevention: enforce it structurally, as in §4, and instrument it so the margin to the deadline is measured rather than assumed.

"Refresh and restore are the same operation." Wrong model: two names for one thing. Engineering consequence: an inability to reason about either one's cost or trigger, and confusion about why a read that already restores a row does not satisfy the maintenance obligation. Correct model: same machinery, different trigger. Restore is compelled by an access that just disturbed a row. Refresh is initiated by an approaching deadline, on a row nobody asked for. Prevention: ask what triggered it. An access, or the clock?

"A busy system refreshes itself through normal traffic." Wrong model: since accesses restore what they touch, heavy traffic keeps memory maintained. Engineering consequence: a plausible optimisation that loses data. It contains a real grain of truth — an access genuinely does re-establish the row it touches — which is what makes it dangerous. Observable failure: corruption concentrated in regions the workload never touches, which is the hardest place to look. Correct model: the deadline applies to every location. A workload touches a small, unpredictable subset; the at-risk locations are precisely the untouched ones. Prevention: treat coverage of all storage as the requirement. Module 15 covers the latitude a device actually permits.

"The deadline timer should pause while the controller is busy." Wrong model: the timer measures opportunity to maintain, so it should stop when maintenance is impossible. Engineering consequence: the deadline silently extends exactly when the design is least able to meet it, which converts an enforced obligation into an unenforced one under load — while every signal still looks healthy. Observable failure: corruption correlating with sustained load and with nothing else, in a design whose own status registers claim it is meeting its interval. Correct model: the physics does not pause. The timer measures elapsed time, unconditionally; a design unable to keep up must make room by holding traffic, not by moving the deadline. Prevention: the comment in §4's RTL. Never gate a deadline clock with a busy signal.

"If the obligation counter saturates, the design is safe." Wrong model: saturating a counter at its limit prevents overflow, so nothing bad happens. Engineering consequence: the most insidious version of this bug. Saturation makes the counter well-behaved while the obligation is discarded — the design forgets work it owed and reports nothing. Correct model: reaching the limit means a deadline was missed. That is an event to be recorded, which is why §4 sets a sticky deadline_missed rather than quietly clamping. Prevention: whenever a counter tracks an obligation rather than a resource, make saturation an error rather than a boundary.

9. Four Assertions Worth Writing

These state §7's invariants against the tracker's own signals. All four are checkable without visibility into anything else.

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

// P1 -- THE property of the chapter. The obligation is never exceeded, which
// is to say the deadline is never missed. Written against the sticky bit so
// a single violation anywhere in a long run cannot be missed by sampling.
property p_deadline_never_missed;
  @(posedge clk) disable iff (!rst_n)
    !deadline_missed;
endproperty
assert property (p_deadline_never_missed);

// P2 -- an obligation is never silently dropped. `owed` may only DECREASE
// when a maintenance operation actually completed. This is the property that
// catches the two-conditional rewrite described in §4: that bug loses an
// increment rather than producing a spurious decrement, so P2 is written to
// pin the accounting exactly rather than merely bound it.
property p_owed_accounting_exact;
  @(posedge clk) disable iff (!rst_n)
    ##1 (owed == $past(owed)
              + OWE_W'($past(tick) && !$past(at_limit))
              - OWE_W'($past(retire)));
endproperty
assert property (p_owed_accounting_exact);

// P3 -- traffic is never accepted while maintenance owns the device. The
// structural enforcement of §6: the hardware makes room, rather than relying
// on traffic to leave gaps.
property p_no_traffic_during_maintenance;
  @(posedge clk) disable iff (!rst_n)
    (state == S_MAINT) |-> !req_ready;
endproperty
assert property (p_no_traffic_during_maintenance);

// P4 -- maintenance is never started while it is already running, and is
// only started when something is actually owed. Both directions matter: the
// first prevents a duplicate operation, the second prevents an operation the
// deadline did not ask for.
property p_maint_start_is_well_formed;
  @(posedge clk) disable iff (!rst_n)
    maint_start |-> (maint_due && (state == S_SERVE));
endproperty
assert property (p_maint_start_is_well_formed);

What each buys. P1 is the chapter's requirement as one line, and its value comes from the stickiness of the signal it watches: a deadline missed once in a ten-million-cycle regression is caught. P2 is the subtle one and the reason this assertion set is worth having — it pins the accounting to an exact expression, so the coincident tick-and-retire case that the naive implementation gets wrong is checked in every cycle rather than only when stimulus happens to produce it. P3 asserts that the enforcement is structural. P4 is a well-formedness check on the handshake in both directions, which is the form most interface contracts actually take.

What they do not claim. None of them proves any cell was maintained — this is a control model with no addressing, so the question "did every location get covered?" is outside what these signals can answer. In a real controller that property needs the maintenance address sequence to be checked for full coverage within the interval, which is a Module 15 concern. Saying so is part of the lesson: an assertion set proves things about the mechanism it can see, and claiming more for it than that is its own failure mode.

10. Debugging — A Controller That Believes It Is Compliant

Symptom. Rare, non-reproducible incorrect data from memory. The controller's status registers report that it is meeting its maintenance interval. Corruption is worse under sustained load and worse at elevated temperature.

The status register is what makes this interesting: the design's own self-report says it is fine.

Mechanism 1 — the deadline timer is gated by activity. What to observe: whether the interval counter advances during every cycle, including while maintenance is running and while the request path is stalled. Expected evidence: the reported interval looks compliant while the elapsed interval between completions is longer, because the timer stopped for part of it. How to discriminate: compare a free-running cycle count against the design's own interval count over a long window. Divergence is conclusive, and it also explains the load correlation: the busier the design, the more the timer paused. §8's fourth misconception in its natural habitat.

Mechanism 2 — obligations are being dropped in the coincidence case. What to observe: cycles where a maintenance completion and an interval expiry land together, and whether owed behaves correctly across them. Expected evidence: the completion count exceeding what the tick count should have produced — a slow drift rather than a single event. How to discriminate: P2 in §9 fails immediately if this is happening; without it, the tell is that the discrepancy grows with run length rather than appearing at a specific moment.

Mechanism 3 — the counter saturates silently. What to observe: whether the obligation count ever sits at its maximum, and whether anything records that it did. Expected evidence: the count pinned at the limit during load peaks, with no error reported. How to discriminate: this is §8's fifth misconception. If the design clamps rather than flagging, the status register will look healthy by construction — which is exactly the reported symptom.

Mechanism 4 — the device is not completing in time. What to observe: the latency of each maintenance operation against the interval. Expected evidence: completions arriving close to or after the next expiry, so the design is permanently behind. How to discriminate: this is a sizing problem, not a logic one, and it shows up as owed rarely returning to zero. The fix is in the interval, the device, or the scheduling — not in the tracker.

Mechanism 5 — the tracker is correct and the problem is elsewhere. What to observe: whether the corruption correlates with temperature or access pattern rather than with the controller's behaviour. Expected evidence: corruption that persists at a comfortable maintenance margin. How to discriminate: raise the maintenance rate substantially and see whether the corruption changes at all. If it does not, this chapter is not the cause and Chapter 2.2 §8's other mechanisms are.

Root-cause discrimination in one measurement. Instrument a free-running cycle counter alongside the design's own interval counter, and log the elapsed cycles between successive maintenance completions. That single time series separates mechanisms 1 to 4: a gated timer shows divergence between the two counters; dropped obligations show a growing completion deficit; saturation shows a pinned count; and a slow device shows long but honestly reported intervals. Mechanism 5 shows a healthy time series.

The reasoning lesson. The design's self-report was the least trustworthy evidence, because every mechanism above except the last corrupts the reporting and the behaviour together. When a design reports on its own compliance with a deadline, measure the deadline independently — from a counter nothing in the design can gate.

11. Interview Reasoning

"Why does DRAM need refresh?" Because the cell stores charge passively and nothing drives it to contest the leakage paths that always exist, so the separation between its two states narrows until the sensing decision becomes unreliable (2.2). The repair is to re-establish the state at full strength, and it must happen before the margin is gone — which makes it a deadline. A strong answer avoids the circular form ("DRAM refreshes because it needs refreshing") and derives it: passive storage, uncontested loss, narrowing margin, bounded time.

"What work does a refresh actually perform?" The same work a read already does: connect the cells to the sensing circuitry while the decision is still reliable, let it resolve which state each is in, and drive the resolved state back at full strength. The data is discarded — the point was the restoration. So refresh is not a separate engine but the ordinary access mechanism, initiated by a deadline rather than by a request, on locations nobody asked for.

"Why can't a busy memory system rely on normal traffic to keep data alive?" Because an access only re-establishes the rows it touches, and the deadline applies to every location. A workload touches a small and unpredictable subset, so the locations at risk are precisely the untouched ones. The obligation is universal and time-based, and being busy provides no coverage guarantee — it makes the problem harder, because a busy design is under more pressure to defer.

"Is refresh a performance problem or a correctness problem?" Both, and the distinction is the point. It costs performance, because maintenance occupies the same structures that serve requests, so the device is periodically unavailable for reasons unrelated to traffic. But the deadline itself is correctness: miss it and data is wrong, later, in a read with nothing to connect it to the cause. So when to do the work is an engineering decision and whether to do it is not — and a design must enforce it structurally rather than relying on traffic to leave gaps.

"Your maintenance timer is gated by a busy signal to avoid triggering during a burst. What is wrong with that?" It silently extends the deadline exactly when the design is least able to meet it. The physics does not pause while the controller is busy, so a timer that does is measuring the wrong thing — and worse, the design's own status reporting will claim compliance while the elapsed interval quietly grows with load. The correct structure is a deadline clock that runs unconditionally, and a design that makes room by holding traffic when it must.

"How would you verify that a controller never misses its maintenance deadline?" Not with a scoreboard — no transaction is mishandled when a deadline is missed, so data comparison detects it only by coincidence, long after and only under the right conditions. Instead assert the mechanism: that the obligation count never exceeds its limit, that it changes only through an expiry or a completion and by exactly one each, and that traffic is never accepted while maintenance owns the device. Then instrument the maximum observed interval so margin is measured rather than assumed. The general principle is that a requirement about elapsed time is verified by asserting the timing mechanism, not by sampling for the damage.

12. Engineering Check

A design owes at most one maintenance operation at a time. Under a sustained traffic burst, a maintenance completion happens to land in the same cycle as the interval expiry. The obligation counter is updated by two separate conditionals: an increment when the interval expires, and a decrement when a completion arrives.

1. What happens in that cycle? Both conditionals fire, and because they are separate nonblocking assignments to the same variable in one procedural block, the later one wins. The decrement overwrites the increment, so the new obligation is never recorded. The count returns to zero and the design believes it owes nothing.

2. What is the consequence, and when does it appear? One row that should have been maintained is not. Nothing fails at that moment: no transaction errors, no status bit, no assertion — the design looks perfectly healthy. The consequence appears later as incorrect data from that row, if and when something reads it, and only if the margin actually ran out. There is no evidence connecting the failing read to the cycle where the obligation was lost.

3. Why is this failure profile the worst possible one? Because it requires a coincidence, so it is rare; it produces no immediate symptom, so it survives review and directed testing; and its consequence is remote in both time and location from its cause. A bug that fails loudly and often is cheap. This one is expensive precisely because it is well behaved almost always.

4. What is the fix, and why that shape? Compute the count from both events in a single expression, as §4 does, so the two contributions add rather than compete. The general rule: when one piece of state is affected by several events that can coincide, derive its next value once from all of them. Two conditionals on one variable is a race written in slow motion.

5. What would have caught it? P2 in §9 — an assertion that pins the accounting to an exact expression rather than merely bounding it — fires in the first cycle the coincidence occurs. A cover property on the coincidence itself would also have revealed that the regression never produced the case, which is the earlier and cheaper discovery. Notice that neither is a data check: the bug is in the bookkeeping, so the check has to be on the bookkeeping.

6. Suppose instead the counter saturated at its maximum and the design continued. Is that safer? No — it is the same failure with better manners. Saturating keeps the counter well-formed while discarding the obligation, and reports nothing. Whenever a counter tracks an obligation rather than a resource, reaching the limit is an event to record, not a boundary to clamp at. That is why §4 sets a sticky deadline_missed instead.

13. Summary

The maintenance operation is not special machinery. It is the ordinary access mechanism — connect the cells to sensing, resolve the state, drive it back at full strength — initiated by an approaching deadline rather than by a request, on locations nobody asked for, and performed for its side effect rather than its data. The data is discarded; the restoration was the point.

That makes it cost device availability, because it occupies the same structures that serve requests. And the cost is architecturally unusual: it is not caused by traffic. Every other delay in a memory system is request-driven; this one is driven by the clock, happens whether the system is busy or idle, and cannot be avoided by asking for less.

Meeting the deadline requires real logic: something that tracks elapsed time unconditionally, something that decides an obligation exists, something that takes the device, and something that makes requesters wait rather than dropping them. The deadline clock must never be gated by a busy signal, because the physics does not pause when the controller is busy.

It is a correctness property, not a performance one. There is no graceful degradation: miss it and data is wrong, later, in a read with nothing to connect it to the cause. So it must be enforced structurally rather than by leaving gaps in traffic, and it must be made observable — a dropped obligation should be a signal, not silent corruption — because a correctness failure with no signal can only be discovered by its consequences.

And the accounting deserves care out of proportion to its size. An obligation count touched by two separate conditionals loses work in the rare cycle where an expiry and a completion coincide: no immediate symptom, no failing transaction, data lost later and elsewhere. One expression, derived from all the events that can change it.

14. What Comes Next

This chapter took the obligation on trust in one respect. §1 said the maintenance operation works on "a whole row of cells at once" and pointed forward for the reason. It also assumed sensing exists, that a read disturbs what it touches, and that driving a state back is something the array can do.

Those assumptions are the rest of the module, and they start with structure. Chapter 2.4 puts the storage element of 2.1 into its actual circuit: one access transistor, one capacitor, a wordline that decides when the cell participates, and a bitline shared with many other cells that decides where its charge goes. That arrangement is what makes a single tiny stored charge selectable out of an array of billions — and, as 2.5 then shows, it is also exactly why reading destroys what it reads.

Return to Charge Storage and Leakage for the mechanism that created this obligation, or Capacitor Storage for the two absences that generate the whole module. For the system-level cost of a periodically unavailable device, see The Memory Wall Problem. 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.