Skip to content
VLSI Mentor

DDR · Module 7

Activate (ACT)

ACT opens a row, and it is the right place to establish what a DDR command actually is: a sampled encoding, qualified for a target, carrying operands, interpreted against device state — four separate questions that must not be collapsed.

Module 6 established what crosses a DDR interface: which wires exist, who drives each one, when it is sampled, and how the set changed across generations. It stopped deliberately short of what the values mean.

This module closes that gap, and its question is:

How do encodings on the command interface cause a DRAM device to perform operations?

That sounds like it should be answered by a table. It is not, and the single most important thing this chapter does is explain why — because a table answers one of four questions and people routinely assume it answers all four.

Activate is the right command to start with. It is the only command that opens a row, so every other command in this module depends on it having happened. And because it is the first, it carries the module's conceptual scaffolding.

1. What Activate Requests

Semantically, ACT says: open row R in bank B.

That is all. It names a bank, it names a row, and it asks for that row to be brought into the bank's sense amplifiers. It moves no data. It produces nothing on DQ. The requester does not yet know which columns it wants, and does not need to.

What it changes is state. Chapter 5.2 established that a bank holds one open row at a time and that this is the scope of row-state exclusivity. ACT is the command that sets it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   bank B CLOSED   + ACT(B, R)  ->  bank B OPEN with row R

And what it requires is that the bank be closed. A bank already holding an open row cannot activate another — Chapter 5.2 §5's illegal_activate. To change rows you must precharge first, which is Chapter 7.4.

2. A Command Is Not a Signal

Chapter 6.4 §7 already dismantled "RAS# means activate". The command model makes the correction precise.

A command requires four things simultaneously, and missing any one means no command happened:

A sampling event. Chapter 6.1 §2: a command is a value sampled at a defined instant, not a level held on a wire.

Target qualification. Chapter 6.3 §1: the command bus is a broadcast. Every rank sees every encoding, and CS# decides which one acts. An unqualified encoding is not a command — it is a deselect, and the CA lines carry no obligation.

An encoding. The pattern that says which operation.

Operands. The bank, the row, and — as §5 shows — flags whose meaning depends on which command carries them.

So "which signal means activate" is not a well-formed question. In DDR3 the answer involves a combination of dedicated pins. In DDR4, ACT_n asserted low is the activate indication, and at that same event the three pins named RAS_n/CAS_n/WE_n are carrying row address bits. In DDR5 the command/address interface is encoded differently again.

The semantics are stable and the encoding is not — which is exactly why a controller should not think in pins.

3. Semantic Commands, and Why the Separation Matters

Here is the module's most valuable architectural lesson, and it is a design principle rather than a fact about DDR.

A memory controller's scheduling logic should reason in operations, not in pin patterns.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   controller intent          "I need row 500 of bank 3"
         |
   scheduler                  reasons in ACT / RD / WR / PRE / REF / MRS
         |
   semantic command           DDR_CMD_ACT, bank=3, row=500
         |
   generation-specific encoder   maps the operation onto this generation's CA
         |
   PHY                        launches the CA lines with correct electrical timing
         |
   CK sampling event          the device samples
         |
   DRAM command decoder       recovers the operation
         |
   state transition           bank 3 now holds row 500
A controller's scheduler reasons in semantic operations and emits a semantic command naming an operation with its operands. A generation-specific encoder maps that operation onto the command and address encoding of the generation in use. The PHY launches those lines with correct electrical timing. The device samples them at a clock event, its decoder recovers the operation, and a state transition follows. Each layer has a distinct responsibility and the semantic representation is what insulates the scheduler from the generation.The command pipeline — four layers, four responsibilitiesSchedulerEncoderPHYDRAMDDR_CMD_ACT, bank,rowgeneration-specificCA patternCA lines,electrically timedsampled at CK, thendecodedbank now open(state, not a reply)
Figure 1 — intent becomes an operation, an operation becomes an encoding, and only then a waveform.

The dashed return is not a message. Chapter 4.1 §4 established that DDR has no per-command acknowledgement — the device does not reply. It represents state the controller must model, which is why Chapter 5.2 §4 called the per-bank table a correctness structure rather than an optimisation.

4. RTL — The Semantic Command and Its Encoder

Engineering problem

Represent a command as an operation with operands, and map it onto a generation-specific encoding at a single, replaceable boundary.

Classification

SYNTHESIZABLE RTL — an educational controller/encoder-boundary architecture.

What it represents: the semantic command type, and the encoder that maps operations onto a generation's command/address interface.

