DDR · Module 7
Read (RD / RDA)
READ names a column in a row that is already open — it opens nothing. And RDA is not a separate command but a READ carrying one address bit high, which is why a decoder must identify the operation before interpreting any operand.
Chapter 7.1 established the command model and built the encoder — semantic operation in, generation-specific interface values out. This chapter builds the decoder, and the two are not symmetric in an important way.
An encoder knows the operation and places the operands. A decoder receives everything at once and must work out the operation before it can interpret anything else — because, as Chapter 7.1 §5 established, an operand's meaning depends on which command carries it.
READ is the right command for this, because it has the clearest case of that dependence. So the chapter's question is:
How does a decoder turn sampled bits into a semantic command with operands — and what does READ actually require?
The second half matters as much as the first. READ does not open a row. It reads from one that is already open, and the misconception that it opens the row it names is one of the most consequential in the module.
1. READ Reads an Open Row
Semantically, READ says: return the data at column C of the row currently open in bank B.
Three things follow, and the first is the one people get wrong.
It does not open a row. The row must already be open. Chapter 5.2 §4 established the mechanism: a column command carries no row address at all. It names a column within whatever the bank is currently holding in its sense amplifiers, and the device has no idea which row the controller intended.
So READ's prerequisite is state, not encoding. The bank must be open, and it must be open with the right row. The device can detect the first and cannot detect the second — which is why Chapter 5.2 called the controller's per-bank open-row table a correctness structure.
And it changes no row state. A read is non-destructive at this level — the row stays open, and further columns of it can be read without any further activate. Chapter 6.5 §1 established the asymmetry: one activate serves many column accesses, and that ratio is why the row buffer matters.
The last two messages are the point. Neither read carries a row address, and the second needs no new activate. The row is state the command relies on and does not describe — and if the controller's model of that state is wrong, the device serves the wrong row's data correctly, with nothing reported anywhere.
2. Decode Is Ordered
Now the decoder, and the discipline that makes it correct.
A decoder cannot extract operands in parallel with identifying the operation, because operand meanings depend on the operation. The decode has a mandatory order:
1. QUALIFIED? is chip select asserted? (no -> not a command)
2. WHICH OP? identify the operation (generation-specific)
3. OPERANDS interpret the fields FOR THAT OP
4. LEGAL? is the operation allowed in current state?Step 4 is in the figure and outside the decoder. Chapter 7.1 §1's four questions: decode answers "what operation", and whether it is allowed is a different question with a different owner. A decoder that returned "illegal" for a state violation would be conflating them — so §4's block reports unrecognised encodings and says nothing about state.
3. RDA Is a READ, Not Another Command
Here is the operand that makes the ordering necessary.
Verified DDR4 behaviour: address bit A10 sampled with a READ or WRITE selects auto-precharge. High enables it; low does not.
So "RDA" is not a distinct command. It is a READ whose A10 operand is high, and its effect is that the device precharges the bank itself after the access completes — without the controller issuing a separate precharge.
Three consequences, and the third is the one that bites.
It changes row state. An ordinary READ leaves the bank open; a READ with auto-precharge leaves it closed. Same encoding, same operation, opposite state consequence — decided by one operand bit.
It saves a command. The controller does not have to issue the precharge, which frees a command-bus event. Chapter 6.3 §3 established that the command bus is a real resource, so this is a genuine saving.
And it makes the state change implicit. The bank closes and no command on the bus says so. A monitor watching commands alone will believe the bank is still open — which is Chapter 7.4 §5's central monitoring problem, and the reason auto-precharge is introduced here and paid for there.
4. RTL — The Command Decoder
Engineering problem
Recover a semantic command and its operands from sampled interface values, in the correct order: qualification, then operation, then operands interpreted for that operation. Report unrecognised encodings without guessing.
Classification
SYNTHESIZABLE RTL. A command decoder — present in a DRAM device's front end, in a controller's own loopback checking, and in every DV command monitor.
What it represents: the ordered decode, the operation identification, and operand interpretation that depends on the operation.
What it does not represent: state legality — it reports what operation was requested and says nothing about whether it is permitted, because Chapter 7.1 §1's questions three and four have different owners. Chapter 5.2's ddr_bank_state_table already holds per-bank state and checks legality against it, and this block deliberately does not duplicate it. Also absent: timing, the data path, address-field decomposition (Module 8), and any analog property.
The command bit values are the same educational placeholders as Chapter 7.1 §4 — not JEDEC encodings. The A10 operand behaviour is verified and real.
Interface contract
sample_evt, cs_n, act_n and the interface values come in. cmd_out with cmd_valid_out and the operand outputs come out. decode_unrecognised reports an encoding the decoder does not know.
State
Registered outputs only. Decode is combinational from the sampled values — a command's meaning does not depend on history, with the single exception Chapter 7.6 introduces.
Combinational behaviour
The ordered decode.
Sequential behaviour
Output registration.
How to simulate
vlog ddr_cmd_decode.sv tb_ddr_cmd_decode.sv then vsim -c tb_ddr_cmd_decode -do "run -all".
Expected output
The same encoding with A10 low and A10 high produces DDR_CMD_RD both times, with op_autoprecharge differing — and a precharge encoding with A10 high produces DDR_CMD_PRE with op_allbank set and op_autoprecharge clear.
// ─────────────────────────────────────────────────────────────────────────
// DDR COMMAND DECODER. Classification: SYNTHESIZABLE RTL.
//
// The inverse of Chapter 7.1's encoder, and NOT symmetric with it. An
// encoder knows the operation and places operands; a DECODER receives
// everything at once and must identify the operation BEFORE interpreting
// anything else.
//
// DECODE IS ORDERED:
// 1. qualified? (chip select) -- no -> not a command at all
// 2. which operation? -- generation-specific encoding
// 3. operands, INTERPRETED FOR THAT OPERATION
// 4. legal? -- NOT THIS BLOCK'S QUESTION
//
// WHY THE ORDER IS MANDATORY: operand meanings depend on the operation.
// VERIFIED DDR4 BEHAVIOUR: address bit A10 sampled with a READ or WRITE
// selects AUTO-PRECHARGE; the same bit sampled with a PRECHARGE selects
// SCOPE (all banks vs one). A decoder that extracts A10 as a fixed field
// misreads it on half the commands it sees.
//
// WHAT THIS DOES NOT REPRESENT: state legality. It reports the requested
// operation and says nothing about whether it is permitted -- Chapter 5.2's
// ddr_bank_state_table already holds per-bank state and checks legality,
// and this block does not duplicate it. Also absent: timing (Modules
// 13/14), the data path (Modules 10/12), address-field decomposition
// (Module 8), and every analog property.
//
// ###### THE COMMAND BIT VALUES ARE EDUCATIONAL PLACEHOLDERS ######
// Same values as Chapter 7.1 Section 4. NOT JEDEC encodings.
// The A10 OPERAND BEHAVIOUR, by contrast, is verified and real.
// #################################################################
// ─────────────────────────────────────────────────────────────────────────
module ddr_cmd_decode #(
parameter int GEN = 4,
parameter int ROW_W = 17,
parameter int BANK_W = 4,
parameter int COL_W = 10,
// Width of the address field presented at a command event. Wide enough
// to carry a row address, since that is the widest operand.
parameter int ADDR_W = 17,
// Position of the dual-purpose bit within that field.
parameter int AP_BIT = 10
) (
input logic clk,
input logic rst_n,
input logic sample_evt,
input logic cs_n,
// Present in the DDR4-style encoding. Ignored at GEN 3.
input logic act_n,
input logic pin_ras_a16,
input logic pin_cas_a15,
input logic pin_we_a14,
input logic [ADDR_W-1:0] addr_in,
input logic [BANK_W-1:0] bank_in,
// ── Semantic output.
output ddr_cmd_e cmd_out,
output logic cmd_valid_out,
// ── Operands, interpreted for the decoded operation.
output logic [BANK_W-1:0] op_bank,
output logic [ROW_W-1:0] op_row,
output logic [COL_W-1:0] op_col,
// A10 with a READ or WRITE. Meaningless for other operations and driven
// low there, so a consumer cannot accidentally act on a stale value.
output logic op_autoprecharge,
// A10 with a PRECHARGE. Same bit, different operation, different name.
output logic op_allbank,
// An encoding this decoder does not recognise. Reported; no operation
// and no operands are produced.
output logic decode_unrecognised
);
// ── COMPILE-TIME legality.
if ((GEN != 3) && (GEN != 4)) begin : g_gen
initial $fatal(1, "ddr_cmd_decode: GEN must be 3 or 4 (DDR5 is Module 25)");
end
if (ADDR_W <= AP_BIT) begin : g_ap
initial $fatal(1, "ddr_cmd_decode: ADDR_W must exceed AP_BIT");
end
if (ROW_W < 4 || COL_W < 1 || BANK_W < 1) begin : g_w
initial $fatal(1, "ddr_cmd_decode: operand widths must be >= 4 / 1 / 1");
end
// ── EDUCATIONAL command patterns. Identical to Chapter 7.1's. NOT JEDEC.
localparam logic [2:0] ENC_NOP = 3'b111;
localparam logic [2:0] ENC_ACT = 3'b011;
localparam logic [2:0] ENC_RD = 3'b101;
localparam logic [2:0] ENC_WR = 3'b100;
localparam logic [2:0] ENC_PRE = 3'b010;
localparam logic [2:0] ENC_REF = 3'b001;
localparam logic [2:0] ENC_MRS = 3'b000;
// ── STEP 1: qualification. Chapter 6.3: the command bus is a broadcast
// and an unqualified event is not a command. Nothing downstream runs
// without this, and the CA lines carry no obligation when it fails.
logic qualified;
assign qualified = sample_evt && !cs_n;
logic [2:0] enc;
assign enc = {pin_ras_a16, pin_cas_a15, pin_we_a14};
// ── STEP 2: which operation.
ddr_cmd_e op;
logic op_known;
logic act_via_act_n;
// In the DDR4-style encoding an asserted ACT_n IS the activate
// indication, and the three balls then carry row address rather than an
// encoding -- verified in Chapter 6.6. So the activate must be detected
// from act_n and NOT from the encoding bits, which at that moment are
// address.
assign act_via_act_n = (GEN == 4) && !act_n;
always_comb begin
op = DDR_CMD_NOP;
op_known = 1'b0;
if (act_via_act_n) begin
op = DDR_CMD_ACT;
op_known = 1'b1;
end else begin
unique case (enc)
ENC_NOP: begin op = DDR_CMD_NOP; op_known = 1'b1; end
// At GEN 3 the activate is one of the encodings; at GEN 4 it is
// reached only through act_n, so this arm is unreachable there.
ENC_ACT: begin op = DDR_CMD_ACT; op_known = (GEN == 3); end
ENC_RD: begin op = DDR_CMD_RD; op_known = 1'b1; end
ENC_WR: begin op = DDR_CMD_WR; op_known = 1'b1; end
ENC_PRE: begin op = DDR_CMD_PRE; op_known = 1'b1; end
ENC_REF: begin op = DDR_CMD_REF; op_known = 1'b1; end
ENC_MRS: begin op = DDR_CMD_MRS; op_known = 1'b1; end
default: begin op = DDR_CMD_NOP; op_known = 1'b0; end
endcase
end
end
// ── STEP 3: operands, INTERPRETED FOR THE DECODED OPERATION.
//
// This is where the ordering pays off. A10 is read as an
// auto-precharge flag only for a read or write, and as a scope
// selector only for a precharge. Both outputs are driven LOW for
// every other operation so a consumer cannot act on a value that
// means nothing for the command it accompanies.
logic [BANK_W-1:0] bank_x;
logic [ROW_W-1:0] row_x;
logic [COL_W-1:0] col_x;
logic ap_x, ab_x;
always_comb begin
bank_x = bank_in;
row_x = '0;
col_x = '0;
ap_x = 1'b0;
ab_x = 1'b0;
unique case (op)
DDR_CMD_ACT: begin
// Activate carries a row and no column. At GEN 4 the top three
// row bits arrive on the multi-function balls (Chapter 6.6).
if (GEN == 4) row_x = {pin_ras_a16, pin_cas_a15, pin_we_a14,
addr_in[ROW_W-4:0]};
else row_x = addr_in[ROW_W-1:0];
end
DDR_CMD_RD, DDR_CMD_WR: begin
// Column access. No row operand at all -- Section 1's point, and
// the reason Chapter 5.2's silent mismatch is possible.
col_x = addr_in[COL_W-1:0];
ap_x = addr_in[AP_BIT]; // VERIFIED: A10 = auto-precharge
end
DDR_CMD_PRE: begin
// Same bit, different meaning. VERIFIED: A10 = all-bank scope.
ab_x = addr_in[AP_BIT];
end
// Refresh and mode-register operands are Chapters 7.5 and 7.6's.
// Left at their defaults here rather than guessed at.
default: ;
endcase
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cmd_out <= DDR_CMD_NOP;
cmd_valid_out <= 1'b0;
op_bank <= '0;
op_row <= '0;
op_col <= '0;
op_autoprecharge <= 1'b0;
op_allbank <= 1'b0;
decode_unrecognised <= 1'b0;
end else begin
cmd_valid_out <= 1'b0;
decode_unrecognised <= 1'b0;
if (qualified) begin
if (op_known) begin
cmd_out <= op;
cmd_valid_out <= 1'b1;
op_bank <= bank_x;
op_row <= row_x;
op_col <= col_x;
op_autoprecharge <= ap_x;
op_allbank <= ab_x;
end else begin
// REPORT, NEVER GUESS. An unrecognised encoding produces no
// operation. Substituting a plausible one would hand a consumer
// a command the device never received.
decode_unrecognised <= 1'b1;
end
end
end
end
endmoduleCycle-by-cycle example
GEN = 4, AP_BIT = 10:
| Event | act_n | encoding | addr[10] | cmd_out | op_autoprecharge | op_allbank |
|---|---|---|---|---|---|---|
| 0 | 1 | ENC_RD | 0 | DDR_CMD_RD | 0 | 0 |
| 1 | 1 | ENC_RD | 1 | DDR_CMD_RD | 1 | 0 |
| 2 | 1 | ENC_PRE | 1 | DDR_CMD_PRE | 0 | 1 |
| 3 | 0 | (address) | — | DDR_CMD_ACT | 0 | 0 |
| 4 | 1 | 3'b110 | — | — | — | — (unrecognised) |
Events 0 and 1 are the same command with different state consequences. Identical encoding, identical operation — and event 1 leaves the bank closed because the device precharges it itself.
Event 2 is the ordering payoff. addr[10] is high on both event 1 and event 2, and it means completely different things. op_autoprecharge is low here and op_allbank is high — a decoder extracting A10 as a fixed field would have set the wrong one.
Event 3 reaches ACT through act_n, not through the encoding bits — which at that event are carrying row address, exactly as Chapter 6.6 established.
Waveform expectation
§5. Watch op_autoprecharge and op_allbank never assert together, and neither assert for commands that do not carry them.
Synthesis implication
A small combinational decode, a multiplexer per operand, and output registers. Negligible. In a real device this sits at the command inputs and is on the critical path from the sampling event, so a real implementation would flatten the two always_comb stages into one — the two-stage form here exists to make the ordering visible.
Corner cases
GEN == 3 makes act_via_act_n permanently false, so ACT is reached through the encoding — and the GEN 4 arm becomes unreachable, which is correct rather than dead code. ADDR_W <= AP_BIT does not elaborate, because an out-of-range bit select would be silently zero-padded by some tools and would make auto-precharge permanently inactive. An unrecognised encoding produces no operation and no operands. An unqualified event produces nothing at all.
Debugging clues
If all-bank precharges appear as single-bank ones, or reads appear to request auto-precharge at roughly the rate A10 is high, the operand extraction is not ordered after the operation decode — the single most likely bug in this block. If activates are decoded as garbage commands at GEN 4, act_via_act_n is missing and the encoding bits are being read while they carry address. If op_autoprecharge is set on a refresh or mode-register command, the per-operation defaults are not being applied.
Limitations
No state legality — Chapter 5.2 owns that and this block does not duplicate it. No timing. No data path. No address-field decomposition. No DDR5. And the command bit values are educational, as the header states.
5. Two Meanings of One Operand, in Cycles
ddr_cmd_decode — ordered decode and the dual-purpose operand
10 cyclesCompare cycles 2 and 4. addr[10] is high at both. At cycle 2 the encoding is RD, so the bit is an auto-precharge request and op_autopre asserts at cycle 3. At cycle 4 the encoding is PRE, so the identical bit is an all-bank scope selector and op_allbank asserts at cycle 5.
op_autopre is low at cycle 5 and op_allbank is low at cycle 3. That is the ordered decode working: each output is driven only for the operations it belongs to, so a consumer cannot act on a field that means nothing for the command it accompanies.
Cycle 6's activate is reached through act_n, with the encoding column showing addr because the three balls are carrying row address at that event.
Cycle 8's 110 is unrecognised. No operation, no operands, and a report. Guessing a plausible command here would hand the consumer something the device never received.
Representative educational cycles. The one-cycle decode latency is a property of this model, and the spacing between commands implies no timing requirement.
6. Four Assertions Worth Writing
// VERIFICATION-ONLY, inside ddr_cmd_decode.
// P1 -- THE ORDERING PROPERTY. The auto-precharge output is asserted only
// for a read or write, and the all-bank output only for a precharge. This
// is the whole reason decode must be ordered, and a decoder that extracted
// A10 as a fixed field would violate one of these on roughly half the
// commands it sees.
property p_autoprecharge_only_on_column;
@(posedge clk) disable iff (!rst_n)
op_autoprecharge |-> ((cmd_out == DDR_CMD_RD) || (cmd_out == DDR_CMD_WR));
endproperty
assert property (p_autoprecharge_only_on_column);
property p_allbank_only_on_precharge;
@(posedge clk) disable iff (!rst_n)
op_allbank |-> (cmd_out == DDR_CMD_PRE);
endproperty
assert property (p_allbank_only_on_precharge);
// P2 -- and they are mutually exclusive, because they are the SAME BIT
// interpreted for different operations. Both asserting would mean the
// decoder had identified two operations at once.
property p_operand_meanings_exclusive;
@(posedge clk) disable iff (!rst_n)
!(op_autoprecharge && op_allbank);
endproperty
assert property (p_operand_meanings_exclusive);
// P3 -- an unrecognised encoding yields NO operation. Report, never guess:
// a substituted command would be one the device never received, and the
// consumer's model would diverge silently.
property p_unrecognised_yields_nothing;
@(posedge clk) disable iff (!rst_n)
decode_unrecognised |-> !cmd_valid_out;
endproperty
assert property (p_unrecognised_yields_nothing);
// P4 -- no command without qualification. Chapter 6.3: an unqualified
// event is not a command, so the decoder must produce nothing for it.
property p_no_command_unqualified;
@(posedge clk) disable iff (!rst_n)
cmd_valid_out |-> ($past(sample_evt) && !$past(cs_n));
endproperty
assert property (p_no_command_unqualified);
// P5 -- the liveness companion. P1 to P4 all forbid; a decoder that
// decoded nothing would satisfy every one of them.
property p_known_encoding_decodes;
@(posedge clk) disable iff (!rst_n)
(sample_evt && !cs_n && op_known) |=> cmd_valid_out;
endproperty
assert property (p_known_encoding_decodes);P1 is the chapter's property, and its value is that it catches a bug with no functional error signature. A decoder that mis-extracts A10 produces well-formed commands with wrong flags — the reads look fine, the precharges look fine, and the state consequences diverge. Nothing fails; the model drifts.
P2 is subtle and worth the line. The two outputs describe the same physical bit, so both asserting means the decoder believes the event is simultaneously a column access and a precharge. It should be impossible by construction in §4 — op is a single value — and asserting it anyway guards against a later change that computes the two independently.
What none of them prove. Nothing about state legality: this decoder happily reports a READ to a closed bank, because that is Chapter 5.2's question. Nothing about timing legality. Nothing about whether the encoding values match a real device, which is a specification question no assertion reaches. And nothing about the data the read will return.
7. DV — What a Read Tells a Monitor
READ is the command where a monitor's job gets interesting, because the command and its data are separated in time.
A monitor observing a READ learns three things and must infer a fourth.
It learns the operation and its operands — bank, column, and whether auto-precharge was requested.
It learns which row will be read, only by consulting its own model. The command carries no row. A monitor without a per-bank open-row model cannot say what address was read — it can only report "column C of bank B's current row", which is not an address.
It learns that data will arrive later, and Chapter 6.5 §4 established the interval is a fixed pipeline depth. Correlating the command with its data is the monitor's responsibility, and it is what makes a command monitor different from a bus monitor.
And it must infer the state change if auto-precharge was requested — because §3 established that the bank closes with no command on the bus saying so. Chapter 7.4 §5 builds the monitor that handles this.
The practical shape of a read monitor, therefore:
decode command -> extract operands -> look up open row in own model
-> emit a transaction with a real address
-> schedule expected data arrival
-> if auto-precharge, update own model to closedThe third step is the one that distinguishes a useful monitor from a trace dumper. Without it, every read transaction is missing its row.
8. Debugging — A Read Returned Data From the Wrong Row
Symptom. A read returns well-formed data that belongs to a different row than the requester wanted. No errors anywhere.
This is Chapter 5.2 §4's silent mismatch, and this chapter explains why it is undetectable by the device: the read carries no row address, so the device has nothing to compare against. The controller's model is the only thing that could have caught it.
Mechanism 1 — the controller's model said open and the device had a different row. Inspect: the controller's per-bank open-row table against the sequence of activates and precharges actually issued. Expected evidence: an activate that was never issued, or one that was refused. Discriminator: replay the command stream against a reference bank model. This is first because the model divergence is the bug, and the command trace contains everything needed to find it.
Mechanism 2 — an auto-precharge closed the bank and the model missed it. Inspect: whether earlier reads or writes to that bank carried A10 high. Expected evidence: the bank closing with no precharge command on the bus. Discriminator: look for A10 on prior column commands. §3's implicit state change — and it is a common monitor and controller bug precisely because nothing on the bus announces it.
Mechanism 3 — the decoder mis-extracted A10. Inspect: whether auto-precharge is being reported for the right commands. Expected evidence: reads with A10 high not closing the bank, or precharges being treated as auto-precharge requests. Discriminator: check whether op_autoprecharge ever asserts for a non-column command. §6's P1, and the fingerprint is that the rate of spurious flags tracks how often A10 happens to be high.
Mechanism 4 — the activate opened the wrong row. Inspect: the row operand of the activate, compared in binary. Expected evidence: the intended row differing from the encoded one in the top three bits. Discriminator: Chapter 7.1 §9's mechanism 2 — a discrepancy confined to particular bit positions names a concatenation fault in the encoder, not a state problem.
Mechanism 5 — the wrong rank responded. Inspect: which rank acted. Expected evidence: the right row in the wrong device. Discriminator: Chapter 6.3 §9's question — wrong device, or right device doing the wrong thing? Available from the first trace and it splits the investigation entirely.
Discrimination, cheapest first. Ask whether the wrong device or the wrong row — one question. Then replay the command stream against a reference bank model, which locates the first divergence. Then check prior column commands for A10. Then compare the activate's row operand in binary.
The reasoning lesson. The command stream contains the answer, and the device does not. Because a read carries no row address, the device cannot detect this class of fault and will never report it — so the entire diagnostic burden falls on replaying the commands against a model. That inverts the usual instinct: rather than instrumenting the device or the data, you reconstruct what the commands implied and find where that stopped matching reality. A complete command trace is worth more here than any amount of data inspection, which is exactly why Chapter 7.4 §5's monitor is built the way it is.
9. Common Misconceptions
"READ opens the row it names." Wrong model: a read is self-contained and fetches the addressed location. Why it is tempting: it is how essentially every other memory interface behaves, and a read request naturally names what it wants. Consequence: no activate issued before the read, so the device serves whatever row happens to be open — which may be a legitimately open row from an unrelated access. Chapter 5.2 §4 established this returns plausible, well-formed, wrong data with no error. Correct model: a column command carries no row address at all. It names a column within the row the bank is currently holding. The row must have been opened by a prior ACT, and the controller's model is the only thing that can verify it is the right one. Prevention: ask what the command carries. If there is no row field, the row is state the command depends on and does not describe.
"RDA is a different command from RD." Wrong model: auto-precharge is a separate operation with its own encoding. Why it is tempting: it has its own name in every datasheet and its own row in command tables. Consequence: a decoder that looks for a distinct encoding and never finds one, and — more damagingly — a controller or monitor that treats the two as unrelated and so misses that one of them closes the bank. The state consequence differs and the command does not. Correct model: verified — RDA is a READ with address bit A10 high. Same encoding, same operation, one operand different. Its effect is that the device precharges the bank itself afterwards, with no command on the bus saying so. Prevention: ask which bits differ between the two. If the answer is an address bit, it is one command with a flag.
"A10 is the auto-precharge bit." Wrong model: the bit has a fixed meaning. Why it is tempting: it genuinely is the auto-precharge bit — on reads and writes, which are the commands people think about most. Consequence: a decoder that reads a precharge's scope selector as an auto-precharge request, and vice versa. All-bank precharges appear as single-bank ones; reads appear to request auto-precharge whenever A10 happens to be high. Neither produces an error; both produce state-model divergence. Correct model: verified — A10 is an auto-precharge flag with a READ or WRITE, and a scope selector with a PRECHARGE. The meaning is a property of the pair, not of the bit. Prevention: extract operands after decoding the operation, never in parallel. Field extraction is downstream of opcode decode in any protocol where field meanings depend on the opcode.
"If it decodes, it will work." Wrong model: successful decode means the command will do what was intended. Why it is tempting: decode is the visible, checkable step, and a decoder returning a clean result feels conclusive. Consequence: the four questions collapsed to one. A READ to a closed bank decodes perfectly and is illegal; a READ to an open bank holding the wrong row decodes perfectly, is legal, and returns the wrong data. Decode establishes neither. Correct model: decode answers "what operation was requested". Chapter 7.1 §1's questions three and four — state legality and timing legality — are separate, with separate owners. Prevention: after every decode, ask what must already be true. For a read the answer is "a row must be open, and it must be the right one" — and only the second is invisible to the device.
10. Interview Reasoning
"Does a READ command open the row it accesses?" No — and it does not name a row at all. A column command carries a bank and a column and no row address, so it reads from whatever row that bank is currently holding in its sense amplifiers. The row must have been opened by a prior activate. The important consequence is that the device cannot detect a disagreement between the row the controller intended and the row actually open: the command gives it nothing to compare against, so it serves the open row's data correctly and no error is reported anywhere. That is why the controller's per-bank open-row model is a correctness structure rather than a performance optimisation.
"Is RDA a separate command?" No. It is a READ with address bit A10 sampled high — same encoding, same operation, one operand different. The effect is that the device precharges the bank itself after the access, so the controller saves a command-bus event. The consequence that matters is that the bank closes with no command on the bus announcing it, so a monitor or controller tracking state from the command stream alone will believe the bank is still open unless it interprets that operand. That is the main reason auto-precharge is worth understanding at the command level rather than as a performance feature.
"Why must a command decoder identify the operation before extracting operands?" Because operand meanings depend on the operation. The verified case is DDR4's A10: with a read or write it selects auto-precharge, and with a precharge it selects scope — all banks or one. Same wire, same sampling event, two unrelated meanings, distinguished only by the command encoding present at that event. A decoder that extracts A10 as a fixed field will misread it on roughly half the commands it sees, and the failure has no error signature: the commands are well-formed, the flags are wrong, and the state model drifts. The general rule is that field extraction is downstream of opcode decode in any protocol where field meanings depend on the opcode.
"What would a command monitor need in order to report a read's actual address?" Its own per-bank open-row model. The read carries only a bank and a column, so a monitor that decodes the command alone can report "column C of bank B's current row" — which is not an address. To produce a real address it must track every activate and every precharge, including the implicit precharges caused by auto-precharge operands, and look up the open row at the moment of the read. That look-up is what distinguishes a command monitor from a bus trace dumper, and it is also why the monitor's model can diverge from the device's in exactly the same way a controller's can.
"A read returned data from the wrong row. Where do you look?" First at whether the wrong device responded or the right device returned the wrong row, because those are disjoint investigations. If it is the right device, the productive move is to replay the command stream against a reference bank model and find the first point where the model and reality diverge — the device cannot help here, because a read carries no row address and therefore has nothing to detect. Within that replay, the specific thing to check early is whether an earlier read or write to that bank carried A10 high, because auto-precharge closes the bank with no command on the bus announcing it, and both controllers and monitors commonly miss it. If the divergence traces back to an activate, compare the intended row against the encoded row in binary, since a discrepancy confined to the top few bits points at the encoder's concatenation rather than at state.
11. Engineering Exercise
Educational encodings; verified operand behaviour; no timing values implied.
1. A controller issues READ to bank 2 with no prior ACT to bank 2. What does the device do? It serves column C of whatever row bank 2 currently holds — or, if bank 2 is closed, there is no row to read and the operation is illegal by state. In neither case does it open the requested row, and in the first case it returns well-formed wrong data with no error.
2. Two commands have identical encodings and differ only in addr[10]. Name both and state how their state consequences differ. READ and READ-with-auto-precharge. The first leaves the bank open; the second leaves it closed, because the device precharges it itself. One operand bit, opposite state outcomes — and no command on the bus announces the second.
3. A decoder extracts auto_precharge = addr[10] unconditionally. Describe its behaviour on an all-bank precharge. It reports DDR_CMD_PRE with auto-precharge set and all-bank clear — exactly inverted. The precharge would be treated as single-bank, so a consumer's model would close one bank when the device closed all of them. No error is produced; the divergence surfaces later as reads from banks the model believes are open.
4. Why does §4's decoder drive op_allbank low for a READ rather than leaving it unassigned? Because a stale or meaningless value can be acted on. A consumer reading op_allbank after a read would see whatever the last precharge left there. Driving per-operation defaults makes every operand output meaningful-or-zero, and §6's P1 asserts it so a later change cannot reintroduce the hazard.
5. A monitor reports every read as "bank 3, column 40" and never reports a row. What is missing, and is the monitor wrong? It is missing a per-bank open-row model. It is not wrong — it is reporting exactly what the command carried — but it is not useful, because "column 40 of bank 3's current row" is not an address. The monitor must reconstruct the row from the activate history, which is Chapter 7.4 §5's subject.
6. Using Chapter 7.1 §1's four questions, classify: READ decoded correctly to a bank that is open with the wrong row. Encoding: valid. Semantics: valid. State legality: valid — the bank is open, which is all the device requires. Timing legality: valid. All four pass, and the read is still wrong. That is the uncomfortable and important case: the four questions are necessary and not sufficient, because which row is open is a fact only the controller's model tracks.
12. Summary
READ says: return the data at column C of the row currently open in bank B. It carries no row address, so it opens nothing and the device cannot detect a disagreement between the intended row and the open one — Chapter 5.2 §4's silent mismatch, explained from the command side.
Its prerequisite is state and its consequence is none — the row stays open, and further columns can be read without another activate, which is Chapter 6.5 §1's asymmetry.
Decode is ordered, and the order is mandatory. Qualification, then operation, then operands interpreted for that operation, then — separately and elsewhere — legality. Verified: A10 is an auto-precharge flag with a READ or WRITE and a scope selector with a PRECHARGE. A decoder extracting it as a fixed field misreads it on roughly half the commands it sees, with no error signature — well-formed commands, wrong flags, drifting state model.
RDA is not a separate command. It is a READ with A10 high, and its effect is that the device precharges the bank itself. Same encoding, opposite state consequence, and no command on the bus says so — which is why it is a monitoring problem as much as a performance feature.
The general decoder rule: in any protocol where field meanings depend on an opcode, field extraction is downstream of opcode decode, never parallel to it.
And for DV, a read's command alone is not an address. A monitor must carry a per-bank open-row model and look the row up — including tracking the implicit precharges auto-precharge causes — or every read transaction it reports is missing its row.
13. What Comes Next
Chapter 7.3 takes the mirror command, and it separates three events this chapter treated as one.
A write's data does not accompany its command — it arrives afterwards. That makes observed, accepted and completed visibly distinct: a monitor sees the command, a protocol checker evaluates whether it was acceptable, and a scoreboard cares whether the data eventually landed. Those are three different events with three different consumers, and write is where the separation is impossible to ignore.
Return to Activate for the command model and the encoder this chapter inverts, Banks for the row state a read depends on, CAS# for why the command-to-data interval is a pipeline depth, or DQ and DQS for how the returning data is owned and timed. The full path is on the DDR tutorials index.
Continue learning
Related tutorials
- Related topic
Row Misses
Nothing is ever missing in DRAM — every row is always in the array. A miss means the bank holds nothing, which needs exactly one command, and how it came to be closed is information most models discard.
- Related topic
The Read Command
Accepting a read returns nothing. It starts a timed return pipeline and creates an obligation the controller must carry — which is why a read transaction exists long before any data does.
- Related topic
Write Recovery (tWR)
The bus is free, the controller owes nothing, and the bank still cannot be closed. A precharge issued too early does not delay the write — it interferes with data still being driven into cells.
- 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.
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.
