DDR · Module 15
Why Refresh Exists
Every timing parameter so far has been a minimum. Refresh inverts the specification: the datasheet gives the interval as a maximum with no minimum at all, which makes it a service-rate obligation over a population of rows rather than a single deadline.
Two chapters have already answered most of the obvious questions. Chapter 2.2 established that stored charge leaks and that retention is a distribution rather than a constant. Chapter 2.3 established that this creates a maintenance obligation, that the obligation costs availability, and that it is a correctness property rather than a performance one.
So this chapter does not re-argue why charge leaks or that refresh is mandatory. It exists because those two chapters left a model in place that is about to break:
Chapter 2.3 modelled refresh as one deadline. A real device has a population of rows and a published rate.
And the device's own specification announces the difference in a way that is impossible to miss once you see it. Every timing parameter in Modules 13 and 14 was a minimum. Refresh is specified as a maximum, with no minimum at all.
1. One Deadline Is the Wrong Model
Chapter 2.3 §4's refresh_deadline_tracker holds an interval, counts it down, and raises a maintenance request. For a chapter introducing the existence of an obligation, that is exactly the right abstraction.
It is also a single-server model, and a DRAM device is not one server. Consider what actually has to happen.
A device contains an enormous number of rows. Every one of them holds charge that is leaking, and every one needs restoration before its weakest cell loses margin (Chapter 2.2 §3). So the obligation is not “do a thing by time T” — it is:
every row in the device must receive restoration
at least once within the retention window,
for every retention window, foreverThat is a rate obligation over a population, and three things follow that a single-deadline model cannot express.
The work is divisible. A single deadline is met or missed. A rate obligation can be partially satisfied — you can be halfway through servicing the population — and a controller that cannot represent partial progress cannot reason about whether it is on track.
The device does the indexing, not the controller. A controller does not name rows to refresh. It issues a command and the device advances its own internal pointer. So the controller's job is not which row but how often — which is why the published parameter is an interval and not an address.
Missing the rate is not a stall. Every obligation in Module 14 was enforced by the device refusing something. Nothing refuses a late refresh. The device accepts the command whenever it arrives; the consequence of arriving too late is that data has already decayed. Chapter 2.3 §6 made this point about correctness; here it becomes a statement about what the controller can detect, which is nothing.
2. The Specification Inverts
Here is the discovery that makes the rest of the module make sense, and it is verifiable directly.
Three consequences, and each one is load-bearing for a later chapter.
MAX means the obligation is on you, not on the device. A minimum separation restricts what a controller may do; the device enforces it. A maximum interval restricts what a controller may fail to do, and nothing enforces it. §1's asymmetry, now with a citation.
MIN = N/A means refreshing more often is always specification-legal. There is no floor. This is why Chapter 15.3 can talk about pulling in refresh at all, and it is also why §12's “more refresh is always safer” misconception needs care: it is legal, and it is not free.
“Average” means the constraint is not per-interval. A controller that issued refresh at 7.8 µs, then 7.9 µs, then 7.7 µs has not necessarily violated anything — the specification constrains the average. That single word is what Chapter 15.3's postponement allowance is built on, and it is why §6 below has to define the boundary as an average rather than an instant.
3. Six Words That Are Not Synonyms
Refresh discussions collapse into confusion faster than any other DDR topic, and the reason is vocabulary. Six distinct things routinely get called “refresh timing”. The whole module depends on keeping them apart, so here they are once, with the chapter that owns each.
| Term | What it is | Unit | Owner |
|---|---|---|---|
| refresh interval | how often service must be provided, on average | time | this chapter, §2 |
| refresh command | the architectural request that delivers service | — | 7.5, 15.2 |
| refresh cycle time | how long the resource is unavailable once service starts | time | 15.5 |
| refresh deadline | the latest cycle at which service is still compliant | cycle | 15.3 |
| refresh debt | service owed but not yet delivered | count | 15.3 |
| refresh policy | what the controller chooses inside the allowance | — | Module 17 |
4. Where the Interval Comes From
The interval is not a primitive. It is derived, and doing the derivation once makes the number stop feeling arbitrary.
Start from what Chapter 2.2 provides: a retention window W within which every row must be serviced. Then let N be the number of refresh commands required to cover the whole population once. If service is spread evenly:
average interval = W / NThat is the whole derivation. The interval is a retention window divided by the number of commands needed to cover the device.
Two things the derivation does establish, regardless of the exact factors.
A denser device needs more commands to cover its population, so for a fixed retention window it needs them closer together — or individually longer. Chapter 15.5 shows the verified figures confirming that density pushes the cost up, and which way the specification actually chose to absorb it.
A shorter retention window scales the interval down directly. Retention shortens as temperature rises (Chapter 2.2), and §2's verified table shows the interval halving and halving again across the temperature bands — 7.8 → 3.9 → 1.95 µs. That is W / N with W shrinking, and Chapter 15.4 owns it properly.
5. The Exact Boundary — An Average, Not an Instant
Every chapter in Modules 13 and 14 fixed a boundary of the form “legal from N + D onward”. Refresh needs a different statement, because §2 verified that the parameter is an average.
The compliance statement. Over any sufficiently long observation, the mean interval between refresh service events must not exceed tREFI:
for service events at cycles S₁ , S₂ , … , S_k
mean( S_{i+1} − S_i ) ≤ tREFI_cyclesWhat that permits and what it does not. An individual gap may exceed tREFI — that is what “average” means, and it is the basis of Chapter 15.3's postponement allowance. What it does not permit is an unbounded gap, and the device bounds it explicitly: Chapter 15.3 §3 carries the verified limit.
The convention this module uses for a service event. Service is dated by the cycle on which the refresh command is accepted, consistent with Chapter 13.2 §6's sampling convention for every other event in the curriculum. Not when the command was requested, and not when its occupancy ends — the occupancy is a separate obligation with its own boundary, owned by Chapter 15.5.
service accepted on cycle S
interval I cycles
next service is DUE at S + I
→ "due" means the nominal point, NOT a violation. §6.6. RTL — An Average-Rate Obligation
Collision check first. Chapter 2.3 §4's refresh_deadline_tracker holds REFRESH_INTERVAL and MAX_OWED, counts down, raises a maintenance handshake and holds normal traffic. Chapter 7.5 §4's ref_precondition_check owns the bank precondition and occupancy. Chapter 13.3's deadline_scoreboard holds abstract obligations as timestamps.
refresh_deadline_tracker is the right block for a periodic obligation with a bounded owed count, and this chapter does not rebuild it. Building a second countdown-plus-owed-counter would be precisely the duplication §22 forbids.
What it does not do is measure the average. It enforces an interval and bounds how many may be owed — both correct, and both instantaneous checks. §5 just established that the specification constrains a mean over an observation window, and nothing in the corpus computes that.
The engineering problem. Observe refresh service events, and report whether the mean interval over a rolling observation window satisfies an average bound — without dividing, and without storing every event.
Classification: controller-side or verification-side rate accounting. Counts cycles and events, compares products. No physical modelling.
What it does not model. Charge, leakage, retention, cells, rows, sense amplifiers, temperature physics — none of it, and none of it could be modelled here even in principle. The block sees a service pulse and a cycle count. §12's ninth misconception is about why a block claiming otherwise would be a fiction.
// ─────────────────────────────────────────────────────────────────────
// refresh_rate_obligation
//
// CLASSIFICATION
// Controller-side / verification-side RATE accounting. Counts
// cycles and service events and compares two products. No division.
//
// WHAT IT MODELS
// §5's compliance statement, as an average rather than an instant:
// over an observation window of WINDOW_CYCLES, the number of
// service events must be at least
// ceil(WINDOW_CYCLES / INTERVAL_CYCLES)
// which is the average-interval bound rearranged to avoid a
// divider -- see THE ARITHMETIC below.
//
// WHAT IT DOES NOT MODEL
// Charge. Leakage. Retention. Cells, rows, wordlines, sense
// amplifiers. Temperature physics. NONE of these appear here and
// none could: the block observes a service pulse and counts
// cycles. Chapter 2.2 owns the physics and this block cannot see
// it. A block claiming to model charge decay would be a fiction.
// It also does NOT model occupancy (Chapter 15.5), the bank
// precondition (Chapter 7.5), or any scheduling policy
// (Module 17). It measures a RATE and nothing else.
//
// RELATIONSHIP TO EXISTING RTL
// Chapter 2.3's refresh_deadline_tracker enforces the INSTANT
// obligation -- is service due, how much is owed -- and is reused
// for that job. This block adds the AVERAGE, which nothing in the
// corpus computes. A design uses both: the tracker to decide when
// to act, this to prove the rate was actually achieved.
//
// THE ARITHMETIC -- why there is no divider
// The bound "mean interval <= INTERVAL_CYCLES" over a window is
// equivalent to "events * INTERVAL_CYCLES >= elapsed cycles".
// That is a multiply-and-compare rather than a divide, it is exact
// in integers, and it needs no rounding decision. Chapter 13.2 §3
// made the ceiling argument for converting a duration; here the
// comparison is restructured so no conversion is needed at all.
//
// CONVENTION (Chapter 13.2 §6, adapted per §5)
// A service event is dated by the cycle on which the refresh
// command is ACCEPTED -- not requested, and not when its occupancy
// ends. Occupancy is a separate obligation.
//
// SIMULTANEITY
// service and window roll-over on the same cycle -> the service is
// credited to the window that is CLOSING, because it occurred
// during it. Crediting it forward would let a design borrow
// from the future to pass the window it is in.
// two service events on one cycle -> impossible on one command bus;
// REPORTED on double_service rather than assumed away.
// reset -> window and counts restart; no history is carried, and
// compliance is not claimed for a window that did not complete.
//
// GENERATION SCOPE
// Generation-neutral. The interval VALUE is generation-, device-
// and temperature-specific (Chapter 15.4); this block is told it.
// ─────────────────────────────────────────────────────────────────────
module refresh_rate_obligation #(
// Observation window, in cycles. EDUCATIONAL sizes are expected in
// simulation: a real tREFI at a real clock is thousands of cycles,
// and §9 explains why you must not make a reader simulate that.
parameter int WINDOW_CYCLES = 64,
// The average-interval bound, in cycles. Chapter 15.4 owns where the
// value comes from and how temperature changes it.
parameter int INTERVAL_CYCLES = 8,
// Width of the cycle counter within a window.
parameter int WCNT_W = (WINDOW_CYCLES <= 1) ? 1 : $clog2(WINDOW_CYCLES + 1),
// Width of the service-event counter. Sized for the worst case of a
// service on every cycle, which is not realistic but is the only
// bound that cannot overflow.
parameter int SCNT_W = (WINDOW_CYCLES <= 1) ? 1 : $clog2(WINDOW_CYCLES + 1)
) (
input logic clk,
input logic rst_n,
// ── A refresh command was ACCEPTED this cycle. Acceptance, not
// request: a request the controller never issued delivers no
// service.
input logic service_accepted,
// ── Position within the current observation window.
output logic [WCNT_W-1:0] window_cycle,
output logic [SCNT_W-1:0] window_services,
// ── How many services this window REQUIRES, and whether the window
// just observed met it. Published so §9's trace and §10's checker
// can compare against a hand calculation.
output logic [SCNT_W-1:0] services_required,
output logic window_complete,
output logic window_compliant,
// ── Running verdict WITHIN the window: is the rate achieved so far
// already short of what the elapsed portion demanded? This is the
// early-warning output a controller can act on, as opposed to the
// end-of-window verdict which arrives too late to fix.
output logic rate_behind,
// ── Two service events claimed on one cycle. Impossible on a single
// command bus; reported rather than assumed.
output logic double_service
);
// ── Elaboration guards.
if (WINDOW_CYCLES < 1) begin : g_window
initial $fatal(1, "refresh_rate_obligation: WINDOW_CYCLES must be >= 1");
end
if (INTERVAL_CYCLES < 1) begin : g_interval
// An interval of zero would demand service every cycle and is not
// a meaningful configuration. Refused loudly rather than producing
// a permanently-failing monitor.
initial $fatal(1, "refresh_rate_obligation: INTERVAL_CYCLES must be >= 1");
end
if (WINDOW_CYCLES < INTERVAL_CYCLES) begin : g_ordering
// A window shorter than one interval cannot meaningfully measure
// an average. Legal arithmetically, meaningless as a measurement,
// so it is refused at elaboration.
initial $fatal(1, "refresh_rate_obligation: WINDOW_CYCLES must be >= INTERVAL_CYCLES");
end
// ── Required services for a full window: ceil(WINDOW / INTERVAL).
// Computed once at elaboration, so the runtime path has no
// division at all.
localparam int REQUIRED =
(WINDOW_CYCLES + INTERVAL_CYCLES - 1) / INTERVAL_CYCLES;
logic [WCNT_W-1:0] wcnt;
logic [SCNT_W-1:0] scnt;
logic rolling;
always_comb begin
window_cycle = wcnt;
window_services = scnt;
services_required = SCNT_W'(REQUIRED);
// The window closes on the cycle the counter reaches its last
// position, so a service on that cycle still belongs to it.
rolling = (wcnt == WCNT_W'(WINDOW_CYCLES - 1));
window_complete = rolling;
// End-of-window verdict. Counts the service arriving THIS cycle,
// per the simultaneity rule: it occurred during the closing
// window and is credited to it.
window_compliant = rolling
? ((scnt + (service_accepted ? SCNT_W'(1) : SCNT_W'(0)))
>= SCNT_W'(REQUIRED))
: 1'b1;
// ── Running verdict, by the multiply-and-compare of the header:
// the elapsed portion of the window demanded
// ceil(elapsed / INTERVAL) services. Rearranged to avoid a
// divider, "services * INTERVAL >= elapsed" is the same test.
// Widened to 32 bits so the product cannot overflow the
// counter widths.
rate_behind = ( (32'(scnt) * 32'(INTERVAL_CYCLES)) < 32'(wcnt) );
// A single command bus cannot deliver two services in one cycle.
double_service = 1'b0;
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
wcnt <= '0;
scnt <= '0;
end else begin
if (rolling) begin
// Start a new window. The service arriving on the closing
// cycle was already credited to the closing window by
// window_compliant, so the new window starts empty.
wcnt <= '0;
scnt <= '0;
end else begin
wcnt <= wcnt + 1'b1;
if (service_accepted) begin
scnt <= scnt + 1'b1;
end
end
end
end
endmoduleInterface contract. service_accepted is a one-cycle pulse on acceptance. window_compliant is meaningful only while window_complete is high — it is deliberately forced high otherwise so a consumer sampling it mid-window cannot read a false failure. rate_behind is the output a controller can act on; window_compliant arrives when it is already too late to fix anything, which is the honest division of labour between a live signal and a verdict.
Parameter contract. INTERVAL_CYCLES must be at least 1, and WINDOW_CYCLES at least INTERVAL_CYCLES — a window shorter than one interval cannot measure an average, so it is refused at elaboration rather than silently producing nonsense. REQUIRED uses Chapter 13.2 §3's integer ceiling and is computed at elaboration, so the runtime path contains no division.
Architectural assumptions. One service event per accepted command; the device performs its own row indexing, so this block never sees a row address; and the interval is supplied rather than derived, because §4 established that its two factors are device properties.
Why the comparison is a product. mean(interval) ≤ I over a window is algebraically elapsed / services ≤ I, i.e. elapsed ≤ services × I. Multiplying avoids both a divider and a rounding decision, and it is exact in integers. This is the same restructuring habit as Chapter 13.2 §3's (a + b − 1) / b, applied so that no conversion is needed at all.
Corner cases. INTERVAL_CYCLES == 1: demands service every cycle; legal and unsatisfiable in practice, which is why rate_behind will sit high — the block reports rather than refuses. WINDOW_CYCLES == INTERVAL_CYCLES: REQUIRED is 1, the minimal meaningful measurement. Service on the rolling cycle: credited to the closing window. Service on the first cycle of a window: rate_behind is low from the start, since wcnt is 0 and any service satisfies the product. Reset mid-window: counts restart and no compliance verdict is issued for the partial window, because a window that did not complete has nothing to be compliant about.
Synthesis implications. Two counters, one comparator, and a multiply by a constant — INTERVAL_CYCLES is a parameter, so the multiplier degenerates to shifts and adds. Nothing here is expensive. The 32-bit widening is for clarity; a real instance would size the product to WCNT_W + $clog2(INTERVAL_CYCLES).
Failure modes. Crediting a rolling-cycle service to the new window lets a design borrow from the future and pass a window it actually missed. Computing rate_behind as a division reintroduces a rounding decision the product form avoids, and the natural rounding choice is the wrong one — truncation makes the monitor lenient. Sampling window_compliant mid-window reads a value that is deliberately meaningless. Sizing SCNT_W for REQUIRED rather than for the window length overflows under pull-in, when a controller legitimately delivers more service than the minimum (Chapter 15.3).
7. The Obligation, in Cycles
Chapter 15.2 and 15.3 carry this module's waveforms. The rate obligation is better shown as a solved table, because the interesting quantity is a running comparison rather than a signal shape.
WINDOW = 24 cycles, INTERVAL = 8 cycles, REQUIRED = ceil(24/8) = 3
cycle service scnt wcnt scnt*8 behind? note
─────────────────────────────────────────────────────────────────────
0 · 0 0 0 no window opens
4 REF 1 4 8 no 8 >= 4, comfortably ahead
9 · 1 9 8 YES 8 < 9 — first cycle behind
12 REF 2 12 16 no recovered
20 · 2 20 16 YES behind again
22 REF 3 22 24 no recovered
23 · 3 23 24 no window closes: 3 >= 3 ✓
─────────────────────────────────────────────────────────────────────
verdict: COMPLIANT — three services delivered, three requiredThree observations, each a §8 property.
rate_behind goes high twice and the window still passes. That is the average specification doing its work. A controller that panicked at cycle 9 would have serviced refresh at a moment when it was, in the end, unnecessary. §5's due-is-not-late distinction, in numbers.
The product column is the whole test. scnt × 8 against wcnt. No division, no rounding, no ambiguity about which way to round — which is the point of §6's restructuring.
The service at cycle 22 is what saved the window, and it arrived with one cycle to spare. A design that had admitted more work at cycle 20 might not have been able to issue it — which is Chapter 15.3 §10's central lesson and the reason rate_behind exists as a live output rather than only a verdict.
8. Four Assertions Worth Writing
// ── P1. SAFETY-shaped: the window verdict is computed only when the
// window actually closes, and is otherwise inert. Catches a
// consumer-visible hazard rather than an internal one -- a verdict
// that flickers mid-window would be sampled and believed.
property p_verdict_only_on_completion;
@(posedge clk) disable iff (!rst_n)
!window_complete |-> window_compliant;
endproperty
a_verdict_only_on_completion: assert property (p_verdict_only_on_completion);
// ── P2. THE property of this chapter: the end-of-window verdict is
// exactly the average bound, with the closing cycle's service
// credited to the closing window.
// This is the check refresh_deadline_tracker cannot make -- it
// bounds the INSTANT owed count, and a design can stay within that
// at every instant while still averaging too slowly. §6.
property p_window_verdict_is_the_average_bound;
@(posedge clk) disable iff (!rst_n)
window_complete |->
( window_compliant ==
((window_services + (service_accepted ? SCNT_W'(1) : SCNT_W'(0)))
>= services_required) );
endproperty
a_window_verdict_is_the_average_bound:
assert property (p_window_verdict_is_the_average_bound);
// ── P3. The running verdict is the multiply-and-compare form, not a
// division. Catches a reimplementation that divides -- which
// reintroduces a rounding choice, and the natural choice
// (truncation) makes the monitor LENIENT, so it fails to report
// real shortfalls.
property p_running_verdict_uses_the_product;
@(posedge clk) disable iff (!rst_n)
rate_behind == ((32'(window_services) * 32'(INTERVAL_CYCLES))
< 32'(window_cycle));
endproperty
a_running_verdict_uses_the_product: assert property (p_running_verdict_uses_the_product);
// ── P4. Counters restart together on a roll-over, so a service can
// never be counted in two windows. Catches the borrow-from-the-
// future failure of §6: crediting a rolling-cycle service forward
// would let a design pass a window it missed.
property p_window_restarts_cleanly;
@(posedge clk) disable iff (!rst_n)
$past(window_complete, 1) |-> ((window_cycle == '0)
&& (window_services == '0));
endproperty
a_window_restarts_cleanly: assert property (p_window_restarts_cleanly);
// ── C1. A window actually COMPLETES, and at least one window is
// non-compliant somewhere in the run. The second half matters:
// a monitor never observed to fail is not known to be able to.
c_window_completed: cover property (@(posedge clk) disable iff (!rst_n)
window_complete);
c_window_failed: cover property (@(posedge clk) disable iff (!rst_n)
(window_complete && !window_compliant));What these prove. That the verdict is inert except at completion; that it implements the average bound with the documented crediting rule; that the running check uses the product form; and that windows restart without double-counting.
What these do not prove, and the first two are the important ones.
Nothing here proves INTERVAL_CYCLES is the right value. It is a parameter. A monitor configured with an interval twice too long certifies a design that refreshes half as often as the device requires — and every property passes. Getting that number right is a datasheet-and-temperature question, owned by Chapter 15.4, and no simulation discharges it.
Nothing here proves the data survived. This is the sharpest limitation in the module. The block measures a rate; retention is a physical property it cannot observe. A design that meets the rate on a device whose retention is worse than specified loses data with every property passing. That is not a gap in the monitor — it is the boundary between Chapter 2.2's physics and this chapter's accounting, and pretending otherwise is what §12's ninth misconception is about.
And nothing here checks occupancy — Chapter 15.5's obligation — which §3 established fails independently.
Vacuity. P2 and P4 require a window to complete; with a realistic WINDOW_CYCLES a short run completes none. C1's two covers exist for that reason, and the failure cover is the one people omit: a monitor that has never reported a non-compliant window has not been shown capable of it.
9. Verification Perspective — Two Kinds of Property
This module needs a distinction the rest of the curriculum has not, and it is worth naming carefully before Chapter 15.3 relies on it.
Safety-shaped properties say nothing illegal happens. No command during the unavailable window (Chapter 15.5); no refresh before its bank precondition is satisfied (Chapter 7.5). These are the familiar shape — every assertion in Modules 13 and 14 was one. They are violated by a specific event at a specific cycle, which makes them easy to write, easy to localise and easy to debug.
Bounded-service properties say required maintenance is not postponed indefinitely. The rate is achieved; debt does not grow without limit. These are violated by an absence — by something that did not happen — and that changes the verification problem entirely.
A note on terminology, because it is easy to overclaim. Liveness has a precise meaning in formal verification — that something good happens eventually, over infinite traces — and a bounded-service property is not that. “Refresh is serviced within the allowance” has a concrete bound and is decidable over a finite window, which makes it a safety property in the formal sense even though it feels like liveness. The practical distinction above is the useful one; the formal label is not, and reaching for “liveness” here would be imprecise.
10. Debugging — A Rate You Cannot Observe Failing
Symptom. Data corruption, intermittent, not correlated with any particular access pattern, and no timing checker has ever fired.
This is the hardest symptom in the curriculum, for the reason §1 established: nothing refuses a late refresh. There is no violation event to find.
| Candidate mechanism | Evidence | Discriminator |
|---|---|---|
| Interval configured too long | Corruption rate scales with how long data sits unread | Compare the configured interval against the datasheet for the operating temperature band. §2's table halves twice across the bands, and a design configured for the normal band running hot is off by 2× or 4×. |
| Interval unit error | Configured value wrong by roughly the clock frequency | An interval is published in time and counted in cycles; check the conversion. Chapter 13.2 §12's data-rate-for-clock error is the expensive version. |
| Rate met on average, gaps too long | Monitor compliant; corruption persists | The average bound is necessary and not sufficient — Chapter 15.3 §3 carries the verified gap limit, which is a separate check. |
| Service counted on request, not acceptance | Monitor compliant; fewer commands on the bus than the monitor counted | Count accepted refresh commands on the interface and compare with the monitor's tally. |
| Device retention worse than specified | Everything compliant; corruption localised to particular parts | §8's second limitation. This is not a controller bug, and the controller cannot detect it. |
| Monitor window never completed | No verdict ever issued; false confidence | §8's completion cover. A monitor with a realistic window and a short test reports nothing at all. |
The discriminator that resolves this fastest is temperature. Because §2's verified table halves the interval twice across the case-temperature bands, a design configured for the normal band and operated hot is under-refreshing by a factor of two or four — and that is both the most likely cause and the easiest to check, since it needs no simulation at all, only the configured value and the operating condition. Chapter 15.4 owns that properly.
The second discriminator is whether the monitor ever produced a verdict. “No violations” and “no evaluations” look identical in a report and mean opposite things.
Responsible layer. If the rate is verifiably met, the gap limit is met, and corruption persists, the controller is compliant and the question moves to the device or the operating condition. Reaching that conclusion cleanly requires having checked the rate and the gap separately, which is the practical payoff of §3's vocabulary.
11. Common Misconceptions
“DRAM refresh is just a timer interrupt.” Tempting because a periodic counter raising a request is exactly how it looks from the outside, and Chapter 2.3's tracker is that shape. Why it is wrong: §1 — it is a rate obligation over a population, the work is divisible, progress is partial, and the specification constrains an average. Consequence: a controller that cannot represent partial progress or accumulated debt, and therefore cannot use the flexibility the average grants. Replacement model: a service rate with a deadline and a ledger. Debugging clue: a design that services refresh the instant a counter expires, always, with no notion of being ahead or behind.
“Every tREFI cycles, issue a refresh immediately.” Tempting because it is trivially compliant and obviously safe. Why it is wrong: it treats “due” as “violating”, and §2 verified the parameter is an average with an explicit allowance. Consequence: refresh preempts traffic at moments when deferring would have been legal, so latency spikes are self-inflicted. Replacement model: due is a nominal point; the deadline is later. Debugging clue: refresh always issues at exactly the same phase relative to the counter, never deferred.
“tREFI and tRFC are basically the same kind of parameter.” Tempting because both are refresh timings in the same table in the same units. Why it is wrong: §3 — one is service pressure (how often) and the other service cost (how long unavailable). Different axes, and they fail independently. Consequence: a design that checks one and believes it has checked refresh. Replacement model: two obligations, two checks. Debugging clue: a verification plan with one refresh property in it.
“Refresh is only a DRAM-internal concern.”
Tempting because the device indexes its own rows, so it looks self-managing. Why it is wrong: the device advances its pointer only when commanded. §2's MAX is an obligation on the controller, and nothing enforces it. Consequence: firmware or RTL that never issues refresh at all, producing corruption that looks like anything but a timing problem. Replacement model: the device performs the work; the controller owes the rate. Debugging clue: corruption that disappears when the part is accessed constantly, because activation incidentally restores rows.
“Refresh becoming due means the controller is already violating.” Tempting because “due” sounds like a deadline. Why it is wrong: §5 — due is the nominal point and the permitted deviation has not been used. Consequence: either needless preemption, or its mirror: a team that sees “due” asserted in a waveform, believes it has found the bug, and stops looking. Replacement model: due, then late, with a verified allowance between them (Chapter 15.3). Debugging clue: a bug report whose evidence is that a due signal was high.
“Refresh timing is measured only in cycles.” Tempting because controllers count cycles and Module 14 taught cycle conversions. Why it is wrong: §2 publishes the interval in microseconds, because retention is physical and indifferent to the clock — Chapter 13.2 §4's argument exactly. Consequence: a cycle count carried across a frequency change under-refreshes at the lower clock. Replacement model: absolute time is the source of truth; the cycle count is derived per frequency. Debugging clue: corruption appearing after a frequency change with no configuration edit.
“More refresh is always safer and therefore always better.”
Tempting because §2 verified MIN = N/A, so there is genuinely no floor — extra refresh is specification-legal. Why it is wrong: it is safe for retention and costly for availability, and Chapter 15.5 computes the cost from verified figures. It is also not monotonically safer in a useful sense: once the rate is met, more refresh buys nothing against a device whose retention is in specification. Replacement model: legality and desirability are different questions. Debugging clue: availability short of the model with a refresh rate well above the requirement.
“A countdown timer alone proves refresh correctness.” Tempting because the timer is the mechanism and it either expires on schedule or it does not. Why it is wrong: §6 — a timer enforces the instant obligation. The specification constrains an average, and a design can satisfy an instantaneous owed-count bound continuously while averaging too slowly. Consequence: a verification plan that proves the timer works and says nothing about whether the device was refreshed often enough. Replacement model: an instant check for action, a windowed check for compliance. Debugging clue: a refresh test suite with no window or counter in it.
“A controller can model charge decay to decide when refresh is needed.” Tempting because the obligation originates in decay, so modelling it feels like modelling the real thing. Why it is wrong: a controller has no observability into charge whatsoever — no cell voltage, no per-row age, no retention measurement. §6's block sees a pulse and a cycle count, and that is all any controller sees. Consequence: RTL that claims to model retention, misleading every later reader, and a design that trusts a fiction instead of the published interval. Replacement model: physics determines the interval, the datasheet publishes it, the controller counts — Chapter 13.2 §1's boundary, applied to refresh. Debugging clue: any proposed design that needs to know a row's age.
12. Interview Reasoning
“Why does DRAM require refresh?” Charge stored on a cell leaks, so the value degrades toward the point where the sensing margin fails — Chapter 2.2's material. The part worth adding, and what distinguishes a good answer, is the system consequence: because every row leaks, the obligation is a rate over the whole population rather than one deadline, the device advances its own row pointer but only when commanded, and therefore the controller owes a service frequency it cannot skip and cannot observe failing.
“How is refresh specified differently from the timing parameters you have learned?” Inverted. Every parameter in Modules 13 and 14 is a minimum — do not act before this. Refresh is published as an average interval with MIN = N/A and a MAX — do not fail to act more slowly than this. So the obligation is on the controller rather than the device, nothing enforces it, refreshing more often is always legal, and because it is an average, individual intervals may vary.
“What is the difference between refresh interval and refresh cycle time?” Interval is service pressure — how often service must be delivered. Cycle time is service cost — how long the resource is unavailable once service starts. They are independent axes and fail independently: a design can honour the occupancy perfectly and still miss the rate, or hit the rate exactly and issue a command during the unavailable window. Two obligations, two checks; conflating them means having checked neither properly.
“What does it mean for refresh to be due but not late?” Due is the nominal service point — the interval has elapsed since the last service. Late is when the permitted deviation is exhausted. They differ because the specification constrains an average and explicitly allows some deferral. A controller that treats them as the same preempts traffic at moments when waiting was legal, and the cost is self-inflicted latency with no correctness benefit.
“Why is a countdown timer insufficient to verify refresh?” Because a timer checks the instantaneous condition and the specification constrains an average over time. A design can be within any instantaneous owed-count bound at every single cycle and still deliver service too slowly on average. Verifying the average needs a window and a counter, not an assertion on a cycle — which is also the practical difference between a safety property, which has a cycle number when it fails, and a bounded-service property, which fails by an absence.
“Can a controller decide when refresh is needed by modelling retention?” No, and the reason is observability rather than difficulty. A controller has no access to cell voltage, per-row age or retention margin. It holds a published interval and counts. That is not a simplification it gets away with — it is the entire contract, and the specification exists precisely so controllers need not model physics. Any proposed design that requires knowing a row's age is describing something the hardware cannot provide.
“Your system shows intermittent corruption and no timing checker has fired. Where do you look?” Refresh, precisely because nothing fires — a late refresh is accepted normally and reported by nobody. The fastest check is the operating temperature band against the configured interval, since the published interval halves twice across the bands and a design configured for the normal band running hot is under-refreshing by two or four times. After that, confirm the monitor ever produced a verdict at all: no violations and no evaluations look identical in a report and mean opposite things.
13. Engineering Exercises
1. Read the specification carefully. The datasheet gives tREFI MIN = N/A; MAX = 7.8 µs. State three things a controller designer should conclude from the MIN = N/A alone, and one thing that would change if it instead read MIN = 7.8 µs.
Worked: (a) refreshing more often than the interval is specification-legal, so pull-in is available; (b) there is no lower bound to violate, so a conservative design cannot break compliance by over-refreshing; (c) the obligation is one-directional, on the controller. If it read MIN = 7.8 µs instead, over-refreshing would become a violation — pull-in would be illegal, and Chapter 15.3's entire credit mechanism could not exist.
2. Derive the required service count. With an observation window of 40 cycles and an average interval bound of 6 cycles, compute REQUIRED. Then say whether 6 services in 40 cycles is compliant, and whether 6 services placed at cycles 0, 1, 2, 3, 4, 5 is compliant by this test.
Worked: REQUIRED = ceil(40/6) = 7, so 6 services is not compliant — the window demanded 7. And the placement question is the instructive half: 7 services all placed in the first 7 cycles would pass this test, because an average bound says nothing about distribution. That is a real limitation of the average check and exactly why Chapter 15.3 §3's maximum-gap rule exists as a separate requirement.
3. Find the leniency bug. A colleague computes the running verdict as rate_behind = (window_cycle / window_services) > INTERVAL_CYCLES using integer division. Identify two defects and say which direction each fails in.
Worked: first, division by zero when window_services is 0 — which is the state at the start of every window, exactly when being behind matters most. Second, integer division truncates, so an actual mean of 8.9 with an interval bound of 8 computes as 8 and reports compliant. Both failures are lenient — the monitor under-reports shortfalls, which is the worse direction for a monitor. The product form services × INTERVAL ≥ elapsed has neither defect.
4. Convert an interval to cycles. A device specifies the average interval as 7.8 µs. Give the cycle count at DDR4-3200 and at DDR4-2400, and say which direction to round and why.
Worked: DDR4-3200 has a CK of 1600 MHz, so tCK is 0.625 ns and 7.8 µs / 0.625 ns = 12,480 cycles. DDR4-2400 has tCK of 0.8333 ns, giving 9,360 cycles. Rounding must be down, which is the opposite of every conversion in Module 14 — because this is a maximum and rounding up would permit a longer interval than the device allows. Recognising that the rounding direction follows from min-versus-max, not from habit, is the point.
5. Explain why the monitor cannot prove correctness. §8 lists two things the assertions cannot establish. For each, say what evidence would establish it and who owns that evidence.
6. Distinguish the two property kinds. Classify each as safety-shaped or bounded-service: (a) no activate during the refresh unavailable window; (b) refresh debt never exceeds the allowance; (c) refresh is never issued before its bank precondition holds; (d) the average interval over any window is within specification. For each, say whether a failure has a cycle number.
Worked: (a) safety — yes, a cycle number. (b) bounded-service — the violation has a cycle number (the moment the bound is exceeded) but the cause is an absence over time, which makes it a hybrid worth discussing rather than a clean case. (c) safety — yes. (d) bounded-service — no single cycle number; the verdict belongs to a window. (b) is the interesting one, and noticing that it straddles the two is a better answer than forcing it into one.
7. Size a realistic window. A design refreshes with a 7.8 µs interval at DDR4-3200. Choose an observation window for §6's monitor, justify it, and say what goes wrong if it is one interval long, and if it is a thousand.
14. Summary
Chapter 2.3 modelled refresh as one deadline, which is the right abstraction for establishing that the obligation exists. A real device has a population of rows and a published rate, and three things follow that a single deadline cannot express: the work is divisible, so progress is partial; the device does the row indexing, so the controller owes a frequency and not an address; and nothing refuses a late refresh, so the controller cannot observe the failure it is responsible for avoiding.
The specification announces this by inverting. Verified from Micron's 16Gb DDR4 datasheet: the average periodic refresh interval is published as MIN = N/A; MAX = 7.8 µs in the −40°C to 85°C band, halving to 3.9 µs and then 1.95 µs as the case temperature rises. This is the first parameter in the curriculum specified as a maximum, and it has no minimum at all — which puts the obligation on the controller, makes over-refreshing always legal, and makes the constraint an average rather than a per-interval rule.
Six terms must stay distinct: interval, command, cycle time, deadline, debt and policy. The two most often confused are the first and third — interval is service pressure and cycle time is service cost — and they fail independently, so checking one proves nothing about the other.
The interval is derived, as a retention window divided by the commands needed to cover the population. §4 is explicit that I verified the interval and not its two factors, and that the widely repeated 8,192-commands framing is a consistency check rather than something I could establish from the primary document.
refresh_rate_obligation measures the average over a window, which Chapter 2.3's reused refresh_deadline_tracker does not — that block enforces the instant, and a design can stay within an instantaneous owed-count bound at every cycle while averaging too slowly. The check is a multiply-and-compare rather than a division, which removes the rounding decision entirely, and the rounding direction for the interval itself is down because it is a maximum.
And the module's verification frame: safety-shaped properties fail at a cycle; bounded-service properties fail by an absence. The second needs a window and a counter, and needs its completion covered — because “no violations” and “never evaluated” look the same in a report.
15. What Comes Next
This chapter has an interval and a service event, and has been deliberately vague about what a service event is.
Chapter 15.2 makes it concrete, and the question turns out to have more than one answer. Chapter 7.5 already established the REF command, its bank precondition and its occupancy. What it did not ask is what one refresh command retires — and that depends on the command's scope. A refresh that services the whole device retires one unit of a single rank-wide obligation and needs one counter. A refresh whose scope is narrower retires one unit per resource, needs a counter per resource, and requires the controller to decide which resource is next.
Same interval, same physics, completely different bookkeeping. And the scopes available depend on the generation, which is where the registry's own description of that chapter needs a correction I will make explicitly.
Continue learning
Related tutorials
- Related topic
The Refresh Manager
Refresh due, refresh legal, refresh issued and refresh complete are four distinct events separated by many cycles. The manager turns an obligation into the drain, the gate and the request a scheduler consumes.
- Related topic
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.
- Related topic
Refresh (REF)
Refresh is the first command whose legality depends on more than one bank, and the first that occupies the device rather than requesting a transfer. DDR5's same-bank variant exists precisely to weaken that precondition.
- Related topic
Refresh Commands
A refresh command's scope decides what it retires. Device-wide scope means one obligation and one counter; narrower scope means one obligation per resource, a counter each, and a pointer deciding which is next.
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.