What it explicitly does not represent: a scheduler — there is no queue, no arbitration, no reordering, and Module 17 owns those. No address decomposition into fields. No timing of any kind. No PHY: the encoder produces logical values, and Chapter 6.1 §8 established that turning them into electrically correct waveforms is the PHY's job.

Interface contract

cmd_valid with cmd and its operands presents a semantic command. The outputs are the generation-specific interface values. encode_unsupported reports an operation this generation's encoder cannot express.

State

Registered outputs only. Encoding is a pure function of the semantic command — which is the point: no history, no context, nothing to get out of step.

Combinational behaviour

The operation-to-encoding mapping and the operand placement.

Sequential behaviour

Output registration at the launch event.

How to simulate

vlog ddr_cmd_encode.sv tb_ddr_cmd_encode.sv then vsim -c tb_ddr_cmd_encode -do "run -all"; VCS vcs -sverilog ddr_cmd_encode.sv tb_ddr_cmd_encode.sv && ./simv; Xcelium xrun -sv ddr_cmd_encode.sv tb_ddr_cmd_encode.sv. Every RTL block in Module 7 simulates the same way.

Expected output

The same semantic DDR_CMD_ACT produces different interface values at GEN = 3 and GEN = 4 — the encoder absorbing the generation difference while the input is unchanged.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// DDR SEMANTIC COMMAND TYPE AND ENCODER.
// Classification: SYNTHESIZABLE RTL -- an educational
// CONTROLLER/ENCODER-BOUNDARY architecture.
//
// THE ARCHITECTURAL LESSON: a controller's scheduling logic should reason
// in OPERATIONS, not in pin patterns. The operations are stable across
// generations; the encoding is not. Putting the boundary here means the
// scheduler is generation-portable and only this block changes.
//
// ############ THE COMMAND BIT VALUES BELOW ARE EDUCATIONAL ############
// They are PLACEHOLDERS chosen so the structure of encoding is visible.
// They are NOT JEDEC encodings and correspond to no generation's actual
// bit combinations. Read the device specification for real encodings.
//
// WHAT IS REAL AND MODELLED STRUCTURALLY (verified, Chapter 6.6):
//   DDR4 has a dedicated ACT_n. ACT_n LOW means "this is an activate",
//   and the three multi-function balls then carry row address bits A16,
//   A15, A14. ACT_n HIGH means those balls carry the legacy command bits.
//   DDR3 has no ACT_n; the activate is one of the pin encodings.
// ######################################################################
//
// WHAT THIS DOES NOT REPRESENT: a scheduler (no queue, no arbitration, no
// reordering -- Module 17), address decomposition into fields (Module 8),
// any timing whatsoever (Modules 13/14), and the PHY -- this block emits
// LOGICAL values and Chapter 6.1 established that making them electrically
// correct is the PHY's job. DDR5's CA encoding is not modelled (Module 25).
// ─────────────────────────────────────────────────────────────────────────

// ── The semantic command set. NOT a JEDEC-defined type: this is an
//    educational RTL architecture. The set here covers the operations
//    Module 7's canonical chapters own.
typedef enum logic [2:0] {
  DDR_CMD_NOP = 3'd0,   // occupy the bus, request nothing (Section 6)
  DDR_CMD_ACT = 3'd1,   // open a row                      (this chapter)
  DDR_CMD_RD  = 3'd2,   // column read                     (Chapter 7.2)
  DDR_CMD_WR  = 3'd3,   // column write                    (Chapter 7.3)
  DDR_CMD_PRE = 3'd4,   // close a bank                    (Chapter 7.4)
  DDR_CMD_REF = 3'd5,   // refresh                         (Chapter 7.5)
  DDR_CMD_MRS = 3'd6    // mode register set               (Chapter 7.6)
} ddr_cmd_e;

