DDR · Module 6
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.
Chapters 6.4 and 6.5 covered the trio's row and column halves. WE# is the third member and has the simplest job: it selects direction. With a column command, WE# asserted means write and deasserted means read.
That takes one sentence, and this chapter is not about it.
The trio's real lesson is arithmetic:
Three signals give eight encodings. What happens when you need a ninth?
DDR4's answer is the clearest demonstration in this module of Chapter 6.1's thesis — dedicated pins giving way to encoding — and it is the reason 6.4 and 6.5 both ended by pointing here.
1. The Smallest Job
WE# distinguishes a write from a read at the moment a column command is issued.
Two observations make it more interesting than it sounds.
Direction is decided at command time, not at data time. Chapter 6.5 §4 established that a column command commits the data bus to a transfer beginning a fixed interval later — and the direction of that transfer is fixed by WE# at the command, not when the data moves. A controller therefore knows which way the bus will point well before it points that way, which is what makes Chapter 6.9's ownership problem schedulable rather than reactive.
And direction is orthogonal to everything else in the encoding. RAS# and CAS# between them say what kind of access; WE# says which way. That orthogonality is exactly what makes a three-signal encoding efficient — and, as §2 shows, exactly what makes it run out.
2. Eight Encodings
Three binary signals give eight combinations, and CS# qualifies whether any of them applies:
{RAS#, CAS#, WE#} -> 8 possible encodings
CS# deasserted -> none of them apply (deselect)Eight was generous in the SDR era and became tight. Two independent pressures push on the same scarce resource, and they push from opposite directions.
More commands were needed. Each generation added capability — Chapter 4.3 added termination control, Chapter 4.4 added calibration, and mode-register operations, refresh variants and power-state transitions all need encodings. Eight slots, several of which are spoken for by the basic accesses, does not leave much.
And more row-address bits were needed. Chapter 5.1 §11 worked the arithmetic: a device with 65 536 rows needs a 16-bit row address, and capacity grew by adding rows. Row address is the widest field the interface must carry, and it must be carried at activate time.
3. DDR4's Answer
DDR4 adds ACT_n — a dedicated signal whose only job is to say which interpretation applies to three shared pins.
ACT_n LOW -> this is an ACTIVATE
RAS_n/A16, CAS_n/A15, WE_n/A14 carry A16, A15, A14
the command needs no further encoding
ACT_n HIGH -> this is some other command
the same three pins carry RAS_n, CAS_n, WE_n
the legacy encoding appliesNotice what ACT_n cost and what it bought. It cost one pin. It bought three address bits during activates and preserved the eight-encoding command space for everything else — and, separately, it removed the activate from the encoding space entirely, freeing a slot.
The trade is favourable because the two needs are anti-correlated, which is the general condition for this move. Multiplexing two functions onto shared wires is only possible when they are never needed simultaneously, and recognising that anti-correlation is the design insight. Without it, ACT_n would simply be a fourth command signal and would have bought nothing.
4. RTL — The Multi-Function Pin
Engineering problem
Three pins carry different things at different events, and a single signal decides which. Decode them correctly — and make a decoder that ignores the selector produce visibly wrong results, because that is the failure Chapter 6.4 §9 identified as the most common on DDR4.
Classification
SYNTHESIZABLE RTL. A multi-function pin decoder, which is genuinely present in any DDR4 controller's command path and in any monitor watching one.
What it represents: the DDR4 pin multiplexing exactly as specified — ACT_n selecting between address and command interpretations of three shared pins.
What it does not represent: the meaning of the legacy command encodings, which is Module 7's; the row address's decomposition into structural fields, which is Modules 8 and 18'; any timing; any electrical property. It decodes which interpretation applies and assembles the fields — it does not say what any command does.
Interface contract
act_n, cs_n and sample_evt qualify the event. The three shared pins plus the always-address low bits come in; is_activate with row_addr, or legacy_cmd with cmd_valid, come out.
State
Registered outputs only. The decode itself is combinational, which is correct: the interpretation is a property of the event, not of history.
Combinational behaviour
The selection and both field assemblies.
Sequential behaviour
Output registration at the sampling event.
How to simulate
vlog ca_pin_mux.sv tb_ca_pin_mux.sv then vsim -c tb_ca_pin_mux -do "run -all".
Expected result: the same three pin values decode to a row-address fragment or to a command encoding depending solely on ACT_n, and the two output paths are never simultaneously valid.
// ─────────────────────────────────────────────────────────────────────────
// CA PIN MUX. Classification: SYNTHESIZABLE RTL.
//
// DDR4 MULTI-FUNCTION COMMAND PINS. Three balls carry different things at
// different events and ACT_n decides which:
//
// ACT_n LOW -> RAS_n/A16, CAS_n/A15, WE_n/A14 carry A16, A15, A14
// ACT_n HIGH -> the same three carry RAS_n, CAS_n, WE_n
//
// The multiplexing works because the two needs are ANTI-CORRELATED: an
// activate needs the most address bits and almost no command encoding,
// while every other command needs the reverse. They never coincide.
//
// WHAT THIS DOES NOT REPRESENT: the MEANING of the legacy encodings
// (Module 7), the row address's decomposition into structural fields
// (Modules 8/18), any timing, any electrical property. It decodes WHICH
// INTERPRETATION APPLIES and assembles the fields. It does not say what
// any command does.
//
// GENERATION: DDR4. DDR3 and earlier have dedicated pins and need no
// selector; DDR5 encodes commands differently again.
// ─────────────────────────────────────────────────────────────────────────
module ca_pin_mux #(
// Total row-address width including the three multiplexed bits.
parameter int ROW_W = 17
) (
input logic clk,
input logic rst_n,
input logic sample_evt,
input logic cs_n,
// THE SELECTOR. Without consulting this, the three pins below cannot be
// interpreted at all -- which is the entire point of the block.
input logic act_n,
// The three multi-function pins, named as the balls are named.
input logic pin_ras_a16,
input logic pin_cas_a15,
input logic pin_we_a14,
// Address bits that are always address, whatever ACT_n says.
input logic [ROW_W-4:0] addr_low,
// ── Activate path.
output logic is_activate,
output logic [ROW_W-1:0] row_addr,
// ── Legacy command path: {RAS_n, CAS_n, WE_n}.
output logic [2:0] legacy_cmd,
output logic cmd_valid
);
// ── COMPILE-TIME legality. Three bits are multiplexed, so the row
// address must have room for them plus at least one always-address
// bit -- otherwise addr_low would be zero-width or negative.
if (ROW_W < 4) begin : g_row_w
initial $fatal(1, "ca_pin_mux: ROW_W must be >= 4 (three muxed bits plus addr_low)");
end
// ── Qualification. An unselected event carries no command, so neither
// interpretation applies and the pins mean nothing at all -- exactly
// as Chapter 6.3 established.
logic qualified;
assign qualified = sample_evt && !cs_n;
logic activate_now;
assign activate_now = qualified && !act_n;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
is_activate <= 1'b0;
row_addr <= '0;
legacy_cmd <= 3'b111;
cmd_valid <= 1'b0;
end else begin
is_activate <= 1'b0;
cmd_valid <= 1'b0;
if (activate_now) begin
// ACT_n LOW: the three pins are the TOP THREE ROW ADDRESS BITS.
// Assembled here in their address positions, which is the step a
// naive decoder skips -- it reads them as a command encoding and
// reports a phantom command on every single activate.
row_addr <= {pin_ras_a16, pin_cas_a15, pin_we_a14, addr_low};
is_activate <= 1'b1;
end else if (qualified) begin
// ACT_n HIGH: the legacy three-signal encoding. What it MEANS is
// Module 7's subject; this block only reports which encoding was
// presented.
legacy_cmd <= {pin_ras_a16, pin_cas_a15, pin_we_a14};
cmd_valid <= 1'b1;
end
end
end
endmoduleCycle-by-cycle example
ROW_W = 17, so addr_low is 14 bits:
| Cycle | cs_n | act_n | Three pins | Decoded as |
|---|---|---|---|---|
| 0 | 0 | 0 | 101 | activate, row bits A16..A14 = 101 |
| 2 | 0 | 1 | 101 | command encoding 101 |
| 4 | 0 | 0 | 011 | activate, row bits = 011 |
| 6 | 1 | 1 | 011 | nothing — deselect |
Cycles 0 and 2 carry the identical pin value 101 and decode to entirely different things. One is part of a row address; the other is a command encoding. Nothing about the three pins distinguishes them — only ACT_n does.
That is the failure mode in one table. A decoder that ignores ACT_n reads cycle 0's 101 as a command, reports it, and does so on every activate — which is Chapter 6.4 §9's first debugging mechanism and its exact signature: phantom commands correlated precisely with real activates.
Waveform expectation
§5. Watch is_activate and cmd_valid never assert together, and the same pin values producing different outputs.
Synthesis implication
A multiplexer, a concatenation and a handful of registers. Negligible. In a real controller the same structure runs in reverse on the transmit side — the controller must drive those pins with address or command depending on what it is issuing, which is the same multiplexing with the direction reversed.
Corner cases
ROW_W == 4 gives a one-bit addr_low, the minimum legal configuration, and is worth testing because the concatenation's widths are easiest to get wrong there. A deselect event produces neither output regardless of ACT_n. Reset leaves legacy_cmd at all-ones, which is the deassert state of three active-low signals — a more honest reset value than zero, which would read as a valid command encoding.
Debugging clues
If phantom commands appear on every activate, ACT_n is not being consulted — the single most common DDR4 decode bug and the reason this block exists. If the row address is short by three bits or has them in the wrong positions, check the concatenation order: the multiplexed bits are the most significant three, and placing them at the bottom produces addresses that are plausible and wrong. If commands are decoded during activates and addresses during commands, ACT_n's polarity is inverted — it is active low, so low means activate.
Limitations
No command meaning — Module 7 owns the encodings' semantics, and this block deliberately reports the raw three bits. No address decomposition into bank, row and column fields, which is Modules 8 and 18. No timing, no electrical behaviour. And it is DDR4-specific: DDR3 needs no selector and DDR5 works differently, so a controller supporting several generations needs this path to be configurable rather than fixed.
5. Two Meanings, One Set of Wires
ca_pin_mux — the same three pins as address, then as command
10 cyclesCycles 0 and 2 are the chapter. The pins[2:0] trace shows 101 at both, and the outputs are completely different: a row-address fragment at cycle 0, a command encoding at cycle 2. The wires are identical. Only ACT_n differs.
A monitor that captured pins[2:0] and not act_n would record two identical events and could not explain why the device did different things — which is exactly Chapter 6.3 §4's point about CS# arriving again for a different signal. The command bus does not carry enough information to interpret itself.
Cycle 6 is deselect, and the pins carry 011 meaning nothing at all. Three signals, three different meanings across the trace: address, command, and nothing.
Representative educational cycles. The command spacing is chosen for legibility.
6. Three Assertions Worth Writing
// VERIFICATION-ONLY, inside ca_pin_mux.
// P1 -- the two interpretations are MUTUALLY EXCLUSIVE. An event is an
// activate or a legacy command, never both. A decoder that could report
// both would mean the pins were being read two ways at once, which is the
// phantom-command bug expressed as a property.
property p_interpretations_exclusive;
@(posedge clk) disable iff (!rst_n)
!(is_activate && cmd_valid);
endproperty
assert property (p_interpretations_exclusive);
// P2 -- and EXHAUSTIVE over qualified events, so a decoder that reports
// nothing cannot satisfy P1 vacuously.
property p_interpretations_exhaustive;
@(posedge clk) disable iff (!rst_n)
(sample_evt && !cs_n) |=> (is_activate ^ cmd_valid);
endproperty
assert property (p_interpretations_exhaustive);
// P3 -- THE SELECTOR PROPERTY. The interpretation follows ACT_n and
// nothing else. This is the chapter's architectural claim, and it is the
// property that fails when a decoder ignores the selector -- the single
// most common DDR4 decode fault.
property p_act_n_selects;
@(posedge clk) disable iff (!rst_n)
is_activate |-> !$past(act_n);
endproperty
assert property (p_act_n_selects);
property p_cmd_requires_act_high;
@(posedge clk) disable iff (!rst_n)
cmd_valid |-> $past(act_n);
endproperty
assert property (p_cmd_requires_act_high);
// P4 -- the multiplexed bits land in the TOP of the row address. Guards
// the concatenation order, whose failure produces addresses that are
// entirely plausible and entirely wrong -- the worst kind, because nothing
// downstream objects.
property p_muxed_bits_are_msbs;
@(posedge clk) disable iff (!rst_n)
is_activate |-> (row_addr[ROW_W-1:ROW_W-3]
== {$past(pin_ras_a16), $past(pin_cas_a15), $past(pin_we_a14)});
endproperty
assert property (p_muxed_bits_are_msbs);P3 and its companion are the pair that matters, because they assert the dependency rather than the outputs. A decoder that produced correct-looking activates and commands by some other rule — a counter, a pattern match — would satisfy P1, P2 and P4 and fail these.
P4 guards a silent failure. A concatenation that puts the multiplexed bits at the bottom of the row address produces a valid row address for the wrong row, every time, with nothing anywhere objecting. Chapter 5.2 §4 established that a wrong-row access returns plausible data with no error — so this property is standing between a wiring order and silent data corruption.
What none of them prove. Nothing about what any command means — Module 7 owns that, and legacy_cmd is deliberately reported raw. Nothing about whether the row address is correct for the request, which is Module 18's mapping question. Nothing about timing or stability, which is Chapter 6.1's analog contract. And nothing about DDR5, whose encoding this block does not model.
7. What the Trio Teaches
Three chapters on three signals, and the argument they make together is larger than any of them.
A dedicated pin is justified by frequency, not by importance. Chapter 6.3 established that chip select keeps its pin because selection is needed at every event. The trio lost theirs because command encoding is needed at every event but these particular three bits are not — during an activate, the command is already fully identified by ACT_n.
Multiplexing requires anti-correlation, not merely spare capacity. The move worked because activates need maximum address and minimum encoding while other commands need the reverse. Two functions that are both needed at the same event cannot share wires, no matter how much either one is wasting individually.
And a selector is cheaper than the capacity it unlocks. ACT_n costs one pin and buys three address bits plus a freed encoding slot. That ratio is why the technique keeps recurring — Chapter 6.2 §6 showed DDR5 removing CKE's pin and Chapter 6.7 shows the same for ODT, both by making CS_n and the CA bus carry more.
The direction of travel is consistent across every generation in this module: functions that were wires become functions that are encodings, and the pins that survive are the ones that cannot be.
8. Common Misconceptions
"RAS#, CAS# and WE# are how DDR commands are encoded."
Wrong model: the trio is the command encoding across DDR generations.
Why it is tempting: it was true from SDR through DDR3, and the vocabulary persists everywhere — including in DDR4 pin names.
Consequence: a wrong reading of any DDR4 command table, and concretely the phantom-command decode of §4: reading 101 on the shared pins as a command when ACT_n was low and it was row address. The phantoms correlate exactly with activates, which is the diagnostic fingerprint.
Correct model: the trio encodes commands in SDR through DDR3. In DDR4 those balls are multi-function and ACT_n selects; the activate itself is signalled by ACT_n rather than by an encoding. DDR5 encodes differently again.
Prevention: before decoding a command interface, find the signal that selects the interpretation. If you cannot name it, you cannot decode the bus.
"ACT_n is just a fourth command signal." Wrong model: DDR4 added a command bit, expanding the encoding space from eight to sixteen. Why it is tempting: it is a new signal on the command path, and adding a bit doubling the space is the obvious reading. Consequence: missing the actual mechanism entirely. If ACT_n were merely a fourth command bit, the three shared pins would still be command-only and no address bits would have been gained — which was the pressure that motivated the change. Correct model: ACT_n is a mode selector, not an encoding bit. It decides whether three pins are address or command. It buys address capacity, not encoding capacity — though it also frees the activate's old encoding slot as a side effect. Prevention: ask what changes when the signal changes. An encoding bit changes which command; a selector changes what the other pins are.
"WE# is the most important of the three, since it decides read versus write." Wrong model: direction selection is the trio's principal function. Why it is tempting: read versus write is the most visible distinction in memory traffic. Consequence: under-weighting the row/column distinction, which is where the cost asymmetry lives. Chapter 6.5 §1 showed that a row access is expensive, destructive and infrequent while a column access is cheap and repeatable — and WE# is orthogonal to that entirely. A read and a write to an open row cost nearly the same; a row conflict costs far more than either. Correct model: WE# selects direction, which is the smallest of the three jobs. Direction matters enormously for bus ownership and turnaround, and hardly at all for access cost. Prevention: ask what dominates the cost of an access. It is which row is open, not which way the data flows.
"Multi-function pins are a hack that makes the interface fragile." Wrong model: pin reuse is a compromise that weakens the design. Why it is tempting: sharing wires sounds like a source of ambiguity, and the phantom-decode failure is real. Consequence: misjudging the trade — and, practically, designing a monitor or controller that treats the multiplexing as an edge case rather than as the normal operation it is. Correct model: the interpretation is deterministic and unambiguous at every event, selected by a signal present at that same event. There is no ambiguity in the hardware. The fragility is entirely in decoders that ignore the selector, and the alternative — adding pins to the most heavily loaded signal group in the system — was worse by a large margin. Prevention: separate "ambiguous" from "requires context". The interface is the second, and so is almost every efficient encoding.
9. Debugging — A Controller Activates the Wrong Row
Symptom. A DDR4 system opens rows other than the ones the controller intended. Data comes back plausible but wrong, or accesses land in unexpected places. No errors reported anywhere.
"Plausible but wrong" is the signature of an address fault rather than a signalling fault — the interface is working, and it is being told the wrong thing or being read the wrong way.
Mechanism 1 — the multiplexed bits are assembled in the wrong positions. Inspect: whether the three shared pins land in the top three positions of the row address. Expected evidence: accessed rows differing from intended ones by a permutation of high-order bits. Discriminator: compare the intended row number against the accessed one in binary. If the discrepancy is confined to the top three bits, this is it — and §6's P4 exists precisely to catch it before silicon.
Mechanism 2 — ACT_n polarity is inverted somewhere. Inspect: whether activates are being decoded as commands and vice versa. Expected evidence: phantom commands during activates and activates apparently missing. Discriminator: are both interpretations wrong, or only one? A missing selector consultation (Chapter 6.4 §9) breaks one direction; an inverted polarity breaks both, which is a cleanly different signature.
Mechanism 3 — the row address is correct and the mapping is wrong. Inspect: the controller's address-to-field decomposition upstream of the pins. Expected evidence: the pins faithfully carrying a row number the controller genuinely intended, which is simply not the row the requester wanted. Discriminator: compare at two points — requester intent, and pin values. If the pins match the controller's intent, the interface is innocent and the fault is Module 18's mapping.
Mechanism 4 — not addressing: the row was never opened. Inspect: whether a column access is being served by a previously open row. Expected evidence: data from a row that was legitimately open earlier. Discriminator: did an activate for this row actually occur? Chapter 5.2 §4's silent mismatch — a column command serves whatever row is open, and if the activate was lost (to CKE, to a refused command, to anything) the column access proceeds against the wrong row with no complaint.
Mechanism 5 — the wrong device responded. Inspect: which rank acted. Expected evidence: the right row in the wrong rank. Discriminator: Chapter 6.3 §9's question — wrong device, or right device doing the wrong thing? This splits the entire investigation and is available from the first trace.
Discrimination, cheapest first. Ask whether the wrong device or the wrong row — one question, splitting mechanism 5 off. Then compare intended and accessed row numbers in binary, because a discrepancy confined to the top three bits names mechanism 1 outright. Then check whether an activate for the row actually occurred. Then compare requester intent against pin values.
The reasoning lesson. Comparing addresses in binary rather than in decimal is the whole diagnostic here, and it costs nothing. A row number that is wrong by an arbitrary-looking decimal amount is opaque; the same pair written in binary immediately shows whether the error is confined to particular bit positions — and bit-position-confined errors name a wiring or concatenation fault, while scattered errors name a mapping or state fault. The same discipline applies to data corruption and to mask faults, and it is one of the highest-yield habits in interface debugging.
10. Interview Reasoning
"What does WE# do, and why is it the least interesting of the three?" It selects direction — with a column command, asserted means write and deasserted means read. It is the least interesting because direction is orthogonal to access cost: a read and a write to an already-open row cost nearly the same, while a row conflict costs far more than either, and that distinction belongs to RAS# and CAS#. Where direction does matter enormously is bus ownership, because it is fixed at command time rather than at data time — so the controller knows which way the data bus will point a full latency interval before it points that way, which is what makes ownership schedulable rather than reactive.
"Three command signals give eight encodings. What happened when that was not enough?" Two pressures grew at once and both pointed at pins. More commands were needed as generations added termination control, calibration, mode-register operations and power-state transitions; and more row-address bits were needed as capacity grew by adding rows. Adding pins was the obvious answer and the one thing the interface could least afford, because command and address signals reach every device and are the most heavily loaded in the system. DDR4's answer was to notice that the two needs are anti-correlated in time — an activate needs the maximum address and almost no command encoding, while every other command needs the reverse — and to multiplex the three command pins with three address bits, with ACT_n selecting which interpretation applies.
"Is ACT_n a fourth command bit?" No, and the distinction matters. A fourth command bit would double the encoding space and gain no address capacity, which was the actual pressure. ACT_n is a mode selector: it decides whether three shared pins carry A16, A15 and A14 or carry RAS_n, CAS_n and WE_n. It costs one pin and buys three address bits during activates, while preserving the legacy encoding space for everything else and incidentally freeing the activate's old encoding slot. The test for the general case is to ask what changes when the signal changes — an encoding bit changes which command, and a selector changes what the other pins are.
"Why is multiplexing possible here but not in general?" Because the two functions are never needed at the same event. Multiplexing requires anti-correlation, not merely that each function has spare capacity some of the time. An activate needs the most address bits and is fully identified by ACT_n alone, so its command encoding is spare; every other command needs no full row address, so those address bits are spare. If both were needed simultaneously at any event the sharing would be impossible regardless of how much either wasted individually. That condition is what a designer looks for before proposing pin reuse.
"A DDR4 system opens the wrong rows. Where do you start?" First by asking whether the wrong device responded or the right device opened the wrong row, because those are disjoint investigations and the answer is in the first trace. Then — and this is the highest-yield step — compare the intended row number against the accessed one in binary rather than decimal. If the discrepancy is confined to the top three bits, the multiplexed pins are being assembled in the wrong positions, which produces entirely plausible addresses for entirely wrong rows with nothing objecting. If activates are being decoded as commands and commands as activates in both directions, ACT_n's polarity is inverted. If the pins faithfully carry a row the controller genuinely intended, the interface is innocent and the fault is in address mapping upstream. And it is worth confirming an activate for that row actually happened at all, because a column access serves whatever row is open, so a lost activate produces exactly this symptom silently.
11. Engineering Exercise
DDR4 mechanism; educational values where numbers appear.
1. During a DDR4 activate, what is the WE_n/A14 ball carrying? A14 — a row-address bit. ACT_n is low, which selects the address interpretation. The signal named "write enable" is carrying part of a row address, and the command is not a write at all.
2. A monitor decodes the three shared pins as a command on every qualified event. What does it report during activates, and how would you recognise the fault? It reports a phantom command on every activate, decoded from row-address bits. Recognition is immediate: the phantom rate equals the activate rate, and the phantoms disappear entirely in traffic with no activates. That exact correlation is the fingerprint, and it is Chapter 6.4 §9's first mechanism.
3. Why could DDR4 not simply add three more address pins instead? Because address and command signals must reach every device on the channel, making them the most heavily loaded signals in the system — Chapter 4.4 §2 showed DDR3 had already changed the board topology to cope. Three more such pins cost package area, traces, drivers, receivers and switching energy on the worst signals available, and Chapter 4.5 §3 established DDR4's whole approach was to avoid adding pins.
4. ACT_n costs one pin. Count what it bought. Three address bits during activates, the eight-encoding command space preserved for everything else, and one encoding slot freed because the activate no longer needs one. One pin for three bits plus a slot — and the ratio is why the technique recurs throughout the generations.
5. §4's concatenation places the multiplexed bits at the top of row_addr. Suppose a design placed them at the bottom. What is the symptom? Every activate opens a valid row that is not the intended one, with the error confined to a permutation of bit positions. Nothing objects anywhere — the address is well-formed, the device activates successfully, and the subsequent column access returns plausible data from the wrong row. §6's P4 is standing between a concatenation order and silent corruption, which is why it is worth writing.
6. Could the same multiplexing trick have worked if activates also needed a full command encoding? No — and this is the general condition. Multiplexing requires the two functions to be anti-correlated in time. If an activate needed both the maximum row address and a distinct multi-bit command encoding at the same event, the pins would be needed for both simultaneously and no selector could resolve it. Spare capacity is not sufficient; non-coincidence is what is required.
12. Summary
WE# selects direction — write or read at a column command — which is the smallest of the trio's jobs. Direction is fixed at command time, not at data time, which is what makes bus ownership a scheduled property rather than a reactive one. And it is orthogonal to access cost: a read and a write to an open row cost nearly the same, while a row conflict costs far more than either.
The trio's real lesson is arithmetic. Three signals give eight encodings, and two independent pressures grew against that ceiling: more commands as generations added capability, and more row-address bits as capacity grew by adding rows. Both pressures point at pins, and pins on the command path are the most expensive in the system because those signals reach every device.
DDR4's answer was to find capacity already present and wasted. An activate needs the maximum address bits and is fully identified without a command encoding; every other command needs no full row address. The two needs are anti-correlated in time, which is the precondition for multiplexing.
ACT_n is a mode selector, not a fourth command bit. Low means the three shared balls carry A16, A15, A14; high means they carry RAS_n, CAS_n, WE_n. It cost one pin and bought three address bits, a preserved encoding space, and a freed slot.
The decode failure is the module's most common. Identical pin values decode to completely different things depending solely on ACT_n, so a decoder that ignores the selector reports a phantom command on every activate — with the phantom rate exactly equal to the activate rate, which is the diagnostic fingerprint. And a concatenation that misplaces the multiplexed bits produces valid addresses for wrong rows, silently.
The trio's general lessons carry forward. A dedicated pin is justified by frequency, not importance. Multiplexing requires anti-correlation, not spare capacity. And a selector is cheaper than the capacity it unlocks — which is why CKE and ODT later went the same way.
13. What Comes Next
Chapter 6.7 takes the next signal to lose its pin.
ODT controls termination — which devices present a terminating load, and when. Chapter 4.3 §3 established why on-die termination exists and why it had to be controllable; this chapter covers the signal that controls it, its per-rank policy, and the read-versus-write asymmetry that makes the policy non-obvious.
And it is the second signal DDR5 encoded away, for exactly the reasons §7 set out — which makes it the chapter where the module's thesis stops being an observation and becomes a predictable rule.
Return to RAS# and CAS# for the trio's other members, CS# for the qualification that gates all three, or DDR4 for the generation-level argument this chapter's mechanism serves. Module 7 owns what the encodings mean. The full path is on the DDR tutorials index.
Continue learning
Related tutorials
- Related topic
DDR4
DDR4 is the generation where prefetch depth stops changing. With granularity already at a cache line, the rate had to come from overlapping independent accesses instead — which is what bank groups are, and why peak bandwidth became conditional on the access pattern.
- Related topic
Bank Groups
Not all bank pairs are equally independent. A bank group is the scope at which the internal column data path is shared, and the three-way classification of a request against its predecessor is the interface every later timing module consumes.
- Related topic
RAS# — Row Address Strobe
RAS# is named after a mechanism it no longer uses. In asynchronous DRAM it was literally a clock that latched a row address; in synchronous DRAM it became a level sampled by CK — and in DDR4 it is not even a dedicated pin.
- Related topic
CAS# — Column Address Strobe
A column command is where the data pipeline begins, so the interval from it to data arriving became the number everyone quotes. CAS latency is named after a signal that is no longer a dedicated pin.
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.
