DDR · Module 32
Mobile SoCs
A mobile platform has two ceilings and only one is a budget: retention falls with temperature, so refresh power rises with it and the memory closes a positive feedback loop on itself. The controller acquires a third kind of obligation — it must be throttleable, with authority over the term that closes the loop.
Chapter 32.1 found a mix that was heterogeneous in obligation. A mobile platform's mix is not. Its requesters are numerous but they are broadly alike, and the interesting thing about them is not what they ask for.
What is interesting is that the constraint binding them changes while they are running.
A mobile platform is designed against two ceilings at once — total energy from the battery, and instantaneous heat flow through the case — and a design can satisfy either and fail the other. The heat ceiling is different in kind, because DRAM's own maintenance cost rises with temperature, so the memory closes a positive feedback loop on itself.
CURRICULUM-DERIVED from 24.1 §4, which owns both ceilings and names the loop: retention falls as temperature rises, so a hot device must refresh more often — refreshing more often costs more power, which produces more heat. That chapter states the loop exists and reports the magnitude that makes it matter: self-refresh current on a real device rises by more than a factor of twenty between a cool part and a hot one.
This chapter analyses that loop and draws the consequence nothing else does.
The loop does not have to run away to hurt. It amplifies every other heat source in the device by a factor of one over one minus the loop gain — so a memory problem presents as a whole-device thermal problem, and the quantity that destroys the margin is the thermal path rather than the memory.
And the decision it forces is an obligation the controller has not carried in thirty-one chapters: it must be able to be told to slow down, within a bounded time, without violating anything — and the throttle must have authority over the term that closes the loop, which §13's defect does not.
1. The Shared Baseline, and This Chapter's Question
CURRICULUM-DERIVED from 32.1 §1, which owns this module's baseline: all five platform classes carry the same thirteen obligations of 31.1 §5, none removes any, and the module's question is always which constraint dominates, what decision it forces, and what grade of evidence exists.
For this platform class the three answers are:
1 WHICH CONSTRAINT
two ceilings -- energy and heat -- and the heat ceiling
closes a POSITIVE FEEDBACK LOOP through refresh (§3)
2 WHAT DECISION
the controller must be THROTTLEABLE, with a bounded
response time and authority over the LOOP term (§6, §7)
3 WHAT GRADE
mostly B and D. The mechanisms are documented -- PASR,
temperature-compensated self refresh, the state set -- and
the VALUES are per-device and per-platform (§9)And one thing this chapter must say up front, because 31.2 proved it: axis A1 is identical. The same destructive read, the same restore, the same twenty-two obligations that chapter counted. So nothing below is a structural difference between memory technologies — it is what a platform does to a controller whose contract has not changed.
2. Two Ceilings, and Only One Is a Budget
CURRICULUM-DERIVED from 24.1 §4 and 24.1 §5, which own both ceilings. The distinction this chapter needs is what kind of constraint each one is.
| Energy ceiling | Heat ceiling | |
|---|---|---|
| Set by | the battery and a target life for a defined usage pattern | how fast heat leaves the case |
| Quantity | energy — a budget, integrated over time | power — a rate, instantaneous |
| Violated by | using too much in total | dissipating too much at once, for long enough |
| Response available | reduce work, reduce cost per unit, raise the allowance | reduce the rate, now |
| Is it a feasibility question? | yes — 24.1 §5 owns that framing | no — it is a control problem |
| Can the memory make it worse by itself? | no | yes — §3 |
Row five is the structural difference and it is why this chapter exists.
CURRICULUM-DERIVED from 24.1 §5, the energy ceiling is a feasibility question with a stopping point — given this allowance and this usage pattern, what memory behaviour fits inside it — and it has exactly three levers: reduce the work, reduce the cost per unit of work, or increase the allowance. All three are design-time decisions. Once the budget closes with margin, further reduction buys nothing.
The heat ceiling has no design-time closure, because the thermal path is not a property of the design. A device in a pocket, a device on a car dashboard and a device on a bench have different thermal paths and the same silicon — so the heat ceiling must be met at runtime, by a mechanism, under conditions the designer does not control.
And row six is the one nothing else states. The energy ceiling is passive: spending more energy does not make energy cheaper or dearer. The heat ceiling is active, because the memory's own maintenance cost is a function of the temperature it is helping to produce.
3. The Loop
CURRICULUM-DERIVED from 24.1 §4, which names it: retention falls as temperature rises — 2.3 §4 owns the physics and 15.4 owns temperature as a specified operating condition rather than a physical model — so a hot device must refresh more often, refreshing more often costs more power, and more power produces more heat.
the loop, as a signal path
temperature T
|
| retention falls (2.3 §4)
v
required refresh RATE rises (15.4: a specified condition,
| expressed as a temperature band)
| each refresh costs energy (15.5)
v
refresh POWER rises
|
| dissipated through the thermal path
v
temperature T <-- closes hereTwo properties of that path make it a control problem rather than a caution.
The gain is not small, because the temperature dependence is not small. CURRICULUM-DERIVED from 24.2 §7 as reported by 24.1 §4: self-refresh current on a real device rises by more than a factor of twenty between a cool part and a hot one. That is a measured ratio on a named device — the strongest evidence in this chapter — and §4 is what it implies.
And the loop operates precisely when the device is least able to respond. The refresh obligation is the one the controller cannot decline: CURRICULUM-DERIVED from 15.3, the accrual is a ledger with a bounded postponement allowance, so refresh is deferrable by a bounded amount and not cancellable. Chapter 17.3 §2 owns the sharper form — refresh is not a request and during occupancy normal commands are illegal, not deprioritised. So the loop term is the one term in the power budget that a traffic throttle cannot touch, which is §13's defect stated in advance.
4. The Loop Gain, Derived
A first-order model, and every number in it is grade D. The form is the transferable part, and it rests on exactly one measured input.
DEFINITIONS
T temperature rise above ambient K
P_ext all heat EXCEPT memory refresh W
P_ref(T) refresh power, rising with T W
theta thermal resistance of the path out K/W
k dP_ref/dT, the loop's slope W/K
the steady state, with the loop OPEN (refresh fixed):
T = theta * (P_ext + P_ref)
with the loop CLOSED (refresh rises with T):
T = theta * (P_ext + P_ref0 + k*T)
solve for T:
T * (1 - theta*k) = theta * (P_ext + P_ref0)
T = theta * (P_ext + P_ref0) / (1 - G) where G = theta * k
DERIVED. TWO results, and the second matters more:
STABILITY : the loop is stable iff G < 1.
at G >= 1 there is no steady state -- temperature
rises until something else limits it.
AMPLIFICATION : below G = 1, EVERY heat source in the device
is amplified by 1 / (1 - G).
The memory does not need to be the heat source
to be the problem.Now put grade-D numbers on it, using the one CURRICULUM-DERIVED ratio.
GRADE D, chosen for legibility. The RATIO is CURRICULUM-DERIVED
from 24.2 §7 -- more than 20x cool-to-hot -- and the span and the
absolute values are invented.
refresh power, cool part P_ref = 0.05 W
refresh power, hot part (+40 K) P_ref = 1.00 W (20x)
DERIVED slope k = (1.00 - 0.05) / 40 = 0.024 W/K
three thermal paths, all GRADE D:
path theta G = theta*k 1/(1-G)
------------------ -------- ----------- -------
on a bench, open 15 K/W 0.356 1.55
in a pocket 40 K/W 0.950 20.0
insulated / blocked 45 K/W 1.080 NONE
DERIVED, all recomputed. And read the third column rather than
the second: at theta = 15 the loop costs 55% extra temperature
rise; at theta = 40 it costs TWENTY TIMES.Three conclusions, and the first is the chapter's headline.
The loop amplifies the whole device, not just the memory. DERIVED from the closed form: 1/(1−G) multiplies P_ext as well as P_ref0. So a display, a radio or a compute burst that raises temperature gets its thermal effect multiplied by the memory's refresh loop — and the resulting investigation looks at whichever subsystem grew, not at the memory that amplified it.
The margin is not large and it is destroyed by the thermal path, not by the memory. DERIVED: theta moves from 15 to 45 without a single change to the silicon, and G crosses 1 on the way. CURRICULUM-DERIVED from 24.1 §4: the ceiling is the thermal path. So the memory's stability is a property of how the user is holding the device.
And the settling time degrades before the stability does. DERIVED: a first-order loop's time constant scales as 1/(1−G) too, so at G = 0.95 the device takes twenty times longer to reach its final temperature. A throttle whose response time was validated at G = 0.356 is twenty times too slow at G = 0.95 — which is §7's first requirement, and the reason it is a requirement rather than a preference.
5. Sustained Is Not Burst
CURRICULUM-DERIVED from 24.1 §4: a device can dissipate more for a short period than it can sustain, because its mass absorbs heat before the temperature rises — so a memory subsystem may be allowed a high peak power and a much lower average, which is a different constraint from a battery budget and can bind first.
This chapter's contribution is what that means for the controller, and it is not obvious.
the two limits, as controller requirements
BURST limit -- an instantaneous power cap
enforced by: nothing. The device's thermal mass absorbs it.
controller requirement: NONE. A burst is free.
SUSTAINED limit -- an average over a thermal time constant
enforced by: temperature rising until something responds
controller requirement: the throttle of §6, and its response
time must be short RELATIVE TO THE THERMAL TIME CONSTANT --
not relative to anything in the memory's own timing.So the throttle's deadline comes from outside the memory entirely, and that is unusual: every other bounded response in this curriculum is bounded by a memory parameter. CURRICULUM-DERIVED from 13.3, the constraint classes are all command-to-command. A thermal response deadline is set by a thermal mass, and no DRAM parameter appears in its derivation.
Two consequences that are design requirements.
The throttle must not be engaged for bursts. A controller that throttles on instantaneous power gives up performance the thermal mass had already paid for. So the throttle's input is a filtered temperature or a windowed power, never an instantaneous one — and §11's block filters.
And the window length is a platform property, not a memory one. It must be configured, not compiled — which is 32.1 §13's defect class, and §11 takes it as an input for exactly that reason.
6. The Decision — Throttleability
In thirty-one chapters the controller has never been required to do less than it can. Every obligation so far has been of two kinds: do not do this (legality) or do this within a bound (progress, refresh, write delivery). Throttleability is a third kind, and its novelty is worth stating.
| Obligation kind | Example | What violates it |
|---|---|---|
| Safety — never | no column command before the row-to-column separation — 13.3 | doing something |
| Progress — within a bound | every accepted request completes — 30.9 §5 | not doing something |
| Throttleability — do LESS, on request, within a bound | this chapter | continuing at full rate |
And it interacts with the second kind in a way that must be resolved rather than ignored. A throttle that slows the controller extends every progress bound, so the two obligations are in tension: CURRICULUM-DERIVED from 30.9 §5 Q2, a progress bound must be justified from the worst legitimate wait — and a throttle makes the worst legitimate wait a function of temperature.
The resolution is that the progress bound must be stated per throttle level, not once. A single bound justified at full rate is violated by a correct throttle; a single bound justified at the deepest throttle is uselessly loose at full rate. So throttling turns one bound into a small table, and §17 asserts it that way.
7. What a Throttle Must Satisfy
Three requirements, and the second is the one §13's defect fails.
Requirement 1 — bounded response time, measured against the thermal time constant. §4's result that the time constant scales as 1/(1−G) means the response must be fast enough at the worst G the platform permits, not the nominal one. DERIVED: validating at theta = 15 and shipping into a pocket leaves the response twenty times too slow.
Requirement 2 — sufficient AUTHORITY, over the term that closes the loop. A throttle can only reduce power it controls. §3 established that the loop term is refresh, and 17.3 §2 that refresh is not a request and cannot be declined. So a throttle with authority only over traffic cannot reduce the loop term at all, and its loop gain is unchanged however hard it throttles.
The mechanisms that do have authority over the loop are documented, and they are grade B. CURRICULUM-DERIVED from 24.1 §8, which lists them from a device's own feature summary: partial-array self refresh and temperature-compensated self refresh are supported functions, both of which exist to reduce the idle cost. Chapter 24.2 §9 owns PASR as a mask with a retention consequence — a region excluded from refresh is not preserved — so using it is a data-placement decision, not a knob.
Requirement 3 — hysteresis, and it is mandatory rather than an optimisation. CURRICULUM-DERIVED from 23.5, which owns that result for page policy: a predictor that flips on every change of evidence pays the switching cost continuously and can be worse than either fixed choice. The same argument applies here with a physical mechanism underneath it: throttling lowers temperature, which clears the throttle, which raises temperature. Without hysteresis the loop of §3 becomes an oscillator, and 24.2 §14 records the analogous corner case where a device oscillates because its predictor is wrong in both directions alternately.
So the throttle has three parameters and all three must be justified: a response deadline from the thermal time constant, an authority set naming which power terms it can reduce, and a hysteresis band wide enough that a throttle's own effect cannot immediately clear it.
8. What the Mix Is — and Is Not
Chapter 32.1 §3 found four classes with unequal obligations. This platform has the same four classes and they are not the interesting thing, and saying so explicitly is part of the comparison.
CURRICULUM-DERIVED from 24.1 §6, which owns the requester mix: many small requesters. Their obligations are the same four of 32.1 §3 — the classes are a property of the mechanisms that generate traffic, and those mechanisms are not platform-specific.
What is platform-specific is that the whole mix is subject to an external limiter.
32.1's platform: the mix is HETEROGENEOUS in obligation.
the controller must distinguish WHO is asking.
this platform: the mix is homogeneous enough, and the
controller must instead respond to something
that is not asking at all -- a thermal state
with no request, no queue entry and no class.
STRUCTURAL: the throttle is an input with no requester behind it.
Every other input to the scheduler in thirty-one chapters came
from something that wanted memory. This one comes from physics.That is why throttleability is a new obligation kind rather than a new class. A class is a property of a request; a throttle is a property of the environment — and 30.5 §3's four-stage separation has no stage for it. It enters as a modifier on policy, and §11 places it there.
9. The Evidence Situation
§Scope's grades, applied to this platform class, and the shape differs from 32.1 §5's.
| What you might want | Best grade available | Why |
|---|---|---|
| The state set and which transitions are illegal | A/B | 24.2 §1 owns it as the device's, not a textbook's, from device documentation |
| That PASR and temperature-compensated self refresh exist as functions | A | 24.1 §8 cites a device's own feature summary |
| The self-refresh current ratio cool-to-hot | A, for that device | 24.2 §7 — more than twenty-fold, measured |
| Per-bank refresh current, all-bank versus per-bank | A, and it contradicts a common claim | 24.2 §8 — identical on every rail |
| An exit energy for a low-power state | none | 24.2 §5: datasheets publish exit latency and steady-state current, which cannot be combined without the voltage and the activity during exit |
| The thermal resistance of a platform | none, ever, from a memory source | it is a property of the enclosure, the board and the user |
| A particular SoC's throttle policy | C or D | it is firmware, and it is usually not published |
Two observations that are the useful output.
The mechanisms are documented and the operating point is not — which is 18.4 §2's pattern exactly, and the response is the same: read the configuration. CURRICULUM-DERIVED from 24.2 §5's refusal to invent an exit energy, this chapter's grade-D figures follow that practice: the relationships are the content and the constants are placeholders.
And one row has no grade at all from any memory source. theta is not a memory property. §4's whole result turns on it, and no DRAM datasheet will ever supply it — so the loop gain is a system-integration number that the memory team must ask for and usually cannot compute. That is the honest finding of this section, and §18's row one is its consequence.
10. The Platform, as Blocks
Trace the cycle: device → thermal path → temperature → refresh manager → commit → device. That is §3's loop, and it is a closed path through the diagram — the only closed path in any diagram in this module.
And look at the two edges leaving the throttle. limit to policy and mode to the refresh manager. Both are required, and §13's defect is the block with only the first. CURRICULUM-DERIVED from 17.3 §2, the refresh path reaches the commit point independently of policy, so a throttle that modifies policy alone has no path to the loop at all.
11. RTL — A Thermal Response Path
The platform-profile block for this chapter. THERMAL_LIMITED is the platform property, and the generate boundary shows that a platform with a fan needs none of this — which is the comparison this module is built on.
// ---------------------------------------------------------------------
// thermal_response -- the platform-profile block of §11.
//
// CLASSIFICATION: synthesisable, grade-D parameter values, CORRECT as
// written. The intentionally defective block is §12.
//
// WHAT IT IS: §7's three requirements as hardware -- a bounded
// response, an AUTHORITY SET that includes the refresh term, and
// mandatory hysteresis. It is a MODIFIER on policy and on the refresh
// manager, not a requester: §8 establishes that a thermal state has
// no queue entry and no class.
//
// WHY IT EXISTS HERE: §4 derives that the loop amplifies every heat
// source by 1/(1-G) and that G is set by a thermal path the memory
// does not own. So the response cannot be designed open-loop; it must
// be a mechanism with stated authority, and §7 is its specification.
//
// HOW TO RUN IT: drive filt_temp above the level-1 threshold and hold
// it there.
// EXPECTED RESULT: policy_limit AND refresh_mode_req both change
// within RESP_DEADLINE cycles, and neither clears until filt_temp
// falls below the engage threshold by HYST_K.
// EXPECTED TRACE: refresh_mode_req must move. A response that
// changes only policy_limit has no authority over the loop (§13).
//
// SYNTHESIS: one level comparator chain, one deadline counter, one
// hysteresis register. No memory.
//
// LIMITATIONS: this block DECIDES the response. It does not filter --
// WIN_LEN is a platform property and filt_temp is an INPUT, per §5's
// requirement that the window be configured rather than compiled
// (32.1 §13's defect class). Nor does it implement PASR's mask: 24.2
// §9 owns that as a mask with a RETENTION consequence, so selecting
// a region is a data-placement decision this block must not make
// unilaterally -- it requests a mode and the placement owner
// consents. That boundary is STATED and is not the bug.
// ---------------------------------------------------------------------
module thermal_response #(
// The platform property. A fanned platform has no runtime heat
// ceiling in this sense, so the mechanism is ABSENT rather than
// disabled -- §2's row five.
parameter bit THERMAL_LIMITED = 1'b1,
parameter int LEVELS = 3,
// Grade D. Engage thresholds, in filtered-temperature units. They
// are PARAMETERS here and should be configuration inputs on a real
// platform, for 32.1 §13's reason: a threshold is a platform
// property and a platform property in a parameter is grade D
// consumed as grade A.
parameter int T_L1 = 70,
parameter int T_L2 = 80,
parameter int T_L3 = 88,
// §7 requirement 3. Mandatory, not an optimisation: without it the
// loop of §3 becomes an oscillator (23.5's hysteresis argument
// with a physical mechanism underneath).
parameter int HYST_K = 4,
// §7 requirement 1. Derived from the THERMAL time constant, which
// is not a memory quantity -- §5. It must be short enough at the
// WORST permitted G, not the nominal one (§4's third conclusion).
parameter int RESP_DEADLINE = 2000,
// COUNT, not INDEX: the deadline counter must REPRESENT
// RESP_DEADLINE, so it needs $clog2(RESP_DEADLINE + 1) bits. Sized
// $clog2(RESP_DEADLINE) it saturates one short of the deadline it
// enforces, and the deadline check becomes unreachable -- a
// response requirement present in the source and absent in the
// silicon (31.2 §7).
parameter int DL_W = $clog2(RESP_DEADLINE + 1),
parameter int TMP_W = 8,
parameter int LVL_W = $clog2(LEVELS + 1)
)(
input logic clk,
input logic rst_n,
// §5: FILTERED, never instantaneous. A burst is free and must not
// engage the throttle.
input logic [TMP_W-1:0] filt_temp,
input logic filt_valid,
// Authority set -- BOTH outputs are required (§7 requirement 2).
output logic [LVL_W-1:0] level,
output logic [LVL_W-1:0] policy_limit,
output logic [1:0] refresh_mode_req,
output logic response_late,
output logic [LVL_W-1:0] authority_reported
);
// Refresh mode requests. The MECHANISMS are grade B -- 24.1 §8
// cites a device feature summary listing partial-array self refresh
// and temperature-compensated self refresh as supported functions.
// The ENCODING here is local to this block.
localparam logic [1:0] RM_NORMAL = 2'd0;
localparam logic [1:0] RM_TCSR = 2'd1; // temperature-compensated
localparam logic [1:0] RM_PASR = 2'd2; // masked, WITH consent
initial begin
if (LEVELS < 1) $fatal(1, "thermal_response: LEVELS >= 1");
if (!(T_L1 < T_L2 && T_L2 < T_L3))
$fatal(1, "thermal_response: thresholds must be strictly increasing");
// §7 requirement 3, enforced: a hysteresis band wider than the
// gap between two levels would make the upper level
// unreachable once entered from below.
if (HYST_K >= (T_L2 - T_L1))
$fatal(1, "thermal_response: HYST_K (%0d) >= level gap (%0d): a level becomes unreachable",
HYST_K, T_L2 - T_L1);
if (RESP_DEADLINE < 1) $fatal(1, "thermal_response: RESP_DEADLINE >= 1");
end
generate
if (THERMAL_LIMITED) begin : g_thermal
logic [LVL_W-1:0] lvl_q, lvl_target;
logic [DL_W-1:0] dl_cnt;
logic pending;
// The level decision, WITH hysteresis. Engage on crossing up;
// disengage only after falling HYST_K below the engage point.
// Written as an explicit comparison against (threshold - HYST_K)
// on the way down rather than as a single band, because the two
// directions genuinely differ -- and a single band is the bug
// 23.5 warns about.
always_comb begin
lvl_target = lvl_q;
if (filt_valid) begin
// Upward: plain thresholds.
if (filt_temp >= T_L3[TMP_W-1:0]) lvl_target = LVL_W'(3);
else if (filt_temp >= T_L2[TMP_W-1:0]) lvl_target = (lvl_q > 2) ? lvl_q : LVL_W'(2);
else if (filt_temp >= T_L1[TMP_W-1:0]) lvl_target = (lvl_q > 1) ? lvl_q : LVL_W'(1);
// Downward: only below (threshold - HYST_K).
if (lvl_q == 3 && filt_temp < (T_L3 - HYST_K)) lvl_target = LVL_W'(2);
if (lvl_q == 2 && filt_temp < (T_L2 - HYST_K)) lvl_target = LVL_W'(1);
if (lvl_q == 1 && filt_temp < (T_L1 - HYST_K)) lvl_target = LVL_W'(0);
end
end
// The response, with its deadline. `pending` is set when the
// target changes and cleared when the outputs have followed;
// `response_late` is the observable §7 requirement 1 needs, and
// it exists because a deadline nobody measures is a wish.
always_ff @(posedge clk) begin
if (!rst_n) begin
lvl_q <= '0;
dl_cnt <= '0;
pending <= 1'b0;
response_late <= 1'b0;
end else begin
if (lvl_target != lvl_q) begin
pending <= 1'b1;
dl_cnt <= '0;
lvl_q <= lvl_target; // the response IS the level move
end else if (pending) begin
// The outputs are combinational from lvl_q, so the response
// completes the cycle after the level moves. The counter
// exists to catch a design where it does NOT -- which is
// why the check is kept even though it is currently
// unreachable. 30.5 §11: a guard another guard always
// shadows is untested, so §16's cover watches it.
pending <= 1'b0;
end
if (pending && dl_cnt != {DL_W{1'b1}}) dl_cnt <= dl_cnt + 1'b1;
if (pending && dl_cnt >= RESP_DEADLINE[DL_W-1:0]) response_late <= 1'b1;
end
end
assign level = lvl_q;
// AUTHORITY -- §7 requirement 2, and BOTH terms. policy_limit
// reduces the term the controller chooses; refresh_mode_req
// reduces the term that CLOSES THE LOOP (§3) and which 17.3 §2
// establishes cannot be declined.
assign policy_limit = lvl_q;
always_comb begin
unique case (lvl_q)
LVL_W'(0) : refresh_mode_req = RM_NORMAL;
// Level 1 asks for temperature-compensated self refresh: the
// device adjusts its own rate to the condition rather than
// running the worst-case rate always. 24.1 §8 lists it as a
// supported function; the VALUE of the saving is per-device.
LVL_W'(1) : refresh_mode_req = RM_TCSR;
LVL_W'(2) : refresh_mode_req = RM_TCSR;
// Level 3 REQUESTS a masked mode. It is a request and not a
// command because 24.2 §9 owns PASR as a mask with a
// RETENTION consequence -- an excluded region is not
// preserved -- so the placement owner must consent.
default : refresh_mode_req = RM_PASR;
endcase
end
// §9's finding, as an output: theta is not a memory property, so
// the loop gain cannot be computed here and must be MEASURED.
// This reports what authority was actually applied, which is the
// input §14's monitor needs to recompute G.
assign authority_reported = lvl_q;
end else begin : g_fanned
// A platform with a fan has no runtime heat ceiling in this
// sense. The mechanism is absent, and every output is inert --
// not "disabled", which would imply it could be enabled.
assign level = '0;
assign policy_limit = '0;
assign refresh_mode_req = RM_NORMAL;
assign response_late = 1'b0;
assign authority_reported = '0;
end
endgenerate
endmodulerefresh_mode_req is the output that distinguishes this block from §12's, and it is worth saying why it is a request rather than a command. CURRICULUM-DERIVED from 24.2 §9: PASR is a mask with a retention consequence, so excluding a region from refresh means its contents are gone. A thermal block that unilaterally discarded memory to cool the device would be trading correctness for temperature, and the placement owner is the only party that can consent. So the deepest level asks, and something above it answers.
12. RTL Review — A Throttle
The intended contract:
- On a filtered temperature crossing a level threshold, engage that level within
RESP_DEADLINEcycles. - The reduction must include the refresh term, because §3 establishes refresh as the term that closes the loop and 17.3 §2 that refresh is not a request the scheduler can decline.
- Engage only on a filtered temperature, never an instantaneous one — §5.
- Hysteresis: once engaged at a level, do not disengage until the filtered temperature has fallen
HYST_Kbelow that level's engage threshold. - Report the achieved authority, so §9's unmeasurable loop gain can be recomputed from observation.
// ---------------------------------------------------------------------
// traffic_throttle -- INTENTIONALLY DEFECTIVE, for review (§12).
//
// CLASSIFICATION: synthesisable, grade-D values, and CONTAINS A BUG.
//
// WHAT IT IS MEANT TO DO: the five-clause contract above -- reduce the
// controller's contribution to dissipation on request, within a
// deadline, with hysteresis, including the loop term.
//
// WHY IT EXISTS HERE: §7 requirement 2 is AUTHORITY, and §3 names the
// term that closes the loop. This block is what happens when a
// throttle is given authority over the power it can SEE -- traffic --
// and none over the power that closes the loop. It is the obvious
// design, which is why it is the dangerous one.
//
// HOW TO RUN IT: hold filt_temp above T_L3 on a platform where the
// refresh term dominates dissipation.
// EXPECTED RESULT under clause 2: refresh_mode_req moves away from
// RM_NORMAL.
// EXPECTED TRACE: at maximum level, BOTH outputs must have changed.
// Only one does.
//
// SYNTHESIS: a comparator chain and a hysteresis register.
//
// LIMITATIONS: decides the response only; filtering is upstream, per
// §5. That is STATED and is not the bug.
// ---------------------------------------------------------------------
module traffic_throttle #(
parameter int T_L1 = 70, // grade D
parameter int T_L2 = 80,
parameter int T_L3 = 88,
parameter int HYST_K = 4,
parameter int RESP_DEADLINE = 2000,
parameter int TMP_W = 8,
parameter int LVL_W = 2,
parameter int DL_W = $clog2(RESP_DEADLINE + 1)
)(
input logic clk,
input logic rst_n,
input logic [TMP_W-1:0] filt_temp,
input logic filt_valid,
output logic [LVL_W-1:0] level,
output logic [LVL_W-1:0] policy_limit,
output logic [1:0] refresh_mode_req,
output logic response_late
);
localparam logic [1:0] RM_NORMAL = 2'd0;
logic [LVL_W-1:0] lvl_q;
logic [DL_W-1:0] dl_cnt;
logic pending;
initial begin
if (HYST_K >= (T_L2 - T_L1))
$fatal(1, "traffic_throttle: HYST_K >= level gap");
end
// Clauses 1, 3 and 4 are ALL HONOURED. The level moves only on a
// filtered temperature; hysteresis is applied in the downward
// direction only; the deadline is counted and reported. A reviewer
// checking "does this throttle respond correctly?" finds that it
// does, and that is what conceals the defect.
always_ff @(posedge clk) begin
if (!rst_n) begin
lvl_q <= '0; dl_cnt <= '0; pending <= 1'b0; response_late <= 1'b0;
end else if (filt_valid) begin
logic [LVL_W-1:0] tgt;
tgt = lvl_q;
if (filt_temp >= T_L3[TMP_W-1:0]) tgt = LVL_W'(3);
else if (filt_temp >= T_L2[TMP_W-1:0]) tgt = (lvl_q > 2) ? lvl_q : LVL_W'(2);
else if (filt_temp >= T_L1[TMP_W-1:0]) tgt = (lvl_q > 1) ? lvl_q : LVL_W'(1);
if (lvl_q == 3 && filt_temp < (T_L3 - HYST_K)) tgt = LVL_W'(2);
if (lvl_q == 2 && filt_temp < (T_L2 - HYST_K)) tgt = LVL_W'(1);
if (lvl_q == 1 && filt_temp < (T_L1 - HYST_K)) tgt = LVL_W'(0);
if (tgt != lvl_q) begin pending <= 1'b1; dl_cnt <= '0; lvl_q <= tgt; end
else if (pending) pending <= 1'b0;
if (pending && dl_cnt != {DL_W{1'b1}}) dl_cnt <= dl_cnt + 1'b1;
if (pending && dl_cnt >= RESP_DEADLINE[DL_W-1:0]) response_late <= 1'b1;
end
end
assign level = lvl_q;
assign policy_limit = lvl_q;
assign refresh_mode_req = RM_NORMAL; // <-- THE DEFECT
endmoduleBefore reading on: which clause, and why did this pass thermal validation on the bench?
13. The Defect — Authority Over the Power It Can See
The violated clause is 2. refresh_mode_req is tied to RM_NORMAL at every level, so the throttle has no authority over the term that closes the loop.
And clauses 1, 3 and 4 being honoured is what conceals it. The block responds within its deadline, filters correctly, and applies hysteresis in the right direction — so every property a reviewer thinks to check about a throttle passes. A throttle that responds promptly to the wrong thing looks exactly like a throttle that works.
The arithmetic, and it is §4's model with the throttle applied.
GRADE D. Suppose at the hot operating point the memory's
dissipation splits as:
traffic-dependent term P_traf = 0.60 W
refresh term P_ref = 1.00 W (the 20x figure,
CURRICULUM-DERIVED ratio)
THIS BLOCK at maximum level: P_traf -> ~0, P_ref unchanged.
power removed 0.60 W
loop slope k UNCHANGED at 0.024 W/K
loop gain G = theta*k UNCHANGED
DERIVED, at theta = 40 K/W (a pocket, §4):
G = 0.950, amplification 1/(1-G) = 20.0
so the 0.60 W that was removed reduces the steady-state rise
by 0.60 * 40 = 24 K open-loop -- but the loop is still
amplifying everything that remains by TWENTY.
and the failure mode: as temperature keeps rising, P_ref rises
further, which the throttle cannot touch. The throttle escalates
to maximum, reports "engaged, level 3, responded on time", and
the temperature continues to climb.The correct block reduces k itself, which is the only action that changes G. CURRICULUM-DERIVED from 24.1 §8, temperature-compensated self refresh exists precisely to make the rate follow the condition instead of the worst case — so it acts on the slope rather than on the offset, and acting on the slope is what a loop requires.
Now the review question: why did it pass validation?
Because on a bench the loop term is negligible. DERIVED from §4's grade-D figures: at a cool operating point P_ref = 0.05 W against P_traf = 0.60 W, so traffic is more than 90% of the memory's dissipation and throttling it is genuinely effective. The test is a real, passing, end-to-end thermal validation — of a condition in which the defect cannot manifest.
And that is the same shape as 32.1 §13's defect one chapter earlier: a constant validated on the first platform, a throttle validated at the first thermal path. In both cases the test was correct and the operating point was unrepresentative — which makes the generalisation worth stating.
A mechanism whose authority is a fraction of the total is validated by a test in which that fraction is large. The validation condition must be chosen from where the mechanism is WEAKEST, not from where the platform usually sits — and for a thermal mechanism the weakest point is the hottest, which is also the hardest to reproduce.
The correction, and it is an interface addition rather than a logic change:
// CORRECTED. Clause 2: the response must include the LOOP term.
// The policy limit acts on the OFFSET; the refresh mode acts on
// the SLOPE, and only the slope changes G (§4).
//
// The deepest level REQUESTS a masked mode rather than commanding
// it, because 24.2 §9 owns PASR as a mask with a retention
// consequence -- so this block gains a handshake it did not have.
always_comb begin
unique case (lvl_q)
LVL_W'(0) : refresh_mode_req = RM_NORMAL;
LVL_W'(1),
LVL_W'(2) : refresh_mode_req = RM_TCSR;
default : refresh_mode_req = RM_PASR;
endcase
endThree interface consequences the correction creates, stated rather than assumed. The block gains RM_TCSR and RM_PASR encodings and therefore a contract with the refresh manager. It gains a consent path for the masked mode, because 24.2 §9's retention consequence means the placement owner must agree. And it gains an authority_reported output, because §9 established that theta is not a memory property, so the loop gain can only ever be measured — and measuring it requires knowing what authority was actually applied. §14 is that measurement.
The general finding:
A throttle's specification is not its response time. It is its AUTHORITY SET — the list of power terms it can reduce — and a throttle whose authority set omits a term in the feedback path cannot change the loop gain however fast and however deeply it engages.
14. RTL — Measuring the Loop
§9 established that theta is not a memory property and never will be, so §4's loop gain cannot be computed by the memory team. It can be measured, and this block is the measurement — which makes it the only way the whole analysis becomes actionable rather than illustrative.
// ---------------------------------------------------------------------
// loop_gain_monitor -- verification/telemetry, CORRECT as written.
//
// CLASSIFICATION: synthesisable telemetry. Drives nothing. Grade-D
// parameter values, and it computes NO physical constant.
//
// WHAT IT DOES: samples the filtered temperature and the refresh rate
// over a window and reports the OBSERVED slope between them, plus the
// applied authority. The slope is k of §4; theta must come from the
// platform, and the two together give G.
//
// WHY IT EXISTS HERE: §9's honest finding is that theta has no grade
// from any memory source. So the memory team can supply exactly one
// half of the loop gain -- k -- and this block supplies it as a
// measurement rather than a claim. 18.4 §1's discipline: the number
// this reports is grade C about THIS machine, and it must be carried
// with that qualification.
//
// HOW TO RUN IT: let temperature drift across a band under steady
// traffic, and read the slope.
// EXPECTED RESULT: a non-zero slope whose sign is positive --
// refresh rate rises with temperature (2.3 §4, 15.4).
//
// SYNTHESIS: two accumulators, one min/max tracker, one subtract.
// NO divider: the slope is reported as a numerator and a denominator
// so the consumer owns the rounding -- 27.5 refuses a lone
// percentage and 30.8 §11 requires a derived statistic's range to be
// visible.
//
// LIMITATIONS: reports k, not G. It cannot measure theta, it cannot
// detect a throttle whose authority is wrong -- §12's defect
// produces a PERFECTLY VALID k -- and it says so rather than
// implying coverage it does not give (27.3's independence
// discipline). What it CAN show is that k did not fall when the
// throttle engaged, which is §12's signature.
// ---------------------------------------------------------------------
module loop_gain_monitor #(
parameter int WIN = 1048576,
parameter int TMP_W = 8,
// COUNT, not INDEX: the refresh accumulator must represent a window
// in which every cycle carried a refresh, so it needs
// $clog2(WIN + 1) bits. Sized for an expected rate it would
// saturate at exactly the hot operating point the loop analysis is
// about, and report a FALLING rate as temperature rose.
parameter int CNT_W = $clog2(WIN + 1),
parameter int LVL_W = 2
)(
input logic clk,
input logic rst_n,
input logic [TMP_W-1:0] filt_temp,
input logic filt_valid,
input logic ref_issued,
input logic [LVL_W-1:0] authority_applied,
input logic win_tick,
// The slope, as a PAIR. num / den is k in refreshes per degree.
output logic signed [CNT_W:0] slope_num,
output logic signed [TMP_W:0] slope_den,
output logic [CNT_W-1:0] r_refresh,
output logic [TMP_W-1:0] r_t_min,
output logic [TMP_W-1:0] r_t_max,
output logic [LVL_W-1:0] r_authority,
output logic span_too_small,
output logic result_valid
);
initial begin
if (WIN < 2) $fatal(1, "loop_gain_monitor: WIN >= 2");
end
logic [CNT_W-1:0] c_ref, c_ref_cold, c_ref_hot;
logic [TMP_W-1:0] t_min, t_max;
logic [TMP_W-1:0] t_mid;
logic [LVL_W-1:0] auth_max;
always_ff @(posedge clk) begin
if (!rst_n) begin
c_ref <= '0; c_ref_cold <= '0; c_ref_hot <= '0;
// AND-accumulator discipline: a minimum tracker starts at
// all-ones or the first sample never wins and the reported
// minimum stays zero, which would make every span look
// enormous and every slope look flat.
t_min <= '1; t_max <= '0; t_mid <= '0;
auth_max <= '0;
slope_num <= '0; slope_den <= '0;
r_refresh <= '0; r_t_min <= '0; r_t_max <= '0; r_authority <= '0;
span_too_small <= 1'b0; result_valid <= 1'b0;
end else if (win_tick) begin
r_refresh <= c_ref;
r_t_min <= t_min;
r_t_max <= t_max;
r_authority <= auth_max;
// The slope, as a difference of refresh counts across the
// temperature span, over the span. Reported as a pair.
slope_num <= $signed({1'b0, c_ref_hot}) - $signed({1'b0, c_ref_cold});
slope_den <= $signed({1'b0, t_max}) - $signed({1'b0, t_min});
// A slope over a tiny span is noise, not a measurement. Flagged
// rather than reported as a number -- 30.8 §11's rule that an
// instrument which can report an impossible value has never
// been checked, applied to a meaningless one.
span_too_small <= (t_max <= t_min) || ((t_max - t_min) < 4);
result_valid <= 1'b1;
c_ref <= '0; c_ref_cold <= '0; c_ref_hot <= '0;
t_min <= '1; t_max <= '0; auth_max <= '0;
end else begin
result_valid <= 1'b0;
if (ref_issued && c_ref != {CNT_W{1'b1}}) c_ref <= c_ref + 1'b1;
if (filt_valid) begin
if (filt_temp < t_min) t_min <= filt_temp;
if (filt_temp > t_max) t_max <= filt_temp;
// The midpoint is recomputed from the running extremes, so
// the cold/hot split follows the observed span rather than a
// compiled threshold -- 32.1 §13's defect class avoided.
t_mid <= (t_min >> 1) + (t_max >> 1);
// Bucket each refresh by which half of the observed span its
// temperature fell in.
if (ref_issued) begin
if (filt_temp >= t_mid) begin
if (c_ref_hot != {CNT_W{1'b1}}) c_ref_hot <= c_ref_hot + 1'b1;
end else begin
if (c_ref_cold != {CNT_W{1'b1}}) c_ref_cold <= c_ref_cold + 1'b1;
end
end
end
if (authority_applied > auth_max) auth_max <= authority_applied;
end
end
endmoduleWhat this block can and cannot show is the honest part, and it is stated in its own limitations.
It can show that k did not fall when the throttle engaged. That is §13's exact signature: r_authority reaches its maximum, slope_num / slope_den is unchanged, and the temperature span keeps widening. A throttle with real authority over the loop produces a falling slope, because temperature-compensated refresh changes the rate's dependence on temperature rather than its offset.
It cannot measure G, and no memory-side block ever will. CURRICULUM-DERIVED from §9: theta is a property of the enclosure, the board and the user. So the deliverable is k, reported as grade C about this machine, and the integration team multiplies. CURRICULUM-DERIVED from 18.4 §1: that qualification must travel with the number, or it becomes a grade-A claim about a device family in somebody's slide.
15. RTL — Filtering the Input
§5 required the throttle's input to be filtered and §11's block explicitly declined to do it, naming the window length as a platform property. This block is that filter, and it is the positive counterpart to 32.1 §13's defect: the window length arrives as an input, not as a parameter.
// ---------------------------------------------------------------------
// thermal_filter -- CORRECT as written. Grade-D bounds only.
//
// CLASSIFICATION: synthesisable. No physical constant appears.
//
// WHAT IT IS: §5's requirement as hardware. A burst is free, so the
// throttle must see a WINDOWED quantity; and the window length is a
// property of the platform's thermal mass, so it is an INPUT.
//
// WHY IT EXISTS HERE: §5 derives that the throttle's deadline and its
// input window both come from a thermal mass rather than from any
// memory parameter. 32.1 §13 showed what happens when a platform
// property is compiled in; this block is the same discipline applied
// correctly, and the contrast is the point.
//
// HOW TO RUN IT: apply a short high-temperature burst shorter than
// cfg_win_len, then a sustained rise.
// EXPECTED RESULT: the burst does NOT raise filt_temp enough to
// engage a level; the sustained rise does.
// EXPECTED TRACE: filt_valid must stay LOW until a full window has
// been accumulated -- a partial-window average of a burst looks
// exactly like a sustained load, which is the subtle failure this
// block's clause 3 forbids.
//
// SYNTHESIS: one accumulator, one shift-divide, one sample counter.
// The divide is by a power of two only -- cfg_win_log2 is the
// configuration field, so no divider is instantiated.
//
// LIMITATIONS: a boxcar average over a power-of-two window. A real
// platform may need a different response shape, and if so the SHAPE
// is a platform property too and belongs in configuration by the
// same argument. Stated rather than implied.
// ---------------------------------------------------------------------
module thermal_filter #(
parameter int TMP_W = 8,
// Bounds on the CONFIGURABLE window, not the window itself. A
// bound is a design property; the value is a platform property.
parameter int MAX_WIN_LOG2 = 16,
// COUNT, not INDEX: the accumulator must represent
// (2**MAX_WIN_LOG2) samples each up to 2**TMP_W - 1, so it needs
// MAX_WIN_LOG2 + TMP_W bits. One bit short and it wraps at the
// hottest sustained load -- reporting a LOW filtered temperature
// exactly when the throttle is most needed.
parameter int ACC_W = MAX_WIN_LOG2 + TMP_W,
parameter int SMP_W = MAX_WIN_LOG2 + 1
)(
input logic clk,
input logic rst_n,
input logic [TMP_W-1:0] raw_temp,
input logic raw_valid,
// The window length, as a CONFIGURATION input. Expressed as a
// log2 so the division is a shift: a divider here would be
// hardware paid for a platform constant.
input logic [4:0] cfg_win_log2,
input logic cfg_valid,
output logic [TMP_W-1:0] filt_temp,
output logic filt_valid,
output logic [TMP_W-1:0] raw_peak,
output logic cfg_out_of_range
);
logic [ACC_W-1:0] acc;
logic [SMP_W-1:0] smp;
// Clause 4's range check, at RUNTIME rather than elaboration --
// because the value is a configuration input and a register can
// hold something that does not fit. 32.1 §13's correction needed
// exactly this transition, and here it is designed in.
assign cfg_out_of_range = cfg_valid && (cfg_win_log2 > MAX_WIN_LOG2[4:0]);
always_ff @(posedge clk) begin
if (!rst_n) begin
acc <= '0;
smp <= '0;
filt_temp <= '0;
filt_valid <= 1'b0;
raw_peak <= '0;
end else if (!cfg_valid || cfg_out_of_range) begin
// No configuration, no output. 30.7 §9: an unconfigured value
// is unknown, and unknown is not a default. A filter that
// guessed a window would hand the throttle a number whose
// meaning nobody knows.
filt_valid <= 1'b0;
acc <= '0;
smp <= '0;
end else if (raw_valid) begin
// The raw peak is kept separately and is NOT filtered, because
// §5 needs both quantities: the filtered one decides the
// throttle and the peak shows what the thermal mass absorbed.
// Reporting only the filtered value would hide the burst
// entirely, and 24.1 §4's sustained-versus-burst distinction
// would be unobservable.
if (raw_temp > raw_peak) raw_peak <= raw_temp;
acc <= acc + {{(ACC_W-TMP_W){1'b0}}, raw_temp};
if (smp >= ((1 << cfg_win_log2) - 1)) begin
// A full window: publish and restart.
filt_temp <= (acc + {{(ACC_W-TMP_W){1'b0}}, raw_temp}) >> cfg_win_log2;
filt_valid <= 1'b1;
acc <= '0;
smp <= '0;
end else begin
// Clause 3: NOT a full window, so NOTHING is published. A
// partial-window average of a burst is numerically identical
// to a sustained load at a lower temperature, so publishing
// early would make a free burst engage the throttle -- the
// exact behaviour §5 says costs performance the thermal mass
// had already paid for.
filt_valid <= 1'b0;
smp <= smp + 1'b1;
end
end else begin
filt_valid <= 1'b0;
end
end
endmoduleClause 3 — publishing nothing until a full window — is the subtle requirement and it is worth stating why.
A partial-window average is numerically indistinguishable from a sustained load at a lower temperature. Accumulate three hot samples out of a window of sixteen, divide by sixteen, and the result is a modest number that looks like a mild sustained rise. Divide by three instead and it looks like a severe one. Either way the throttle is being told about a burst as though it were sustained — and CURRICULUM-DERIVED from 24.1 §4, a burst is exactly what the thermal mass has already absorbed and the design is allowed to spend.
And the two outputs are deliberately different quantities. filt_temp decides; raw_peak observes. Reporting only the filtered value would make 24.1 §4's sustained-versus-burst distinction unobservable — and §19's row seven needs both to tell an adequate hysteresis band from an inadequate one.
// ---- The filter's own contract, asserted.
// Clause 3: no output before a full window. This is the property
// that forbids the numerically-plausible early publish.
property p_no_output_before_full_window;
@(posedge clk) disable iff (!rst_n)
filt_valid |-> ($past(smp) >= ((1 << $past(cfg_win_log2)) - 1));
endproperty
assert property (p_no_output_before_full_window)
else $error("a filtered value was published before a full window");
// The configuration discipline, positively: an out-of-range or
// absent configuration produces no output rather than a default.
property p_unconfigured_produces_nothing;
@(posedge clk) disable iff (!rst_n)
(!cfg_valid || cfg_out_of_range) |-> !filt_valid;
endproperty
assert property (p_unconfigured_produces_nothing)
else $error("the filter published a value with no valid configuration");
// The accumulator must never wrap, because a wrapped accumulator
// reports a LOW filtered temperature at the hottest sustained
// load -- 30.8 §11's range rule, and the direction of the error
// is what makes it dangerous rather than merely wrong.
property p_accumulator_never_wraps;
@(posedge clk) disable iff (!rst_n)
(raw_valid && cfg_valid) |-> (acc <= ({ACC_W{1'b1}} - raw_temp));
endproperty
assert property (p_accumulator_never_wraps)
else $error("the filter accumulator wrapped: the filtered value is understated");
// ---- Covers: the window length must VARY, or the configuration
// mechanism was never tested even though it was honoured --
// 32.1 §15's lesson, applied to a different platform value.
cover property (@(posedge clk) disable iff (!rst_n)
filt_valid && (cfg_win_log2 == 4));
cover property (@(posedge clk) disable iff (!rst_n)
filt_valid && (cfg_win_log2 == MAX_WIN_LOG2));
// A BURST that did not engage: the case clause 3 exists for.
cover property (@(posedge clk) disable iff (!rst_n)
(raw_peak > T_L1) && !filt_valid);
// And the out-of-range configuration, so the refusal path is known
// to have been exercised rather than merely present.
cover property (@(posedge clk) disable iff (!rst_n) cfg_out_of_range);The third cover is the chapter's cleanest statement of §5. A raw peak above the engage threshold with no filtered output published is a burst correctly absorbed — and if that cover is zero, the platform's burst behaviour was never exercised and the filter's whole purpose is unverified.
16. SVA Review — Proving a Response That Responds to the Wrong Thing
The properties written for §12's block, and all three are correct:
// Offered as "proves the throttle works". All three PASS on the
// defective block.
property p_engages_within_deadline;
@(posedge clk) disable iff (!rst_n)
(filt_valid && filt_temp >= T_L1 && level == 0) |->
##[1:RESP_DEADLINE] (level != 0);
endproperty
assert property (p_engages_within_deadline)
else $error("the throttle did not engage within its deadline");
property p_hysteresis_holds;
@(posedge clk) disable iff (!rst_n)
(level == 1 && filt_valid && filt_temp >= (T_L1 - HYST_K)) |=> (level >= 1);
endproperty
assert property (p_hysteresis_holds)
else $error("the throttle disengaged inside the hysteresis band");
property p_limit_tracks_level;
@(posedge clk) disable iff (!rst_n) policy_limit == level;
endproperty
assert property (p_limit_tracks_level)
else $error("the policy limit did not track the level");Q. All three pass. What have they proved?
That the throttle responds promptly, with correct hysteresis, and drives the output it drives. None of them names refresh_mode_req — the signal the defect ties off — so none can observe that the authority set is incomplete. Chapter 30.9 §6's variety 2, and it is the third consecutive chapter in which the defect's key signal is absent from the property set.
And the diagnosis is sharper than a missing property. §7 gave the throttle three requirements and the property set covers two of them. Response time and hysteresis are properties of the mechanism; authority is a property of what the mechanism is connected to — so the omission is structural: a property set written about a block naturally covers the block's behaviour and not its reach.
What actually covers clause 2:
// Clause 2. It names refresh_mode_req, so it cannot pass while
// that output is tied off. Variety 2's repair.
property p_authority_includes_refresh;
@(posedge clk) disable iff (!rst_n)
(level >= 1) |-> (refresh_mode_req != RM_NORMAL);
endproperty
assert property (p_authority_includes_refresh)
else $error("the throttle engaged without authority over the refresh term");
// And the monotonicity of the authority set: a deeper level must
// never REDUCE authority. This catches a related bug -- a level
// table with a transcription error -- that the property above
// would miss, because it only requires "not normal".
property p_authority_is_monotone;
@(posedge clk) disable iff (!rst_n)
(level > $past(level)) |-> (refresh_mode_req >= $past(refresh_mode_req));
endproperty
assert property (p_authority_is_monotone)
else $error("a deeper throttle level reduced the refresh authority");
// Clause 5. The reported authority must be the applied authority,
// or §14's measurement is being fed a number the block does not
// mean -- 32.1 §13's "the block reports a configuration it is not
// using", in a different domain.
property p_reported_authority_is_applied;
@(posedge clk) disable iff (!rst_n) authority_reported == level;
endproperty
assert property (p_reported_authority_is_applied)
else $error("the block reports an authority it did not apply");
// The masked mode must never be applied WITHOUT consent, because
// 24.2 §9's retention consequence means it discards data. This is
// the one property in the chapter whose violation is a
// CORRECTNESS failure rather than a thermal one.
property p_masked_mode_requires_consent;
@(posedge clk) disable iff (!rst_n)
(refresh_mode_req == RM_PASR) |-> placement_consent;
endproperty
assert property (p_masked_mode_requires_consent)
else $error("a masked refresh mode was applied without placement consent");And now the property that looks strongest and is weakest, which is this section's real lesson:
// TEMPTING, and it is NOT a proof. The consequent depends on the
// TESTBENCH'S THERMAL MODEL -- on theta, on the mass, on the
// ambient. §9 established that none of those is a memory property.
//
// So this property's outcome is a statement about the model, and a
// model that under-states the loop will let it pass on the
// defective block: at a bench-like theta, throttling traffic DOES
// reduce temperature (§13).
property p_temperature_falls_after_throttle;
@(posedge clk) disable iff (!rst_n)
(level >= 2) |-> ##[1:SETTLE] (filt_temp < $past(filt_temp, SETTLE));
endpropertyThis is 30.7 §10's variety 4 — the environment sharing the design's wrong assumption — broadened from a shared CONSTANT to a shared MODEL. It is not an eleventh variety; it is variety 4 with more surface, and the extra surface matters because a model is harder to inspect than a constant.
Stating it as a broadening rather than a new entry is the honest call. The mechanism is identical: the property's verdict is only as good as an environment input that nobody independently verified, and in 30.7 §10 that input was a flight-time constant while here it is a thermal model. The repair is also identical — sweep it. CURRICULUM-DERIVED from 30.7 §10: a testbench that holds the shared input at one value can never distinguish a design that uses it from one that ignores it, so the thermal model must be swept across the platform's permitted theta range, and §4's table is the sweep.
// ---- Covers. The dimension this defect scales with is the
// THERMAL PATH -- a property of the environment's model, and
// 31.4 §14's rule says running longer never reaches it.
// The loop-dominated regime: the only one in which the defect is
// observable. If this cover is zero, thermal validation ran
// exclusively in the regime where §13 says the bug cannot appear.
cover property (@(posedge clk) disable iff (!rst_n)
(level >= 2) && (refresh_power_est > traffic_power_est));
// The traffic-dominated regime, so both are known to have run.
cover property (@(posedge clk) disable iff (!rst_n)
(level >= 2) && (traffic_power_est >= refresh_power_est));
// Each level reached, per 31.3 §15's per-index rule applied to a
// level space.
cover property (@(posedge clk) disable iff (!rst_n) level == 1);
cover property (@(posedge clk) disable iff (!rst_n) level == 2);
cover property (@(posedge clk) disable iff (!rst_n) level == 3);
// The hysteresis band actually occupied -- a fall that did NOT
// disengage. Without this, p_hysteresis_holds is vacuous.
cover property (@(posedge clk) disable iff (!rst_n)
(level == 1) && filt_valid &&
(filt_temp < T_L1) && (filt_temp >= (T_L1 - HYST_K)));
// The deadline path, which should be unreachable in the correct
// block -- 30.10 §12's dead-or-live distinction: this cover must
// go DEAD after the fix and be LIVE while debugging one.
cover property (@(posedge clk) disable iff (!rst_n) response_late);The first cover is the one that finds the defect, and its threshold is derived from the failure mechanism rather than from the use case — CURRICULUM-DERIVED from 31.2 §14's rule. The regime that matters is refresh power exceeds traffic power, which is a condition on the operating point and not on the duration, so it is reachable in a short directed test at a hot model point and unreachable in any length of bench-temperature run.
17. What the Response Block's Assertions Prove
§16 reviewed the throttle's decision. §11's block also has a deadline and an interaction with progress bounds that §6 flagged and nothing has yet asserted.
// §6's tension, resolved as a table rather than a single bound. A
// throttle extends every progress bound, so one bound justified at
// full rate is VIOLATED by a correct throttle and one justified at
// the deepest throttle is uselessly loose at full rate. 30.9 §5 Q2
// owns that a bound must be justified rather than chosen.
property p_progress_bound_per_level;
@(posedge clk) disable iff (!rst_n)
req_accepted |-> ##[1:MAX_LAT_FOR_LEVEL(level)] resp_valid;
endproperty
assert property (p_progress_bound_per_level)
else $error("a request exceeded the progress bound for the active throttle level");
// The response deadline itself, as a bounded liveness property --
// never as unbounded eventuality (30.9 §5 Q2). RESP_DEADLINE is
// justified from the THERMAL time constant (§5), not from any
// memory parameter, and that derivation is the property's warrant.
property p_response_meets_deadline;
@(posedge clk) disable iff (!rst_n)
$rose(pending) |-> ##[1:RESP_DEADLINE] !pending;
endproperty
assert property (p_response_meets_deadline)
else $error("the response did not complete within its deadline");
// A burst must NOT engage the throttle -- §5's requirement that the
// input be filtered. This is the two-sided bound: the safety
// property alone is satisfied by a throttle that engages always.
property p_no_engage_without_filtered_input;
@(posedge clk) disable iff (!rst_n)
(!filt_valid) |-> $stable(level);
endproperty
assert property (p_no_engage_without_filtered_input)
else $error("the level moved on an unfiltered sample");
// The PLATFORM invariant, parameter in the antecedent and not in
// the claim -- 31.1 §14's test for sharing a property across
// configurations. It may be shared.
property p_fanned_platform_never_throttles;
@(posedge clk) disable iff (!rst_n)
(!THERMAL_LIMITED) -> (level == 0 && refresh_mode_req == RM_NORMAL);
endproperty
assert property (p_fanned_platform_never_throttles)
else $error("a platform with no heat ceiling engaged a throttle");
// And the invariant that makes the hysteresis specification
// MEANINGFUL rather than merely present: the level must never
// oscillate on consecutive filtered samples. §7 requirement 3, and
// 24.2 §14's oscillation corner case is what it forbids.
property p_no_single_sample_oscillation;
@(posedge clk) disable iff (!rst_n)
(filt_valid && level != $past(level)) |=>
(!filt_valid || level == $past(level));
endproperty
assert property (p_no_single_sample_oscillation)
else $error("the level changed on two consecutive samples: hysteresis is ineffective");p_progress_bound_per_level is the property §6 argued for, and it is worth noting what it costs: MAX_LAT_FOR_LEVEL is a function, so the bound is a small table whose every entry needs the justification 30.9 §5 demands. A throttle turns one justified number into several, and a project that throttles while keeping one bound has either an unprovable property or a useless one.
And p_no_single_sample_oscillation is the property that makes hysteresis auditable rather than decorative. A hysteresis band that exists in the parameter list and is too narrow to damp the loop satisfies p_hysteresis_holds and still oscillates — which is 31.2 §7's present in the source, absent in the silicon at the control layer.
18. What Would You Measure?
Q. You own the memory subsystem on a mobile platform. What do you measure, in what order?
| Measurement | What it settles | Cost | Owner |
|---|---|---|---|
Ask the integration team for theta, and for the range it may reach | §4's loop gain — and §9 says you cannot compute it yourself | hours | §9 |
| The thermal time constant of the platform | §5 — the throttle's deadline comes from here and from nowhere in memory | hours | §5 |
k from §14, as an observed slope | the half of the loop gain you can supply, as grade C | days | §14 |
| Whether the throttle's authority set includes the refresh term | §13's defect, and it is answerable by reading the port list | hours | §13 |
r_authority against the slope, at maximum level | whether authority is effective as well as present | days | §14 |
response_late under the worst permitted theta | §4's third conclusion — the deadline scales as 1/(1−G) | days | §11 |
| Level oscillation rate | whether hysteresis is adequate, not merely present | days | §17 |
| Duty cycle and the idle-duration distribution | the energy ceiling, which is a separate question — 31.2 §5 | days | 31.2 |
Row one is first and it is not a measurement you take — it is a number you must request. That is the unusual thing about this platform class, and §9 is why: theta has no grade from any memory source, so the memory team's loop analysis is incomplete by construction until integration supplies the other factor. A team that does not ask has silently assumed a bench value.
Row four costs an hour and is answerable by inspection. Does the throttle drive anything that changes the refresh rate? If not, §13's defect is present regardless of how the throttle performs — and no thermal test at a bench operating point will reveal it.
And row eight is a reminder that this chapter answered only one of the two ceilings. CURRICULUM-DERIVED from 24.1 §4: a design can satisfy either and fail the other. Chapter 31.2 §5 owns the energy question and its deciding quantity, and nothing in this chapter's loop analysis bears on it.
19. Common Wrong Answers
“Mobile memory is about saving power.” §2. Two ceilings, and only one is a budget. The heat ceiling is a rate, met at runtime, under conditions the designer does not control.
“If the energy budget closes, the design is done.” §2, and 24.1 §4 owns the correction: a design can satisfy either ceiling and fail the other.
“Refresh overhead is a small fixed percentage.” §3. It rises with temperature, and 24.2 §7 measured self-refresh current rising more than twentyfold cool-to-hot on a real device.
“The thermal feedback loop is a theoretical concern.” §4. It amplifies every heat source by 1/(1−G), and DERIVED at a grade-D pocket thermal path that factor is 20.
“If it does not run away, the loop does not matter.” §4. Amplification arrives long before instability, and so does a 1/(1−G) blow-up in the settling time.
“The memory is not the heat source, so it is not the problem.” §4. It is the amplifier. A display or compute burst gets its thermal effect multiplied, and the investigation goes to whichever subsystem grew.
“We validated the thermal design in the lab.” §4, §13. theta moves from a bench value to a pocket value without a silicon change, and G crosses 1 on the way.
“Throttle on instantaneous power.” §5. A burst is free — the thermal mass absorbed it — so throttling on an unfiltered sample gives up performance already paid for.
“The throttle deadline comes from the memory timing.” §5. It comes from the thermal time constant, and no DRAM parameter appears in its derivation.
“A throttle just needs to respond quickly.” §7, §13. Response time is one of three requirements. Authority is the one §13's block fails, and hysteresis is the one that turns the loop into an oscillator when omitted.
“Throttle the traffic — that is where the power is.” §13. At the hot operating point the refresh term dominates, and it is the term that closes the loop and the one 17.3 §2 says cannot be declined.
“The throttle engaged at maximum, so we have done all we can.” §13. If its authority set omits the loop term, maximum engagement leaves G unchanged.
“Mask some memory to cool down.” §11, §13, and 24.2 §9 owns the correction: PASR is a mask with a retention consequence, so an excluded region is not preserved. It is a request requiring consent, not a knob.
“Hysteresis is a tuning refinement.” §7. Mandatory, because the throttle's own effect clears its own trigger — 23.5 owns the argument and 24.2 §14 the oscillation corner case.
“One progress bound covers the design.” §6, §17. A throttle extends every bound, so one number justified at full rate is violated by a correct throttle. The bound becomes a table.
“The throttle assertions pass.” §16. They prove response and hysteresis and never name refresh_mode_req. A property set written about a block covers its behaviour, not its reach.
“We asserted that temperature falls after throttling.” §16. That verdict is a statement about the testbench's thermal model — variety 4 broadened from a constant to a model, and the repair is to sweep theta.
“We can compute the loop gain.” §9, §14. Not from a memory source: theta is a property of the enclosure, the board and the user. You can supply k as grade C and must carry that qualification.
“A hot device just needs a bigger heatsink.” §2, §18. Sometimes, and that is an integration answer rather than a memory one — which is why §18's first row is a number you request rather than a measurement you take.
20. Self-Check
-
Name both ceilings, say which is a budget and which is a control problem, and give the one row of §2's table that makes them different in kind.
-
Draw §3's loop as a signal path with four stages, naming the chapter that owns each link.
-
Derive §4's closed-form
Tfrom the open-loop equation. State the stability condition and the amplification factor. -
Recompute the three
Gvalues of §4 fork = 0.012 W/K. State which thermal paths become stable and what that implies about where the margin actually comes from. -
Explain why the loop amplifies heat sources that are not the memory, and what that does to a thermal investigation.
-
Explain why a burst needs no throttle and a sustained load does, and say where the throttle's deadline comes from.
-
Give §7's three requirements. For each, name the failure that omitting it produces.
-
Explain why throttleability is a third kind of obligation, and how it conflicts with the second kind and is resolved.
-
Find the defect in §12 without reading §13. Then explain why it passed thermal validation, and state the general rule about where a fractional mechanism must be validated.
-
Explain why
p_temperature_falls_after_throttleis not a proof, name the variety it instances, and say why it is a broadening rather than a new entry. -
State which half of the loop gain a memory team can supply, what grade it is, and what must travel with the number.
21. Where This Goes
A mobile platform's dominating constraint is a heat ceiling that the memory closes a loop on. Two ceilings and only one is a budget; retention falls with temperature so refresh power rises with it, closing a positive feedback loop whose gain is theta times the refresh slope; the loop amplifies every heat source by 1/(1−G) long before it becomes unstable, and the quantity that destroys the margin is the thermal path rather than the memory; sustained and burst limits differ, so the throttle's input must be filtered and its deadline comes from a thermal mass rather than from any DRAM parameter; and throttleability is a third kind of obligation whose specification is an authority set, not a response time.
Three results carry forward. A throttle's authority set is its specification, and one that omits a term in the feedback path cannot change the loop gain however fast it engages. A mechanism whose authority is a fraction of the total must be validated where that fraction is smallest, not where the platform usually sits. And a property whose consequent depends on an environment model is variety 4 with more surface — the repair is to sweep the model, and §4's table is the sweep.
Chapter 32.3 keeps one controller and gives it two requester populations that want opposite things. Chapter 31.4 §4 established that latency becomes invisible once a requester sustains ceil(L/S) transactions outstanding, and that a faster channel raises that bar. What it did not consider is a platform where one population clears the bar by an enormous margin and another cannot clear it at all — and since both are served by the same controller with the same thirteen obligations, the controller cannot be tuned for either without failing the other.
Continue learning
Related tutorials
- Related topic
Mobile-Memory Mission
A phone asks three different things of its memory and they trade against each other. At a 2% duty cycle nearly half the average power is spent idle, and below 1% it is two thirds.
- Related topic
LPDDR Evolution
LPDDR is not low-power DDR. It is the same reasoning run against a different constraint set — no socket, a fixed battery, no airflow — which produces low-swing signalling, split command and data clocks, and power states expensive enough to reshape the controller.
- Related topic
Low-Power Features
A named device's own state diagram defines the states, and several transitions between them are illegal. Per-bank refresh draws identical current to all-bank refresh on every rail — it buys availability, not energy.
- Related topic
Mobile-Power Management
LPDDR4X lowers two rails and deletes a third. Two of four LPDDR5X rails go unused in self refresh — so gating them saves nothing in the memory, and a bad shutdown order survives ten thousand clean power cycles.
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.