module ddr_cmd_encode #(
  // 3 = DDR3-style dedicated command pins, no ACT_n.
  // 4 = DDR4-style with a dedicated ACT_n selecting the pin interpretation.
  parameter int GEN    = 4,
  parameter int ROW_W  = 17,
  parameter int BANK_W = 4
) (
  input  logic              clk,
  input  logic              rst_n,

  // ── Semantic input. This is what a scheduler emits.
  input  logic              cmd_valid,
  input  ddr_cmd_e          cmd,
  input  logic [BANK_W-1:0] cmd_bank,
  input  logic [ROW_W-1:0]  cmd_row,

  // ── Generation-specific interface output.
  output logic              cs_n,
  // Present only in the DDR4-style encoding. Held deasserted at GEN 3,
  // where no such signal exists.
  output logic              act_n,
  // The three multi-function balls of Chapter 6.6. Their meaning depends
  // on act_n, which is the whole point of that chapter.
  output logic              pin_ras_a16,
  output logic              pin_cas_a15,
  output logic              pin_we_a14,
  output logic [ROW_W-4:0]  addr_low,
  output logic [BANK_W-1:0] bank_out,

  // An operation this generation's encoder cannot express. Reported, never
  // silently substituted -- emitting a different command than the
  // scheduler asked for is the worst available failure.
  output logic              encode_unsupported
);

  // ── COMPILE-TIME legality.
  if ((GEN != 3) && (GEN != 4)) begin : g_gen
    initial $fatal(1, "ddr_cmd_encode: GEN must be 3 or 4 (DDR5 is Module 25)");
  end
  // Three bits are multiplexed with address in the GEN 4 encoding, so the
  // row address needs room for them plus at least one always-address bit.
  if (ROW_W < 4) begin : g_row
    initial $fatal(1, "ddr_cmd_encode: ROW_W must be >= 4");
  end
  if (BANK_W < 1) begin : g_bank
    initial $fatal(1, "ddr_cmd_encode: BANK_W must be >= 1");
  end

  // ── EDUCATIONAL command patterns for the three legacy-style bits.
  //    Placeholders. Not JEDEC. See the header.
  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;

  logic [2:0] enc_bits;
  logic       unsupported_now;
  logic       is_activate;

  always_comb begin
    // Default to the no-operation encoding. A default that decodes to NOP
    // rather than to X or to an arbitrary command means an unhandled case
    // requests nothing, which is the safe direction.
    enc_bits        = ENC_NOP;
    unsupported_now = 1'b0;
    is_activate     = 1'b0;

    unique case (cmd)
      DDR_CMD_NOP: enc_bits = ENC_NOP;
      DDR_CMD_ACT: begin
        enc_bits    = ENC_ACT;
        is_activate = 1'b1;
      end
      DDR_CMD_RD:  enc_bits = ENC_RD;
      DDR_CMD_WR:  enc_bits = ENC_WR;
      DDR_CMD_PRE: enc_bits = ENC_PRE;
      DDR_CMD_REF: enc_bits = ENC_REF;
      DDR_CMD_MRS: enc_bits = ENC_MRS;
      default: begin
        // An operation outside the enum. Report it and encode nothing.
        unsupported_now = 1'b1;
        enc_bits        = ENC_NOP;
      end
    endcase
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      // Reset to a fully deselected, non-committal interface. Chapter 6.3:
      // deselect is a legal and meaningful state, and it is the right
      // reset value because it requests nothing of any device.
      cs_n               <= 1'b1;
      act_n              <= 1'b1;
      pin_ras_a16        <= 1'b1;
      pin_cas_a15        <= 1'b1;
      pin_we_a14         <= 1'b1;
      addr_low           <= '0;
      bank_out           <= '0;
      encode_unsupported <= 1'b0;
    end else begin
      encode_unsupported <= 1'b0;

      if (!cmd_valid) begin
        // No command: deselect. Chapter 6.3 Section 3 established this is
        // how a controller occupies the bus without requesting anything.
        cs_n  <= 1'b1;
        act_n <= 1'b1;
      end else begin
        cs_n               <= 1'b0;
        encode_unsupported <= unsupported_now;
        bank_out           <= cmd_bank;

        if (GEN == 4) begin
          // ── DDR4-style. VERIFIED STRUCTURE (Chapter 6.6): ACT_n low
          //    means activate, and the three balls then carry the TOP
          //    three row-address bits. ACT_n high means they carry the
          //    legacy command bits.
          act_n <= ~is_activate;
          if (is_activate) begin
            {pin_ras_a16, pin_cas_a15, pin_we_a14} <= cmd_row[ROW_W-1:ROW_W-3];
            addr_low                               <= cmd_row[ROW_W-4:0];
          end else begin
            {pin_ras_a16, pin_cas_a15, pin_we_a14} <= enc_bits;
            addr_low                               <= '0;
          end
        end else begin
          // ── DDR3-style. No ACT_n exists; the activate is one of the
          //    encodings, and the row address travels only on the
          //    dedicated address lines. Held deasserted so a GEN 3
          //    instance never drives a signal its generation lacks.
          act_n                                  <= 1'b1;
          {pin_ras_a16, pin_cas_a15, pin_we_a14} <= enc_bits;
          addr_low                               <= cmd_row[ROW_W-4:0];
        end
      end
    end
  end

