DDR · Module 6
Other Sideband Signals
The signals that fit no earlier family: command-path parity, the one output a DRAM drives back to the controller, the selector that made multi-function pins possible, and the references that stopped being designed.
Eleven chapters have covered the clock, the qualifiers, the command trio, termination control, reset, the data bus, its strobe and its mask.
This chapter takes what is left, and the leftovers turn out to share a property worth noticing:
Every signal so far — with the sole exception of the bidirectional data lines — is driven by the controller side. A DRAM device receives clock, commands, addresses, selection, termination control and reset, and drives nothing back except data.
ALERT# is the exception, and that makes it structurally more interesting than its role suggests.
So the chapter's question is:
What is left over, why does each survive as a dedicated signal, and what does the one device-driven output tell us?
1. Almost Everything Points One Way
Take stock of the module's signals by direction, because the asymmetry is stark and it explains a great deal.
A DRAM device is almost entirely a receiver, and this explains something the module has run into repeatedly: the recurring pattern of failures that produce no error report.
Chapter 5.2 §4's silent row mismatch, Chapter 6.2 §4's ignored command, Chapter 6.7 §3's marginal termination, Chapter 6.11 §8's overwritten bytes — every one of them is silent partly because the device has almost no way to speak. With one output wire, a device can report only what that wire has been assigned to report.
So the design question for any device-detectable error is not "should we detect it" but "is it worth a share of the one wire". That framing explains what ALERT# carries and what it does not.
2. PAR — Protecting the Path Where Errors Are Worst
Chapter 4.5 §3 established the asymmetry that justifies command-path protection: a corrupted data bit damages one datum, while a corrupted command bit can activate the wrong row or precharge a bank in use — corrupting state belonging to an access that was never issued.
PAR is a single parity input over the command and address signals. The controller computes it; the device recomputes it and compares.
Two details make it more than a checksum.
It is checked only when CS_n is low. Verified: the check occurs when commands are latched and chip select is asserted. Unqualified events carry no command, so there is nothing to protect — which is Chapter 6.3 §3's point about deselect bounding the interface's sensitivity, appearing again.
And parity detects rather than corrects. A single parity bit over a wide field can tell you something is wrong; it cannot tell you what. That is the right trade here, because the correct response to a corrupted command is not to guess at the intended one — it is to stop and let the controller retry from known state.
3. ALERT# — One Wire, Two Error Classes
ALERT# is the device's only output, and it carries both the command/address parity error report and the CRC data error report. Verified: it is held low for a relatively long period while the device's internal recovery completes.
And a practical warning worth stating plainly. ALERT# is easy to leave unmonitored, because a system works perfectly without watching it right up until it does not. Chapter 6.1 §10's fifth debugging mechanism was exactly this: the system reporting the answer and nothing being connected to hear it.
4. ACT_n and the Trained References
Two more signals, both already met, both worth placing in the taxonomy properly.
ACT_n is the selector Chapter 6.6 §3 built its argument around. As a signal in its own right it is unremarkable — controller-driven, sampled like any command input, one bit. Its significance is entirely structural: it is the signal whose existence made three other pins dual-purpose, and it cost one pin to buy three address bits and a freed encoding slot.
It is the clearest case in this module of a signal whose value is not what it carries but what it enables.
The reference voltages are the other category, and they are where Chapter 4.4 §1's pattern reaches the receiver.
A single-ended receiver compares an incoming signal against a threshold — the problem Chapter 6.1 §3 described when explaining why the clock is differential. That threshold has to come from somewhere.
Chapter 4.5 §3 established that DDR4 made the data reference a trained value, adjusted per system to sit where the signal's actual levels place the best decision point — rather than a fixed value supplied externally. That is the same move as ZQ calibration, applied to the vertical axis instead of the horizontal one, and it is the third instance of the progression Chapter 4.6 §3 named: from designed, to measured once, to adapted continuously.
The consequence for this module is that a reference is not a signal you can reason about from a schematic. It is state established by a procedure, it drifts, and it is invalidated by anything that resets the device — which is Chapter 6.8 §3's initialisation contract arriving at the receiver.
5. RTL — Parity and a Shared Alert
Engineering problem
Compute command/address parity, check it on qualified events only, and report errors on a shared output that also carries another error class — making the resulting ambiguity explicit rather than pretending the wire is unambiguous.
Classification
SYNTHESIZABLE RTL. Parity generation and checking with a shared reporting output — present in both a controller's transmit path and a device's receive path.
What it represents: the parity computation, its qualification by chip select, the shared alert output with its extended assertion, and the ambiguity a shared output creates.
What it does not represent: the CRC computation itself, which is a separate mechanism over write data — only its arrival as an alert source is modelled; the device's internal recovery, which is what the extended assertion is actually waiting for; the controller's retry policy, which is Module 17's; and any electrical property. ALERT_EVENTS is an educational cycle count, not a specification value.
Interface contract
sample_evt, cs_n, ca_in and par_in present a command with its parity. crc_error_in is the other alert source. alert_n is the shared active-low output. alert_reason and alert_ambiguous expose what the wire cannot.
State
The alert countdown and a latched reason.
Combinational behaviour
Parity computation and comparison.
Sequential behaviour
The alert assertion and its hold.
How to simulate
vlog ca_parity_check.sv tb_ca_parity_check.sv then vsim -c tb_ca_parity_check -do "run -all".
Expected result: a command with correct parity passes silently; one with incorrect parity asserts alert_n for ALERT_EVENTS; and a CRC error arriving during a parity alert sets alert_ambiguous.
// ─────────────────────────────────────────────────────────────────────────
// CA PARITY CHECK. Classification: SYNTHESIZABLE RTL.
//
// Command/address parity, checked ONLY ON QUALIFIED EVENTS, reported on a
// SHARED alert output that also carries CRC data errors.
//
// THE SHARED OUTPUT IS THE POINT. Unlike Chapter 6.6's multi-function
// INPUTS -- where ACT_n selects deterministically at every event -- this
// output has NO SELECTOR. The wire does not say which error class it is
// reporting, so the controller must reconstruct context the device already
// had. alert_reason and alert_ambiguous expose what the wire cannot.
//
// WHAT THIS DOES NOT REPRESENT: the CRC computation (a separate mechanism
// over write data -- only its ARRIVAL as an alert source is modelled), the
// device's internal recovery that the extended assertion is actually
// waiting for, the controller's retry policy (Module 17), and every
// electrical property. ALERT_EVENTS is an EDUCATIONAL cycle count.
//
// GENERATION: DDR4. DDR5's command/address interface and its integrity
// arrangements differ -- Module 25.
// ─────────────────────────────────────────────────────────────────────────
module ca_parity_check #(
parameter int CA_W = 24,
// 1 = odd parity, 0 = even. A parameter because the convention is a
// specification choice, not a property of parity.
parameter bit ODD_PARITY = 1'b1,
// Events the alert is held asserted. EDUCATIONAL -- the real duration
// exists so the device can complete internal recovery, and it is
// specification material.
parameter int ALERT_EVENTS = 6,
parameter int CNT_W = (ALERT_EVENTS <= 1) ? 1 : $clog2(ALERT_EVENTS + 1)
) (
input logic clk,
input logic rst_n,
input logic sample_evt,
input logic cs_n,
input logic [CA_W-1:0] ca_in,
input logic par_in,
// The other error class sharing this output. Modelled as an input
// because the CRC mechanism itself is out of scope -- what matters here
// is that TWO sources drive ONE wire.
input logic crc_error_in,
// ACTIVE LOW, and the device's ONLY output. Every report the device can
// make rides this one wire.
output logic alert_n,
output logic parity_error,
// 0 none, 1 CA parity, 2 CRC, 3 both. NOT VISIBLE ON THE WIRE -- this
// output exists so the model can show what the controller must infer.
output logic [1:0] alert_reason,
// Both sources active. The controller cannot distinguish them from the
// wire alone, which is the cost of sharing an output with no selector.
output logic alert_ambiguous,
output logic [CNT_W-1:0] alert_countdown
);
// ── COMPILE-TIME legality.
if (CA_W < 1) begin : g_ca
initial $fatal(1, "ca_parity_check: CA_W must be >= 1");
end
if (ALERT_EVENTS < 1) begin : g_al
initial $fatal(1, "ca_parity_check: ALERT_EVENTS must be >= 1");
end
// ── Parity over the command/address field. ^ca_in reduces to the XOR of
// every bit -- even parity; inverted for odd.
logic par_expected;
assign par_expected = ODD_PARITY ? ~(^ca_in) : (^ca_in);
// ── QUALIFIED ONLY. Chapter 6.3: an unqualified event carries no
// command, so there is nothing to protect. Checking unconditionally
// would report an error on essentially every idle event, and a
// checker that fires constantly stops being read.
logic qualified;
assign qualified = sample_evt && !cs_n;
assign parity_error = qualified && (par_in != par_expected);
assign alert_n = (alert_countdown == '0);
assign alert_ambiguous = (alert_reason == 2'd3);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
alert_countdown <= '0;
alert_reason <= 2'd0;
end else begin
// A new source asserts or re-arms the alert. The hold exists because
// the device needs time to complete internal recovery -- the wire is
// not merely signalling an event, it is signalling a CONDITION.
if (parity_error || crc_error_in) begin
alert_countdown <= CNT_W'(ALERT_EVENTS);
// Accumulate reasons rather than replacing. If both classes occur
// within one assertion the controller sees ONE continuous low on
// the wire and cannot tell, which is exactly what alert_ambiguous
// exists to surface.
if (alert_countdown != '0) begin
alert_reason <= alert_reason
| {crc_error_in, parity_error};
end else begin
alert_reason <= {crc_error_in, parity_error};
end
end else if (alert_countdown != '0) begin
alert_countdown <= alert_countdown - CNT_W'(1);
if (alert_countdown == CNT_W'(1)) alert_reason <= 2'd0;
end
end
end
endmoduleCycle-by-cycle example
ALERT_EVENTS = 6, odd parity:
| Cycle | Event | parity_error | alert_n | alert_reason |
|---|---|---|---|---|
| 0 | qualified, parity correct | 0 | 1 | none |
| 1 | deselect, parity wrong | 0 | 1 | none — not checked |
| 2 | qualified, parity wrong | 1 | 0 | CA parity |
| 3–6 | alert held | 0 | 0 | CA parity |
| 4 | CRC error arrives | 0 | 0 | both — ambiguous |
| 8 | countdown expires | 0 | 1 | none |
Cycle 1 is the qualification rule. The parity bit is wrong and nothing is reported, because the event carried no command. A checker without the cs_n term would fire on idle events constantly.
Cycle 4 is the shared-output problem. A CRC error arrives while the parity alert is still asserted. On the wire, the controller sees one continuous low and has no way to know a second, different error occurred. alert_reason and alert_ambiguous are model outputs with no hardware counterpart.
Waveform expectation
§6. Watch alert_n stay low across both sources with nothing on the wire distinguishing them.
Synthesis implication
An XOR reduction tree over CA_W bits, a comparator and a counter. The XOR tree is the only part that grows, and it sits on the command path's timing — in a real controller the parity is computed a cycle early alongside the command rather than combinationally at the pin.
Corner cases
ALERT_EVENTS == 1 gives a single-cycle assertion, which defeats the purpose — the hold exists so the device can complete recovery — and is permitted so the parameter's effect is isolable. An unqualified event is never checked regardless of the parity bit's value. Both sources asserting on the same cycle sets both reason bits immediately. Reset clears the alert, which is correct: a reset discards the condition the alert was reporting.
Debugging clues
If parity errors fire constantly, check the cs_n qualification first and the parity convention second — odd versus even is a specification choice and getting it backwards makes every qualified command fail, which is a distinctive signature. If the alert asserts and the controller never notices, the alert path is not connected or not monitored — §3's warning, and the most common problem with this signal. If the controller repeatedly mis-attributes errors, check whether it is using assertion duration and recent-command context to disambiguate, because the wire alone cannot.
Limitations
No CRC, only its arrival. No internal recovery — the hold is a countdown standing in for a process. No retry policy. No modelling of what the controller should do with an ambiguous alert, which is a genuine design problem and Module 17's. And parity detects and does not correct, which is a property of the mechanism rather than a limitation of the model.
6. One Wire, Two Reports
ca_parity_check — qualified checking, and an ambiguous shared alert
10 cyclesCycle 1 carries a wrong parity bit and reports nothing, because cs_n is high. The event carried no command, so there was nothing to protect — Chapter 6.3 §3's point that only qualified events carry obligations.
Cycles 3 to 7 are one continuous assertion of alert_n. Watch alert_reason change from 1 to 3 at cycle 5 while alert_n does not change at all. A second error of a different class occurred and the wire is identical.
That is the cost of a shared output with no selector, and it is the chapter's central engineering observation. The controller must reconstruct from context — what it recently issued, what it had enabled, how long the assertion lasted — information the device already had and could not send.
Representative educational cycles. The hold duration stands in for the device's internal recovery, which is specification material.
7. Three Assertions Worth Writing
// VERIFICATION-ONLY, inside ca_parity_check.
// P1 -- QUALIFICATION. Parity is checked only on qualified events. Without
// the chip-select term this fires on nearly every idle event, and a
// checker that fires constantly is indistinguishable from a broken one --
// it stops being read.
property p_check_only_when_qualified;
@(posedge clk) disable iff (!rst_n)
parity_error |-> (sample_evt && !cs_n);
endproperty
assert property (p_check_only_when_qualified);
// P2 -- and the converse: a qualified event with wrong parity IS reported.
// The companion that stops P1 being satisfied by a checker that never
// reports anything.
property p_bad_parity_is_reported;
@(posedge clk) disable iff (!rst_n)
(sample_evt && !cs_n && (par_in != par_expected)) |-> parity_error;
endproperty
assert property (p_bad_parity_is_reported);
// P3 -- either source asserts the alert. The shared output's basic
// contract: the wire must reflect BOTH classes, or one of them is silently
// unreportable.
property p_either_source_alerts;
@(posedge clk) disable iff (!rst_n)
(parity_error || crc_error_in) |=> !alert_n;
endproperty
assert property (p_either_source_alerts);
// P4 -- THE AMBIGUITY PROPERTY, and the chapter's point. When both classes
// occur within one assertion, the wire is unchanged while the reason is
// not. This asserts that the model surfaces information the HARDWARE
// CANNOT -- which is the whole justification for alert_reason existing.
property p_ambiguity_is_invisible_on_wire;
@(posedge clk) disable iff (!rst_n)
($changed(alert_reason) && !alert_n && $past(!alert_n))
|-> $stable(alert_n);
endproperty
assert property (p_ambiguity_is_invisible_on_wire);P4 is unusual and worth explaining. Most properties assert that a design does something correctly. P4 asserts that the wire carries less information than the model does — that a change of error class produces no change on alert_n.
That is a property about a limitation, and it earns its place because the limitation is the chapter's subject. If alert_n ever did change when the reason changed, the model would be over-stating what the hardware can communicate, and every conclusion drawn about controller disambiguation would be wrong.
Asserting the boundaries of what a model represents is a technique worth having. It is how you stop an educational or verification model from quietly acquiring capabilities the real thing lacks.
What none of them prove. Nothing about CRC correctness, since it is an input. Nothing about the device's internal recovery, which the hold stands in for. Nothing about the controller's response, which is the genuinely hard design problem here. And nothing about whether parity detects the errors that actually occur — a single parity bit misses any even number of bit errors, which is a property of the code and not of this logic.
8. Common Misconceptions
"ALERT# tells the controller what went wrong." Wrong model: the signal identifies the error. Why it is tempting: an error output that did not say what the error was would seem pointless. Consequence: a controller with no disambiguation logic, which then handles a command/address parity error as though it were a CRC error or vice versa. Those demand different responses: a parity error means the device's state is suspect and the controller's model may be wrong, while a CRC error means a write's data was corrupted but the state is known and the write can simply be retried. Treating the first as the second leaves a corrupted state model in place. Correct model: ALERT# is a shared output with no selector. It reports both classes and the wire does not distinguish them. The controller disambiguates from context — recent commands, enabled features, and the assertion's duration. Prevention: ask what selects the meaning. For multi-function inputs there is a selector (ACT_n); for this output there is none.
"Command/address parity can correct a corrupted command." Wrong model: parity provides error correction. Why it is tempting: integrity mechanisms are often assumed to correct, and DDR5's on-die ECC does correct. Consequence: a controller with no retry path, assuming the device recovered. A single parity bit over a wide field detects and cannot locate, so there is nothing to correct with. Correct model: parity detects. The correct response to a corrupted command is not to guess the intended one but to stop and retry from known state — which is why the alert is held while internal recovery completes. Prevention: count the check bits against the field width. One bit cannot locate an error in twenty-four.
"Parity applies to everything on the command bus." Wrong model: the check runs on every event. Why it is tempting: continuous protection sounds stronger. Consequence: a checker that reports on idle events, since the CA lines are free to carry anything when nothing is selected. A checker that fires constantly gets disabled, taking the real protection with it. Correct model: the check occurs when commands are latched and CS_n is low. Unqualified events carry no command, so there is nothing to protect — the same bounding Chapter 6.3 §3 identified. Prevention: ask what the lines mean on an unqualified event. Nothing — so there is nothing to check.
"The reference voltage is a fixed value you supply." Wrong model: a reference is a static input. Why it is tempting: it was, in earlier generations, and it is how references usually work. Consequence: no provision for the reference being established by a procedure, drifting, and being invalidated by reset. A controller that treats it as static will not re-establish it after events that discard it — which produces marginality with no functional symptom. Correct model: DDR4 made the data reference trained, adjusted per system to sit where the signal's actual levels place the best decision point. It is state established by a procedure, and it belongs to the same initialisation contract as calibration and leveling. Prevention: ask what establishes it and what invalidates it. If the answers are "a procedure" and "a reset", it is not a fixed value.
9. Debugging — Errors Are Reported and Nobody Acts
Symptom. A system shows intermittent corruption. Investigation eventually finds that ALERT# has been asserting, possibly for a long time, and nothing in the system was reacting to it.
This is a category of fault worth naming separately, because the information needed to diagnose it was available the whole time.
Mechanism 1 — the alert path is not connected or not monitored. Inspect: whether the signal is routed to the controller, whether the controller's alert input is enabled, and whether anything services it. Expected evidence: an asserting wire with no handler. Discriminator: look at the wire. This is first because it costs nothing and because it is common — a system works perfectly without monitoring the alert right up until it does not, so the omission is never caught in bring-up.
Mechanism 2 — parity is not enabled. Inspect: the mode-register setting. Expected evidence: command corruption occurring with no alert at all. Discriminator: is the alert silent or unheard? These are opposite failures with the same symptom, and the distinction is one register read. A silent alert means the protection is off; an unheard one means it is on and ignored.
Mechanism 3 — the controller mis-attributes the error class. Inspect: whether it distinguishes parity from CRC, and how. Expected evidence: recovery action taken that is appropriate to the other class — retrying a write when the state model is suspect, or discarding state when only a write was corrupt. Discriminator: does the recovery match the cause? §3's ambiguity, and it produces a system that responds and responds wrongly, which can be worse than not responding.
Mechanism 4 — the errors are real and the cause is elsewhere. Inspect: what is corrupting commands in the first place. Expected evidence: parity errors correlated with rate, temperature, or a particular rank. Discriminator: treat the alert as a symptom, not a cause. Chapter 6.1 §10's mechanisms — the alert is telling you the command path is marginal, and fixing the reporting does not fix the signalling.
Mechanism 5 — a false alert. Inspect: whether the parity convention matches between controller and device. Expected evidence: every qualified command failing parity. Discriminator: is the error rate near 100%? Odd versus even is a specification choice, and getting it backwards makes every command fail — a distinctive signature that is nothing like a marginality.
Discrimination, cheapest first. Look at whether the wire is asserting at all — one observation splitting "silent" from "unheard". Then read whether parity is enabled. Then check whether the failure rate is near total, which names the convention error. Then ask whether the recovery action matches the likely cause.
The reasoning lesson. The device has exactly one wire with which to tell you anything, and a system that does not monitor it has discarded the entirety of the device's diagnostic capability. §1 showed that a DRAM is almost purely a receiver — so the few things it can report are disproportionately valuable, and each one is something you would otherwise have to infer from symptoms. Connect and monitor the one output, and read it before instrumenting anything else: it is the only place the device gets a say.
10. Interview Reasoning
"Why does a DDR interface protect the command path separately from the data path?" Because the blast radius of one corrupted bit is completely different. A corrupted data bit damages one datum and the requester that asked for it sees the error. A corrupted command bit can activate the wrong row, precharge a bank in use, or be read as a different command entirely — corrupting state belonging to an access that was never issued, and producing failures with no traceable relationship to any request. So the command path is worth more protection per bit, which is why DDR4 added command and address parity alongside write CRC rather than treating data integrity as sufficient. Parity is also checked only when chip select is asserted, because an unqualified event carries no command and there is nothing to protect.
"ALERT# reports two different error classes on one wire. How does a controller tell them apart?" From context, because the wire cannot. That is genuinely different from the multi-function inputs elsewhere in the interface, where ACT_n selects the interpretation deterministically at every event — this output has no selector. The controller has to use what it recently issued, which features it had enabled, and the duration of the assertion, which is one reason the assertion length is specified rather than being left as "some time". The distinction matters because the two classes demand different responses: a parity error means a command may have been misinterpreted so the controller's model of device state is suspect, while a CRC error means a write's data was corrupted but the command was fine and the state is known, so the write can simply be retried.
"Why is ALERT# structurally interesting beyond what it does?" Because it is the only signal a DRAM device drives back to the controller. Everything else in the interface — clock, clock enable, chip select, command and address, the activate selector, parity, termination control, reset — is driven toward the device, and only the data lines and their strobe are bidirectional. That asymmetry explains a pattern that recurs throughout the interface: the number of failures that produce no error report at all. A device with one output wire can report only what that wire has been assigned to report, so the design question for any detectable error is not whether to detect it but whether it is worth a share of the one wire.
"Can command/address parity correct an error?" No — it detects. A single parity bit over a wide field can tell you something is wrong and cannot locate it, so there is nothing to correct with. That is the appropriate trade here, because the right response to a corrupted command is not to guess at the intended one but to stop and retry from known state, which is what the extended alert assertion is for: it gives the device time to complete internal recovery. It also means a controller needs a retry path, and one that assumes the device recovered on its own will not have one.
"You find ALERT# has been asserting and nothing was listening. What does that tell you?" That the system discarded the entirety of the device's diagnostic capability, because that wire is the only thing a DRAM can use to tell you anything. It also means the first question is whether the alert was silent or unheard — those are opposite failures with the same symptom, and one register read distinguishes them: silent means parity was not enabled at all, unheard means it was on and nobody serviced it. After that I would check whether the failure rate is near total, because a mismatched parity convention between controller and device makes every qualified command fail, which looks nothing like a marginality. And it is worth remembering that the alert is a symptom rather than a cause — fixing the reporting does not fix whatever is corrupting commands, which is usually a command-path margin problem.
11. Engineering Exercise
DDR4 mechanisms; educational cycle counts where they appear.
1. A deselected event carries a wrong parity bit. Should the device report an error? No. The event carried no command, so the CA lines mean nothing and there is nothing to protect. Checking unconditionally would fire on essentially every idle event, and a checker that fires constantly stops being read — taking the real protection with it.
2. A controller's parity convention is even and the device's is odd. What is the symptom? Every qualified command fails parity — a near-100% error rate. That is a distinctive signature: marginality produces occasional errors correlated with rate or temperature, while a convention mismatch produces total failure immediately. The rate itself is the diagnostic.
3. A CRC error occurs while a parity alert is still asserted. What does the controller observe? One continuous assertion of alert_n, unchanged. It has no way to know a second error of a different class occurred. §5's alert_reason has no hardware counterpart — the controller must infer from what it recently issued and what it had enabled.
4. Why is a shared output harder to handle than a shared input? A shared input — Chapter 6.6's multi-function pins — has a selector, so the interpretation is deterministic at every event and both sides agree. A shared output with no selector pushes the decoding onto the receiver, which must reconstruct context the transmitter already had. The information exists and cannot be sent, which is a strictly worse position.
5. Argue for or against spending a second pin to separate the two alert classes. For: it removes the ambiguity entirely, lets the controller respond correctly without inference, and the two classes genuinely need different responses. Against: it is a pin on every device on every rank, and Chapter 4.5 §3 showed DDR4's whole approach was avoiding added pins — and errors are rare, so the ambiguity is paid for only when something has already gone wrong. The trade is genuinely tight here, which is worth noticing: most of this module's encoding decisions are clear-cut and this one is not.
6. What makes the reference voltage different from every other "signal" in this module? It is not a signal carrying information — it is a threshold against which other signals are judged, and in DDR4 it is established by a training procedure rather than supplied as a fixed value. So it is state, not communication: it drifts, it is invalidated by reset, and it must be re-established — which puts it in the same category as calibration and leveling rather than with the wires.
12. Summary — and the Module's Answer
The sideband signals are what is left, and they share a property: a DRAM device is almost entirely a receiver. Clock, clock enable, chip select, command and address, the activate selector, parity, termination control and reset all point toward the device. Only DQ and DQS are bidirectional, and ALERT# is the sole output.
That asymmetry explains a pattern this module met repeatedly: the number of failures that produce no report. A device with one output wire can report only what that wire has been assigned to carry.
PAR protects the path where a single corrupted bit has unbounded consequences — a corrupted command can damage state belonging to an access that was never issued. It is checked only on qualified events, because unqualified ones carry no command. And it detects without correcting, which is right: the correct response to a corrupted command is to stop and retry from known state, not to guess.
ALERT# carries two error classes with no selector, which is genuinely harder than a multi-function input. The controller must reconstruct from context — recent commands, enabled features, assertion duration — information the device already had and could not send. And the two classes need different responses: a parity error makes the controller's state model suspect, while a CRC error leaves state known and the write retryable.
ACT_n's significance is not what it carries but what it enables — one pin that made three others dual-purpose. And the trained references are not signals at all but thresholds established by procedure, drifting, invalidated by reset, belonging with calibration rather than with wires.
Which finally answers the module's question. Chapter 6.1 asked why a signal still has a pin of its own, and twelve chapters give a consistent answer:
A function needed at every event keeps its pin — CS# qualifies every command; DQ and DQS carry and time every transfer. A function that must work when the command path does not keeps its pin — CK and RESET#. Everything else becomes an encoding, and did: CKE, ODT, and the RAS#/CAS#/WE# trio.
Frequency and independence, not importance. That is the criterion, and it predicts correctly across every generation this module covered.
13. What Comes Next
Module 7 — DDR Commands takes the encodings this module has consistently deferred to it.
Every chapter here described what a signal carries and stopped short of what the values mean. Chapter 6.6 reported a three-bit legacy_cmd without decoding it; Chapter 6.5 established that a column command starts the data pipeline without saying how a column command is expressed. Module 7 closes that gap, and it can do so quickly because the signals are now understood — which was this module's purpose.
After that the structure fills in: Module 8 gives addresses their fields, Module 9 makes activate and precharge concrete, Modules 10 to 12 cover reads, writes and bursts, and Modules 13 and 14 finally attach the timing this module has consistently declined to invent.
Return to CK / CK# for the taxonomy this module used throughout, DQ for the ownership discipline the data path runs on, or The Memory-Subsystem View for the structure these signals address. The full path is on the DDR tutorials index.
Continue learning
Related tutorials
- Related topic
WE# — Write Enable
WE# selects direction, the smallest of the trio's jobs. The trio's real lesson is what happened when three signals could no longer encode enough commands — and DDR4's answer is this module's clearest case of pins giving way to encoding.
- Related topic
Eye Centering
A second axis turns a line search into a grid search, the probe count into a product, and the centre into something undefined. The grid is a measured proxy for an eye — and JEDEC says of its own receiver mask that it is not the eye.
- 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
Restore Operations
Sensing consumed the stored state, so something must put it back. What restoration drives, why it covers a whole row, why a restored row is then cheap to access again, and an educational control model that cannot skip a prerequisite the array is unable to enforce.
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.