endmodule

Cycle-by-cycle example

ROW_W = 17, semantic input DDR_CMD_ACT, bank=3, row=0x1A5C5:

GENcs_nact_nthree ballsaddr_low
400row bits A16..A14remaining row bits
301 (absent)ENC_ACTremaining row bits

The semantic input is byte-identical in both rows. The scheduler that produced it does not know which generation it is driving. That is the payoff — and it is why GEN is a parameter of this block and of nothing upstream.

And notice what GEN 4 does with the row address. Three of its bits travel on balls named after command signals, because ACT_n has claimed the activate indication and freed them. Chapter 6.6 §3 derived why; here it is the encoder's job to place them.

Waveform expectation

§7. Watch cs_n fall as the command is launched and the three balls carry address rather than an encoding when act_n is low.

Synthesis implication

A small combinational decode plus output registers — tens of flops. Negligible, and that is the point: the layer that makes a controller generation-portable costs almost nothing. In a real controller this sits immediately before the PHY interface, and the GEN parameter would typically be a build-time configuration rather than a runtime one.

Corner cases

GEN outside {3, 4} does not elaborate — DDR5 is Module 25's and modelling it here would be a fiction. ROW_W == 4 gives a one-bit addr_low, the minimum legal configuration and the one where the concatenation widths are easiest to get wrong. A command outside the enum reports encode_unsupported and encodes NOP, never a substituted command. cmd_valid low produces deselect, which is also the reset state.

Debugging clues

If a GEN 4 activate produces a command encoding on the three balls instead of address bits, is_activate is not feeding act_n — and the device will decode whatever those row bits happen to look like. If the row address is short by three bits or has them misplaced, check the concatenation: the multiplexed bits are the most significant three, and putting them at the bottom produces plausible addresses for wrong rows, silently. If a GEN 3 instance drives act_n, the generation guard has been dropped.

Limitations

No scheduler, no queue, no arbitration. No timing. No address decomposition. No PHY. No DDR5. And the command bit values are educational placeholders, as the header states at length — the structure is verified and the values are not real.

5. Operands Mean Different Things in Different Commands

This is the observation that unifies the next three chapters, and it is worth meeting here.

An operand's meaning depends on which command carries it. The same physical address bit is interpreted differently depending on the operation it accompanies.

The clearest verified case, which Chapter 7.2 and Chapter 7.4 both build on: address bit A10 in DDR4.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   A10 sampled with a READ or WRITE   ->  auto-precharge flag
                                          HIGH = precharge after the access

   A10 sampled with a PRECHARGE       ->  scope selector
                                          HIGH = all banks, LOW = one bank

Same wire, same sampling event, two unrelated meanings — and nothing distinguishes them except the command encoding present at the same event.

Chapter 7.6 has another: the bank and bank-group bits, which name a bank during ACT, RD and WR, select a mode register number during MRS.

6. NOP and Deselect Are Not the Same Thing

No canonical chapter in this module owns no-operation, so it belongs here — and the distinction is real.

Deselect is an event where CS# is not asserted. Chapter 6.3 §2 established that this is legal, common, and typically the most frequent state on the bus. The device is not addressed, so the CA lines carry no obligation and no command exists.

A no-operation command is an event where the device is addressed and the encoding requests nothing. The command bus is qualified, the encoding is decoded, and the resulting operation is "do nothing".

Both result in no state change, and they are different events.

Why the difference matters practically, in three ways.

A monitor must distinguish them. A deselect is not a command and should not appear in a command trace; a decoded no-operation is a command and should. A monitor that reports every event as a command produces a trace dominated by deselects, and a monitor that reports neither loses real commands.

They have different obligations on the CA lines. Chapter 6.1 §4 established that stability is owed only at qualified events. On a deselect the CA lines may carry anything; on a qualified no-operation they must be stable and must decode to the no-operation encoding.

And the generations treat them differently. Whether a dedicated no-operation encoding exists, and whether it is recommended over deselect, is generation- and device-specific. This module's DDR_CMD_NOP is the semantic "request nothing", and §4's encoder maps cmd_valid low to deselect and DDR_CMD_NOP to a qualified encoding — which makes the distinction structural rather than a matter of convention.

7. From Intent to State, in Cycles

ddr_cmd_encode — an activate travelling through the pipeline

10 cycles
Ten cycles. A semantic activate command with its bank and row operands is presented to the encoder. The encoder asserts chip select and, because this is a DDR4-style configuration, asserts the activate signal low so the three multi-function balls carry row address bits rather than a command encoding. The device samples at the clock event, decodes an activate, and the addressed bank transitions from closed to open holding that row. A later no-operation command is qualified but requests nothing, and the surrounding deselect events are not commands at all.encode, sample, decodeencode, sample,decodebank 3 openbank 3 openencoded and launchedencoded and launcheddecoded as ACTdecoded as ACTNOP: qualified, no stateNOP: qualified, no stateCKcmd (sem)--ACT----NOP----ACT----cmd_validcs_nact_n3 balls----ROW--NOP------ROW--decoded------ACT----NOP----ACTbank3 statet0t1t2t3t4t5t6t7t8t9
Figure 2 — a semantic command becomes an encoding, is sampled, decodes, and changes state.

Follow one command down the trace. The semantic ACT appears at cycle 1. The encoder drives the interface at cycle 2 — cs_n low, act_n low, and the three balls carrying ROW rather than a command encoding. The decode reports at cycle 3. The bank state changes at cycle 4.

Four distinct events for one command, and they are in four different layers. An engineer debugging "the wrong row opened" needs to know which of the four went wrong, and §9 is built on exactly that.

Cycle 6's NOP is the §6 distinction. cmd_valid was high at cycle 4, so the event was qualifiedcs_n low — and the encoding requested nothing. Contrast cycles 2, 5 and 8, where cs_n is low because a command was launched, and cycles 0, 1, 3 and 9 where nothing was qualified at all.

These are representative educational cycles. The one-cycle encode and one-cycle decode latencies are properties of this model, and the interval between a command and its state change is not a timing requirement — Modules 13 and 14 own those.

8. Three Assertions Worth Writing

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// VERIFICATION-ONLY, inside ddr_cmd_encode.

// P1 -- an unsupported operation encodes NOTHING. Substituting a different
// command would send the device an operation the scheduler never asked
// for, which is the worst available failure: the controller's state model
// and the device's state diverge with no error anywhere.
property p_unsupported_encodes_nop;
  @(posedge clk) disable iff (!rst_n)
    encode_unsupported |-> ({pin_ras_a16, pin_cas_a15, pin_we_a14} == ENC_NOP);
endproperty
assert property (p_unsupported_encodes_nop);

// P2 -- THE GENERATION PROPERTY. In the DDR4-style encoding, act_n is
// asserted exactly for an activate, and the three balls then carry row
// address rather than a command encoding. This is the verified structural
// fact of Chapter 6.6, asserted here so the encoder cannot drift from it.
property p_act_n_only_for_activate;
  @(posedge clk) disable iff (!rst_n)
    ((GEN == 4) && !cs_n && !act_n) |-> ($past(cmd) == DDR_CMD_ACT);
endproperty
assert property (p_act_n_only_for_activate);

property p_act_n_carries_address;
  @(posedge clk) disable iff (!rst_n)
    ((GEN == 4) && !cs_n && !act_n)
      |-> ({pin_ras_a16, pin_cas_a15, pin_we_a14}
           == $past(cmd_row[ROW_W-1:ROW_W-3]));
endproperty
assert property (p_act_n_carries_address);

// P3 -- a generation never drives a signal it does not have. At GEN 3
// there is no ACT_n, and an encoder that drove it would be describing
// hardware that does not exist.
property p_gen3_no_act_n;
  @(posedge clk) disable iff (!rst_n)
    (GEN == 3) |-> act_n;
endproperty
assert property (p_gen3_no_act_n);

// P4 -- no command without qualification. Chapter 6.3: an unqualified
// event is not a command, so a valid semantic command must produce an
// asserted chip select and no command must appear without one.
property p_qualified_iff_commanded;
  @(posedge clk) disable iff (!rst_n)
    $past(cmd_valid) |-> !cs_n;
endproperty
assert property (p_qualified_iff_commanded);

P2 is the property that keeps the encoder honest about the generation it claims to implement. It is the only assertion here tied to a verified external fact rather than to internal consistency — and that makes it the one worth re-checking whenever the specification reference changes.

P1 encodes a safety direction. There are two ways to handle an operation the encoder cannot express: emit nothing, or emit something. They are not equally bad. Emitting nothing leaves the device's state matching the controller's model; emitting a substitute diverges them silently. The property fixes the choice so a later change cannot invert it.

What none of them prove. Nothing about whether the CA lines are electrically validChapter 6.1 §6 established that setup, hold, jitter and margin are analog and unreachable by any digital assertion. Nothing about state legality: this encoder will happily encode an ACT to a bank that is already open, because encoding legality and state legality are different questions and §1's four-question model exists to keep them apart. And nothing about timing legality at all.

9. Debugging — The Wrong Row Opened

Symptom. A controller intended to activate row R in bank B. A different row is open, or a different bank. No errors reported anywhere.

§3's pipeline is the diagnostic structure, and this is its main payoff: the wrong operation reached the device, and there are four layers it could have gone wrong in. The productive first move is not to look at the pins but to find the earliest layer where intent and reality disagree.

Mechanism 1 — the scheduler's intent was already wrong. Inspect: the semantic command the scheduler emitted, upstream of the encoder. Expected evidence: DDR_CMD_ACT carrying the wrong row or bank operand. Discriminator: compare intent against the request that produced it. This is first because it costs nothing and because it eliminates the entire interface if true — an address-mapping error produces exactly this symptom and lives in Module 18.

Mechanism 2 — the encoder placed the operands wrongly. Inspect: the interface values against the semantic command. Expected evidence: the semantic command correct and the encoded row address differing — classically by a permutation of the top three bits, because Chapter 6.6's multiplexed balls carry them. Discriminator: compare the intended row number against the encoded one in binary. Chapter 6.6 §9 established this: a discrepancy confined to particular bit positions names a concatenation fault, while a scattered one names something upstream.

Mechanism 3 — the encoding was correct and the device decoded it differently. Inspect: whether ACT_n's interpretation matches on both sides. Expected evidence: a DDR4 device treating the three balls as a command encoding when the controller sent address, or the reverse. Discriminator: do phantom commands correlate with activates? Chapter 6.4 §9's first mechanism — and it points at a generation mismatch between the encoder and the device, not at a bug in either.

Mechanism 4 — the command was fine and the state was not what the controller believed. Inspect: whether the bank was already open when the ACT was issued. Expected evidence: the activate refused, leaving the previous row open — so the "wrong" row is a legitimately stale one. Discriminator: was the bank closed? This is a state-legality failure rather than an encoding one, and Chapter 5.2 §5's illegal_activate is the check that catches it. The symptom is identical and the layer is completely different.

Mechanism 5 — not the command path: the CA lines were not stable. Inspect: whether errors scale with rate or vary with temperature. Expected evidence: intermittent wrong rows rather than consistent ones. Discriminator: is it consistent or intermittent? A consistent wrong row is a logic fault — mechanisms 1 to 4. An intermittent one is Chapter 6.1 §10's margin territory, and no amount of reviewing encoder logic will find it.

Discrimination, cheapest first. Ask whether the fault is consistent or intermittent — one question, splitting mechanism 5 off entirely and deciding whether this is a logic investigation or a margin one. Then compare the scheduler's semantic intent against the request. Then compare the intended row against the encoded row in binary. Then check whether the bank was open.

The reasoning lesson. The semantic layer exists so this question has somewhere to be asked. Without it, "the wrong row opened" is one undifferentiated fault spanning four layers; with it, the scheduler's output is a small comparable value that either matches intent or does not — and that single comparison cuts the search in half before any waveform is examined. A layer that makes a bug locatable earns its place even when it costs logic, and this one costs almost none.

10. Common Misconceptions

"RAS# means activate." Wrong model: one control signal identifies the operation. Why it is tempting: it was true for SDR through DDR3, the name says "row", and most introductory material stops there. Consequence: a wrong reading of any DDR4 command interface. Chapter 6.6 §3 verified that DDR4's activate is signalled by ACT_n, and at that same event the ball named RAS_n is carrying row-address bit A16. A decoder built on this model reports a phantom command on every activate. Correct model: a command is a sampled encoding plus qualification plus operands, and which signals carry the encoding is generation-specific. The semantics — open a row — are stable; the encoding is not. Prevention: ask what identifies the operation in this generation. If you cannot name the selector, you cannot decode the interface.

"If the bit pattern decodes, the command is legal." Wrong model: successful decode implies executability. Why it is tempting: in most digital interfaces a well-formed request is a valid one, and decode is the visible step. Consequence: no state checking in the controller, and the four-question model collapsed to one. A perfectly decoded READ to a bank with no open row is a legal encoding and an illegal operation — and the device's response is not a helpful error but undefined behaviour or data from whatever row happens to be open, which Chapter 5.2 §4 showed returns plausible wrong data silently. Correct model: encoding legality, state legality and timing legality are three separate questions with three different owners. Decode answers only the first. Prevention: for any command, ask what must already be true. If the answer is "a row must be open", decode has not established it.

"The controller should store raw DDR pin combinations internally." Wrong model: the controller's natural representation is the wire format. Why it is tempting: it is what goes out, so carrying it internally seems to avoid a translation. Consequence: scheduling logic that must be rewritten for each generation despite the scheduling decisions being identical, a checker that needs the encoder's logic before it can compare anything, and — most damaging — no layer at which to ask whether the intent or the encoding was wrong. §9's investigation has nowhere to start. Correct model: the scheduler reasons in semantic operations; a single replaceable encoder maps them to the generation's representation. Operations are architecture; encodings are a generation detail. Prevention: ask whether a change of DDR generation would touch your scheduling logic. If it would, the boundary is in the wrong place.

"NOP and deselect are the same thing." Wrong model: both mean nothing happens, so they are interchangeable. Why it is tempting: the observable outcome — no state change — is identical. Consequence: a monitor that cannot produce a useful command trace, reporting either every bus event as a command or none. And a misunderstanding of the CA lines' obligations: Chapter 6.1 §4 established that stability is owed only at qualified events, so a deselect imposes none and a qualified no-operation does. Correct model: deselect is not a command — the device is not addressed. A no-operation is a command — the device is addressed and the encoding requests nothing. Prevention: look at chip select. If it is deasserted, nothing was commanded.

"A correct functional simulation proves the CA timing is valid." Wrong model: if the right commands arrive in simulation, the interface works. Why it is tempting: the commands genuinely do arrive correctly, and that is real evidence about the logic. Consequence: shipping an interface whose command lines do not meet their setup requirement, producing the hardest fault class — Chapter 6.1 §10's intermittent misinterpretation with no functional failure. Simulation has no representation of setup, hold, jitter or margin, so it cannot distinguish an adequately timed command from a marginal one. Correct model: functional simulation verifies encoding, semantics and state legality. CA timing validity is established by static timing analysis, PHY characterisation and measurement — and Chapter 6.1 §6 explains why no digital assertion reaches it. Prevention: keep an explicit list of properties simulation cannot validate. Command-line timing belongs on it.

11. Interview Reasoning

"What actually makes a DDR command a command?" Four things simultaneously. A sampling event, because a command is a value sampled at a defined instant rather than a level held on a wire. Target qualification, because the command bus is a broadcast that every rank receives — chip select is what decides which device acts, so an unqualified encoding is not a command at all. An encoding that identifies the operation. And operands, which for an activate are the bank and the row. Missing any one of those and no command happened, which is why "which signal means activate" is not a well-formed question.

"Why separate a semantic command from its pin encoding in a controller?" Because the operations are stable across generations and the encodings are not. A scheduler's decisions — which bank to open, when to precharge, how to interleave — are identical for DDR3, DDR4 and DDR5, so putting the boundary before the encoding means only the encoder changes. It also makes the scheduler testable, since a semantic command is a small enumerated value that can be compared against a reference model directly, rather than a pin pattern the checker must decode using logic it might share bugs with. And most practically, it gives you a place to stand when the wrong operation reaches the device: you can ask whether the intent was wrong or the encoding was wrong, and those are different bugs in different layers.

"Why can a valid command encoding still be an illegal command?" Because decoding and legality are different questions. Decode tells you what operation the bits request; it says nothing about whether that operation is permitted in the device's current state. A READ that decodes perfectly is illegal if the target bank has no open row, because a column access reads from whatever row is currently held in the sense amplifiers and there is nothing there. There is also a fourth question beyond that — whether the operation is allowed now, given how recently the previous command was issued — and that is timing legality, which belongs to the timing modules. Four questions, four different causes, four different owners.

"What does ACT require and what does it change?" It requires that the target bank be closed, and it changes that bank's state to open holding the named row. It moves no data and produces nothing on the data bus — the requester has not yet said which columns it wants and does not need to. The prerequisite is the important half: a bank already holding an open row cannot activate another, so changing rows means precharging first. That is why the activate is the command every other command in the module depends on having happened.

"A controller intended to open row R and a different row is open. How do you narrow it down?" First by asking whether the fault is consistent or intermittent, because that decides whether this is a logic investigation or a margin one — a consistently wrong row is logic, an intermittent one is command-line timing and no amount of reviewing encoder code will find it. If it is consistent, compare the scheduler's semantic output against the request that produced it, because an address-mapping error produces this symptom and eliminates the interface entirely if true. Then compare the intended row number against the encoded one in binary rather than decimal, because a discrepancy confined to the top three bits points at the multiplexed command balls being concatenated in the wrong positions. And it is worth checking whether the bank was already open when the activate was issued, because then the activate was refused and the "wrong" row is a legitimately stale one — a state-legality failure with an identical symptom and a completely different cause.

12. Engineering Exercise

Educational encodings and cycle counts throughout; no timing parameters are implied.

1. A decoder reports a well-formed READ. Name two further questions before the device can execute it. State legality — does the target bank have an open row? And timing legality — has enough separation elapsed since the previous command? Decode answered neither, and the two have different owners: this module and Modules 13/14 respectively.

2. §4's encoder is given DDR_CMD_ACT at GEN = 4 and at GEN = 3. What differs at the interface, and what differs upstream? At the interface: GEN 4 asserts act_n low and places row bits on the three multi-function balls; GEN 3 places an encoding there and drives no act_n. Upstream, nothing differs at all — the semantic command is identical. That is the entire value of the boundary.

3. A DDR4 device decodes a command on every activate the controller issues. Which layer, and what is the fingerprint? The decoder is reading the three balls as a command encoding while act_n is low and they carry address. The fingerprint is that the phantom rate equals the activate rate exactlyChapter 6.4 §9's first mechanism. It is a generation-interpretation mismatch, not a bug in either side's logic.

4. Why does §4's encoder report encode_unsupported rather than substituting a similar command? Because substituting sends the device an operation the scheduler never requested, so the controller's state model and the device's state diverge with no error anywhere — and Chapter 5.2 §4 showed that divergence surfaces later as plausible wrong data. Encoding nothing keeps them consistent, which is the safe direction and is why §8's P1 fixes the choice.

5. Classify: a controller issues ACT to bank 3, then ACT to bank 3 again with a different row, with no intervening command. What fails, and which of the four questions? The second activate. Encoding is fine, semantics are fine, and state legality fails — bank 3 already holds an open row, so Chapter 5.2's illegal_activate applies. A precharge must come between them. Note that this is not a timing failure; it would be illegal after any interval.

6. A scheduler is being ported from DDR3 to DDR4. Using §3's pipeline, name what must change and what must not. The encoder must changeact_n, the multiplexed ball placement, the encoding values. The scheduler must not change at all: which bank to open, when to precharge, how to order accesses are the same decisions. If the port touches scheduling logic, the semantic boundary was in the wrong place — which is §10's third misconception, and the test for it.

13. Summary

A command is not a signal. It is a sampled encoding, qualified for a target, carrying operands, interpreted against device state — and those are four requirements that must all hold.

The module's organising idea is that four different questions get conflated. Encoding — what bits were sampled, generation-specific. Semantics — what operation they request, generation-independent. State legality — whether that operation is allowed given current state, which this module owns. Timing legality — whether it is allowed now, which Modules 13 and 14 own. A command can pass the first two and fail the third; it can pass three and fail the fourth.

ACT requests: open row R in bank B. It moves no data. It requires the bank closed and changes it to open holding that row — and every other command in this module depends on it having happened.

A controller should reason in operations, not pin patterns. The scheduler emits semantic commands; a single replaceable encoder maps them to the generation's representation. That buys generation portability, testability, and — most practically — a layer at which to ask whether a fault was intent or encoding. §9's investigation has nowhere to start without it.

Operands mean different things in different commands. Verified: DDR4's A10 is an auto-precharge flag with a read or write, and a scope selector with a precharge. Bank bits name a bank with ACT and select a mode register with MRS. So decode is ordered — identify the operation, then interpret its operands — and a decoder that extracts fields in parallel will misread half of them.

And NOP is not deselect. A deselect is not a command: the device is not addressed and the CA lines carry no obligation. A no-operation is a command: the device is addressed and the encoding requests nothing.

14. What Comes Next

Chapter 7.2 takes the first command that depends on this one.

READ names a column in a row that is already open — it does not open anything, which is the misconception the chapter has to dismantle. And it introduces the auto-precharge variant: RDA is not a different command but a READ carrying A10 high, which schedules a precharge the controller never explicitly issues.

That makes 7.2 the natural home for the decoder — the inverse of §4's encoder — because extracting an operand whose meaning depends on the command is exactly what a decoder has to get right.

Return to CK / CK# for the sampling event a command is defined by, CS# for the qualification that makes an encoding a command, WE# for DDR4's ACT_n and the multi-function balls, or Banks for the row state ACT changes. The full path is on the DDR tutorials index.

Continue learning

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.