Skip to content
VLSI Mentor

DDR · Module 6

RESET# — Asynchronous Reset

RESET# must work when the device's state is unknown and no clock can be trusted, which is why it cannot be a command. Its assertion is asynchronous and its release must not be — and that asymmetry is not optional.

This module has now watched three functions lose their dedicated pins — CKE, ODT, and the RAS#/CAS#/WE# trio — each absorbed into command encoding because encoding is cheaper than pins.

RESET# cannot go the same way, and the reason is structural rather than economic.

A command is only meaningful if the command path is working. It requires a clock to be sampled against, a device in a state where it samples commands, and a device whose configuration is known well enough to interpret them. Reset is the signal you need when none of those can be assumed.

So the chapter's question is:

What must be true before any other signal means anything — and how do you build a signal that works when nothing else does?

The answer contains one of the most important disciplines in synchronous design, and it is an asymmetry: assertion must be asynchronous, and release must not be.

1. Why This One Cannot Be a Command

Work through what a command requires, and reset fails every prerequisite.

A command needs a clock. Chapter 6.1 established that a command is a value sampled at a clock event. Reset may be needed when the clock is absent, unstable, or has just started — during power-up, after a supply excursion, or when a PHY is being re-initialised.

A command needs the device to be sampling. Chapter 6.2 established that a device with its clock enable deasserted does not see commands at all. Reset may be needed precisely when the device is in an unknown power state, and a signal that only works in some states cannot be the mechanism for recovering from all of them.

A command needs its encoding to be interpretable. The device's configuration determines how it reads the command bus. Reset may be needed when that configuration is corrupt or unknown — and a command whose interpretation depends on state you are trying to discard is useless.

2. The Asymmetry

Here is the discipline, and it is asymmetric for two independent reasons.

Assertion is asynchronous because it must be. Pulling RESET# low must take effect without requiring a clock edge. If assertion needed a clock, then a device with a stopped or unstable clock could not be reset — which defeats the purpose. The whole value of reset is that it works when the synchronous machinery does not.

Release must be synchronous because it must be. Deasserting RESET# returns the device to clocked operation, and the moment of return must be aligned to the clock. An asynchronous release means the reset signal deasserts at an arbitrary point relative to the clock edge — which can violate the timing requirements of the registers coming out of reset and leave them metastable: settling to an unpredictable value, at an unpredictable time, differently in different parts of the design.

Assertion of reset must work when the clock is stopped or unstable, so it is asynchronous and takes effect immediately, bringing the device from any state into a known one. Release of reset returns the device to clocked operation, so it must be aligned to the clock through synchronising registers, because an arbitrarily timed release can leave registers metastable and different parts of the design leaving reset on different cycles.Assertionclock may be absentAsynchronoustakes effect at onceAny state to knownthe whole pointReleaseclock is runningSynchronisedthrough registersOne known cycleno metastabilitysosoasymmetric12
Figure 1 — assertion cannot wait for a clock; release cannot ignore one.

The failure mode of getting release wrong is worth being concrete about, because it is subtle and destructive.

Different registers leave reset on different cycles. A metastable release resolves independently in different parts of the design, so some logic begins operating a cycle before other logic. A state machine can therefore start from a state that is not its reset state — one where some of its registers have advanced and others have not, which may be a combination the design never intended to be reachable.

And it is intermittent and unreproducible. Metastability resolution is probabilistic. The same design, the same stimulus, the same board will work thousands of times and fail once. That is the signature, and it is why the discipline is applied universally rather than where it seems necessary.

3. Release Is Not Readiness

Deasserting RESET# does not make the device usable, and this is the same distinction Chapter 6.2 §4 drew for CKE's exit interval — appearing again because it is a general pattern.

After reset is released, an initialisation sequence must complete. Its steps are per-generation and per-device, and Modules 19 to 21 own them. Structurally they cover things this curriculum has already established the need for:

Configuration must be written. Mode registers determine how the device interprets commands, what its termination values are, what burst length applies — Chapter 6.11 shows a case where a mode register decides which of two functions a pin performs.

Calibration must run. Chapter 4.4 §1 established that on-die impedance cannot be manufactured accurately and must be calibrated against an external reference. Until it has been, termination is not at its intended value.

And training must run. Chapter 4.4 §3 established that from DDR3 onward interface timing is measured, not designed — write leveling and read leveling per rank, per direction. Before training, the controller does not know when to launch or capture data.

So there are three distinct states, not two: in reset, out of reset but not initialised, and operational. A controller that models only two will issue commands into the middle state, and §4's RTL exists to make that state explicit.

4. RTL — Asynchronous Assert, Synchronous Release

Engineering problem

Build the reset discipline correctly: assertion that takes effect without a clock, release that is aligned to the clock through synchronising registers, and an explicit initialisation gate so the middle state of §3 is representable rather than implicit.

Classification

SYNTHESIZABLE RTL — and this one is a genuine design pattern, not an educational model. The reset synchroniser below is the standard construct, used essentially unchanged in real designs.

What it represents: the assert/release asymmetry, the synchroniser, and the initialisation gate.

What it does not represent: the contents of a DDR initialisation sequence — mode-register writes, calibration, training — which are per-generation and belong to the device specification and Modules 19 to 21. INIT_EVENTS below is an educational cycle count, not any specification value. It also models no analog behaviour: the rail-to-rail signalling requirement on the reset input, supply sequencing, and the physical conditions under which reset must hold are all outside RTL.

One honest caveat about the synchroniser itself. Metastability is an analog phenomenon and RTL cannot model it. In simulation, the synchroniser below will always resolve cleanly and the unsynchronised alternative will also appear to work. That is precisely why this pattern must be applied by discipline rather than discovered by simulation — the bug it prevents is invisible in the tool where you would look for it.

Interface contract

reset_n_in is the asynchronous input. rst_n_sync is the distributed reset — asynchronously asserted, synchronously released. init_complete and cmd_allowed gate the middle state. illegal_cmd_during_init reports a command issued too early.

State

The synchroniser chain, an initialisation counter, and a completion flag.

Combinational behaviour

The command gate.

Sequential behaviour

The synchroniser and the counter, both reset asynchronously.

How to simulate

vlog reset_release_sync.sv tb_reset_release_sync.sv then vsim -c tb_reset_release_sync -do "run -all".

Expected result: assertion takes effect immediately even with the clock stopped; release propagates through the synchroniser over SYNC_STAGES cycles; commands are refused until INIT_EVENTS further cycles have elapsed.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// RESET RELEASE SYNCHRONISER.
// Classification: SYNTHESIZABLE RTL -- a GENUINE DESIGN PATTERN, not an
// educational model. The synchroniser below is the standard construct.
//
// THE ASYMMETRY IS THE POINT:
//   ASSERTION is ASYNCHRONOUS -- it must work when the clock is stopped,
//     unstable, or has just started. A reset that needed a clock edge
//     could not reset a device whose clock had failed.
//   RELEASE is SYNCHRONOUS -- deassertion at an arbitrary point relative
//     to the clock can leave registers metastable, so different parts of
//     the design leave reset on different cycles and a state machine can
//     start from a state that is not its reset state.
//
// AN HONEST CAVEAT: METASTABILITY IS ANALOG AND RTL CANNOT MODEL IT. In
// simulation this synchroniser always resolves cleanly -- and so does the
// unsynchronised alternative. The bug this pattern prevents is INVISIBLE
// in the tool where you would look for it, which is exactly why the
// pattern is applied by discipline rather than found by testing.
//
// WHAT THIS DOES NOT REPRESENT: the CONTENTS of a DDR initialisation
// sequence -- mode-register writes, ZQ calibration, write and read
// leveling -- which are per-generation and per-device (Modules 19-21 and
// the device specification). INIT_EVENTS is an EDUCATIONAL cycle count.
// Also absent: the rail-to-rail signalling requirement on the reset input,
// supply sequencing, and every analog condition on reset validity.
// ─────────────────────────────────────────────────────────────────────────
module reset_release_sync #(
  // Synchroniser depth. Two is the conventional minimum; deeper reduces
  // the probability of an unresolved capture propagating further.
  parameter int SYNC_STAGES = 2,
  // Cycles after synchronised release before commands are permitted.
  // EDUCATIONAL -- stands in for an initialisation sequence whose real
  // steps and durations are specification material.
  parameter int INIT_EVENTS = 8,
  parameter int CNT_W = (INIT_EVENTS <= 1) ? 1 : $clog2(INIT_EVENTS + 1)
) (
  input  logic             clk,
  // ASYNCHRONOUS, active low. Not sampled anywhere -- it appears in reset
  // sensitivity lists, which is what makes assertion clock-independent.
  input  logic             reset_n_in,

  // A command the controller wishes to issue.
  input  logic             cmd_req,

  // Distributed reset: asynchronously asserted, synchronously released.
  output logic             rst_n_sync,

  output logic             init_complete,
  output logic             cmd_allowed,
  // A command was requested before initialisation completed. Reported so
  // the middle state of Section 3 is observable rather than implicit.
  output logic             illegal_cmd_during_init,

  output logic [CNT_W-1:0] init_countdown
);

  // ── COMPILE-TIME legality.
  //
  //    A single synchroniser stage is rejected rather than permitted with
  //    a warning. One stage captures the asynchronous release directly and
  //    offers no time for an unresolved capture to settle -- it is the bug
  //    this module exists to prevent, wearing the shape of the fix.
  if (SYNC_STAGES < 2) begin : g_stages
    initial $fatal(1, "reset_release_sync: SYNC_STAGES must be >= 2");
  end
  if (INIT_EVENTS < 1) begin : g_init
    initial $fatal(1, "reset_release_sync: INIT_EVENTS must be >= 1");
  end

  // ─────────────────────────────────────────────────────────────────────
  // THE SYNCHRONISER.
  //
  // reset_n_in appears in the SENSITIVITY LIST, not in the body. That is
  // the whole construct: the register asserts the moment the input falls,
  // with no clock required, and releases only when a clock edge shifts a
  // one through the chain.
  //
  // Note the chain is fed a CONSTANT 1. It carries no data -- its only
  // job is to delay the RELEASE by SYNC_STAGES clock edges, giving any
  // unresolved capture in the first stage time to settle before the value
  // reaches anything that matters.
  // ─────────────────────────────────────────────────────────────────────
  logic [SYNC_STAGES-1:0] sync_chain;

  always_ff @(posedge clk or negedge reset_n_in) begin
    if (!reset_n_in) sync_chain <= '0;
    else             sync_chain <= {sync_chain[SYNC_STAGES-2:0], 1'b1};
  end

  assign rst_n_sync = sync_chain[SYNC_STAGES-1];

  // ─────────────────────────────────────────────────────────────────────
  // INITIALISATION GATE.
  //
  // Reset released is not the same as device ready -- Section 3's middle
  // state. This counter makes it explicit. Its reset is the SYNCHRONISED
  // reset, because by this point the design is in clocked operation and
  // everything downstream should leave reset on one known cycle.
  // ─────────────────────────────────────────────────────────────────────
  always_ff @(posedge clk or negedge rst_n_sync) begin
    if (!rst_n_sync) begin
      init_countdown          <= CNT_W'(INIT_EVENTS);
      init_complete           <= 1'b0;
      illegal_cmd_during_init <= 1'b0;
    end else begin
      illegal_cmd_during_init <= 1'b0;

      if (init_countdown != '0) begin
        init_countdown <= init_countdown - CNT_W'(1);
        if (init_countdown == CNT_W'(1)) init_complete <= 1'b1;

        // REPORT, NEVER REPAIR. A command issued during initialisation is
        // a controller bug; on real hardware the device's response is
        // undefined rather than reported, so surfacing it here is the
        // model's contribution.
        if (cmd_req) illegal_cmd_during_init <= 1'b1;
      end
    end
  end

  assign cmd_allowed = rst_n_sync && init_complete;

endmodule

Cycle-by-cycle example

SYNC_STAGES = 2, INIT_EVENTS = 4:

Eventreset_n_insync_chainrst_n_syncinit_countdowncmd_allowed
clock stopped000040
0101040
1111140
2111130
5111101

The first row is the key one. Reset asserts with the clock stopped, and sync_chain goes to zero anyway — because reset_n_in is in the sensitivity list rather than in the body. A reset that required a clock edge would do nothing here, which is the case it most needs to handle.

Events 0 and 1 are the synchronised release. Two clock edges pass before rst_n_sync rises, and every register downstream sees the release on one known edge.

Events 2 to 5 are §3's middle state. Reset is released, the device is not ready, and cmd_allowed is low. A controller that treats reset release as readiness issues commands here.

Waveform expectation

§5. Watch rst_n_sync fall with no clock edge and rise only after two.

Synthesis implication

SYNC_STAGES flip-flops with asynchronous reset, plus a counter. The synchroniser is the part to get right in physical implementation: its registers should be placed close together, and most flows have specific handling for reset synchronisers — false paths on the asynchronous input, and constraints ensuring the chain is not optimised away. A synthesis tool that flattens a constant-fed shift register would remove the entire protection, which is why the construct is usually marked explicitly.

Corner cases

SYNC_STAGES == 1 does not elaborate, deliberately — a single stage captures the asynchronous release directly with no settling time and is the bug wearing the shape of the fix. INIT_EVENTS == 1 gives a single-cycle gate. Reset asserting during initialisation restarts it completely, which is correct: a partially initialised device is not in a known state. Reset asserting with the clock stopped works, which is the entire requirement and is worth a directed test even though simulation makes it look trivial.

Debugging clues

If different parts of a design leave reset on different cycles, the synchronised reset is not the one being distributed — check whether anything downstream is using reset_n_in directly. If reset release appears to work in simulation and fails intermittently on hardware, that is the expected signature of an unsynchronised release, and simulation will never show it. If initialisation never completes, check that the counter's reset is rst_n_sync and not reset_n_in — using the raw input reloads the counter asynchronously and it may never be released cleanly. If commands are accepted immediately after release, cmd_allowed is gating on rst_n_sync alone.

Limitations

Metastability is not modelled and cannot be, which the header states at length and which is the most important limitation in this chapter: simulation cannot distinguish the correct construct from the incorrect one. No initialisation contents. No analog conditions on the reset input. INIT_EVENTS is a cycle count, not a duration. And no modelling of reset's interaction with CKE or power states, which a real sequence must address.

5. Assert Without a Clock, Release With One

reset_release_sync — asynchronous assertion, synchronous release, initialisation gate

10 cycles
Ten cycles. Reset is asserted while the clock is stopped and takes effect immediately, with no clock edge required. When the clock resumes and reset is deasserted, the synchroniser chain fills over two clock edges before the distributed reset releases. An initialisation countdown then runs, during which a requested command is refused and reported. Commands are permitted only once the countdown reaches zero.in resetin resetreleased, not readyreleased, not readyoperationaloperationalasserted, clock stoppedasserted, clock stoppedreleased after 2 edgesreleased after 2 edgescommand too earlycommand too earlyCKreset_n_insync_chain00000111111111111111rst_n_syncinit_countdown4444321000cmd_reqcmd_allowedillegal_cmdt0t1t2t3t4t5t6t7t8t9
Figure 2 — reset takes effect with the clock stopped, and releases two edges later.

The clock trace is deliberately irregular at the start — cycles 0 and 1 show it not toggling. sync_chain is already zero and rst_n_sync is already low, because assertion did not need an edge. That is the property that makes reset useful and it is the one most easily lost by writing a synchronously-reset register instead.

Cycles 2 and 3 are the synchronised release. The chain fills over two edges and rst_n_sync rises at cycle 3. Every register downstream sees that one transition, which is the point of the construct.

Cycles 3 to 6 are the three-state problem made visible. rst_n_sync is high — reset is released — and cmd_allowed is low. The command at cycle 5 is refused and reported at cycle 6. On real hardware the device's response to a command issued during initialisation is undefined, not reported, so this observability is the model's contribution.

Cycle 7 onward is operational. Three states, clearly separated.

Representative educational cycles. The four-event initialisation gate stands in for a real sequence whose steps and durations are specification material.

6. Three Assertions Worth Writing

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

// P1 -- assertion is IMMEDIATE and clock-independent. Sampled on the input
// rather than on a clock, because the property is precisely that no clock
// is required -- checking it at a clock edge would assume what it denies.
always_comb begin
  if (!reset_n_in) a_assert_immediate: assert (!rst_n_sync);
end

// P2 -- release takes at least SYNC_STAGES edges. The synchroniser's
// entire purpose, stated as a delay rather than as a structure, so a
// design that shortened the chain fails even if it still looks like a
// synchroniser.
property p_release_is_delayed;
  @(posedge clk)
    $rose(rst_n_sync) |-> $past(reset_n_in, SYNC_STAGES);
endproperty
assert property (p_release_is_delayed);

// P3 -- THE THREE-STATE PROPERTY. Commands are permitted only when reset
// is released AND initialisation is complete. A controller that models two
// states rather than three issues commands into the middle one, and this
// is the property that makes the middle state real.
property p_cmd_needs_both;
  @(posedge clk) disable iff (!rst_n_sync)
    cmd_allowed |-> (rst_n_sync && init_complete);
endproperty
assert property (p_cmd_needs_both);

property p_no_cmd_during_init;
  @(posedge clk) disable iff (!rst_n_sync)
    (init_countdown != '0) |-> !cmd_allowed;
endproperty
assert property (p_no_cmd_during_init);

// P4 -- reset during initialisation restarts it completely. A partially
// initialised device is not in a known state, so resuming a countdown
// would be worse than restarting it.
property p_reset_restarts_init;
  @(posedge clk)
    $rose(rst_n_sync) |-> (init_countdown == CNT_W'(INIT_EVENTS));
endproperty
assert property (p_reset_restarts_init);

P1 is written as an immediate assertion outside any clocked block, and that placement is the point. A concurrent property sampled at @(posedge clk) would only ever observe reset at clock edges — which assumes the clock is running, which is exactly the condition the property denies. Getting the sampling right here is not a style preference; a clock-sampled version of P1 tests nothing.

P2 asserts a delay rather than a structure, so it holds regardless of how the synchroniser is built and fails if the delay is shortened however elegantly.

And the limitation is the chapter's central one. None of these properties can detect the bug the synchroniser prevents. Metastability is analog; in simulation an unsynchronised release resolves cleanly and passes P2 by accident of zero-delay semantics. This construct is verified by design review and by synthesis constraints, not by simulation — and knowing which of your safety mechanisms simulation cannot validate is worth more than any individual property.

7. Common Misconceptions

"Reset can be synchronous — it is simpler and avoids asynchronous paths." Wrong model: a synchronously asserted reset is an acceptable simplification. Why it is tempting: synchronous design is cleaner, asynchronous inputs complicate timing analysis, and in simulation it works identically. Consequence: a device that cannot be reset when its clock has stopped or is unstable — which is one of the main situations reset exists for. Power-up, supply excursion and PHY re-initialisation all potentially occur without a trustworthy clock, and a synchronous reset is inert in all of them. Correct model: assertion must be asynchronous so it works without a clock. Release should be synchronous. The asymmetry is required, not stylistic. Prevention: ask whether the reset would work with the clock stopped. If not, it is not a reset.

"If assertion is asynchronous, release can be too — it is the same signal." Wrong model: the signal has one discipline. Why it is tempting: it is one wire, and treating the two edges differently looks like unnecessary complication. Consequence: metastability on release. Different registers leave reset on different cycles, so a state machine can start from a combination its designer never made reachable. The failure is probabilistic — thousands of clean runs and one failure — and it is invisible in simulation, which will resolve the release cleanly every time. Correct model: the two edges have opposite requirements. Assertion must not need a clock; release must be aligned to one. A two-stage synchroniser fed a constant provides the alignment. Prevention: apply the pattern by discipline. This is a case where testing cannot substitute for review, because the tool cannot see the fault.

"Reset released means the device is ready." Wrong model: two states — in reset, and operational. Why it is tempting: reset deasserting is the visible transition, and in many simpler devices it genuinely is sufficient. Consequence: commands issued into the middle state, where the device's response is undefined rather than reported. Configuration has not been written, calibration has not run, and training has not measured the interface timing — so the controller does not yet know when to launch or capture data. Correct model: three states. In reset; released but not initialised; operational. The middle state has a defined entry and a defined exit and must be modelled explicitly. Prevention: ask what the device has been told since reset. If the answer is nothing, it has not been configured.

"A reset synchroniser is verified by simulating it." Wrong model: if the reset release works in simulation, the construct is correct. Why it is tempting: it is how every other piece of logic is validated, and the simulation genuinely passes. Consequence: an unsynchronised or single-stage release shipping, because simulation cannot distinguish it from the correct construct. Metastability is analog and has no representation in RTL semantics; the incorrect version passes every test. Correct model: the synchroniser is validated by design review, synthesis constraints and static analysis — false paths on the asynchronous input, constraints preventing the chain from being optimised away, and lint rules requiring the pattern. Simulation confirms the functional sequence and says nothing about the hazard. Prevention: maintain an explicit list of safety mechanisms simulation cannot validate. Reset synchronisers, clock-domain crossings and setup/hold contracts all belong on it.

8. Debugging — The System Fails to Come Up, Intermittently

Symptom. A memory interface usually initialises correctly and occasionally does not. The failure is not reproducible on demand, may differ between boards, and sometimes clears on a retry.

Intermittent, unreproducible, sometimes-clears-on-retry is the signature of a probabilistic fault, and there are few of those. That narrows the search dramatically before any measurement.

Mechanism 1 — reset release is unsynchronised. Inspect: whether the reset distributed to the design is the raw input or a synchronised version, and whether any block uses the raw input directly. Expected evidence: logic leaving reset on different cycles, and a failure rate that changes with clock frequency. Discriminator: is the fault probabilistic rather than conditional? This is first because it costs nothing — it is a code and constraint review — and because simulation will never find it, so it survives a complete regression.

Mechanism 2 — commands issued during initialisation. Inspect: whether the controller waits for the full sequence before issuing. Expected evidence: failures correlated with how quickly the controller starts, and with system timing that varies run to run. Discriminator: does delaying the first command fix it? A crude but decisive experiment, and it separates the middle-state error from a genuine reset fault.

Mechanism 3 — initialisation ran but a step failed silently. Inspect: whether calibration and training reported success and with what margin. Expected evidence: a sequence reporting completion while having converged badly. Discriminator: read the reported margins, not the pass bit. Chapter 4.4 §11's third mechanism — a procedure that found a one-step-wide window reports success and has told you the system will fail.

Mechanism 4 — reset did not hold long enough or was not clean. Inspect: the reset input's duration and its signalling quality against the device's requirement. Expected evidence: failures correlated with supply ramp or with board-to-board variation. Discriminator: measure the reset pulse. This is the genuinely analog mechanism and it is worth reaching last, but a marginal or non-rail-to-rail reset produces exactly this symptom.

Mechanism 5 — not reset: the clock was not stable when initialisation began. Inspect: whether the clock source had settled before the sequence started. Expected evidence: failures correlated with how quickly the sequence begins after power-up. Discriminator: delay the sequence start and see whether it clears. Distinguished from mechanism 2 by what is being delayed — the whole sequence rather than the first command.

Discrimination, cheapest first. Review which reset every block actually uses, and whether a synchroniser exists at all — free, and it addresses the one mechanism simulation cannot find. Then delay the first command, and separately delay the whole sequence start; those two experiments split mechanisms 2 and 5. Then read the training and calibration margins. Only then measure the reset pulse.

The reasoning lesson. A probabilistic fault is a strong clue, because very few mechanisms produce one. Deterministic faults fail every time or under identifiable conditions; genuine randomness usually means metastability, marginal analog timing, or a race — a short list. So the productive first move is not to gather more data but to ask whether the fault is probabilistic or merely poorly characterised, because the answer selects the suspect list. And when metastability is on that list, remember the corollary: the regression suite passing is not evidence, because the tool has no representation of the fault.

9. Interview Reasoning

"Why does RESET# have a dedicated pin when CKE and ODT lost theirs?" Because a command is only meaningful if the command path is working, and reset is needed when it is not. A command needs a clock to be sampled against, a device that is sampling, and a configuration that makes the encoding interpretable — and reset may be required when the clock has stopped, when the device is in an unknown power state, or when its configuration is corrupt. So the criterion is: does this function need to work when the command path does not? If yes, it needs a wire, and no amount of pin pressure changes that. CK and RESET# are the two that pass; CKE, ODT and the command trio did not, which is why they were all eventually encoded.

"Why is reset asserted asynchronously but released synchronously?" The two edges have opposite requirements. Assertion must not depend on a clock, because one of the main situations reset exists for is a stopped or unstable clock — a synchronously asserted reset is inert exactly when it is most needed. Release returns the design to clocked operation, and if it deasserts at an arbitrary point relative to the clock edge it can violate the timing requirements of the registers coming out of reset, leaving them metastable. The practical consequence is that different registers leave reset on different cycles, so a state machine can start from a combination its designer never made reachable — and because metastability resolution is probabilistic, that shows up as thousands of clean runs and one failure.

"How do you verify a reset synchroniser?" Not by simulating it, which is the important part of the answer. Metastability is an analog phenomenon with no representation in RTL semantics, so in simulation the correct construct and an unsynchronised release both resolve cleanly and both pass. It is verified by design review, by lint rules requiring the pattern, and by synthesis and timing constraints — false paths on the asynchronous input, and constraints ensuring the synchroniser chain is not optimised away, since a tool that flattens a constant-fed shift register removes the whole protection. It is worth keeping an explicit list of safety mechanisms that simulation cannot validate, because reset synchronisers, clock-domain crossings and setup/hold contracts all belong on it.

"Is a device ready when reset is released?" No — there are three states, not two. In reset; released but not initialised; and operational. After release, configuration has to be written to mode registers, impedance calibration has to run against the external reference, and interface timing has to be trained per rank and per direction, because from DDR3 onward that timing is measured rather than designed. Until training has run the controller does not know when to launch or capture data. A controller that models only two states issues commands into the middle one, and the device's response there is undefined rather than reported — so it produces a failure with no diagnostic.

"A system intermittently fails to initialise, unreproducibly. How do you approach it?" By first asking whether the fault is genuinely probabilistic or just poorly characterised, because that question selects the suspect list — very few mechanisms produce real randomness, and metastability, marginal analog timing and races are most of them. If it is probabilistic, the first thing to review is whether reset release is synchronised and whether every block uses the synchronised version, because that costs nothing and is the one mechanism a full regression cannot find. Then two crude experiments: delay the first command, and separately delay the start of the whole initialisation sequence — the first tests whether commands are being issued into the not-yet-initialised middle state, and the second tests whether the clock had settled before the sequence began. Then read the training and calibration margins rather than their pass bits, because a procedure that converged on a one-step-wide window reports success and has told you the system will fail. Measuring the reset pulse itself comes last, though a marginal reset produces the same symptom.

10. Engineering Exercise

Educational cycle counts; real initialisation steps and durations are specification material.

1. A design asserts reset synchronously. Name the situation in which it fails completely. A stopped or unstable clock. With no clock edge, a synchronously asserted reset never takes effect — and power-up, supply excursion and PHY re-initialisation are all cases where the clock cannot be trusted. The reset is inert exactly when it is most needed.

2. A design releases reset asynchronously. What is the symptom, and why will simulation not show it? Registers leave reset at slightly different times, so a state machine can start from a state that is not its reset state. The symptom is intermittent and unreproducible because metastability resolution is probabilistic. Simulation resolves the release cleanly every time — metastability has no representation in RTL semantics — so the incorrect construct passes every test.

3. §4 refuses to elaborate with SYNC_STAGES = 1. Justify the refusal rather than a warning. A single stage captures the asynchronous release directly, with no settling time before the value reaches logic that acts on it. It is the bug wearing the shape of the fix — it looks like a synchroniser and provides none of the protection — and because simulation cannot distinguish it from a correct one, a warning would be ignored and a compile failure cannot be.

4. Why is §4's initialisation counter reset by rst_n_sync rather than by reset_n_in? Because by that point the design is in clocked operation and everything downstream should leave reset on one known cycle. Resetting it from the raw input would reintroduce an asynchronous release into the very logic the synchroniser exists to protect. The synchroniser's output is the reset the design uses; the raw input goes only to the synchroniser.

5. A controller asserts its first command two cycles after reset release. What has it assumed, and what is undefined? It has assumed two states rather than three. Configuration has not been written, calibration has not run, and training has not measured the interface — so the controller does not know when to capture the response, and the device's reaction to a command in this state is undefined rather than reported. There is no error to observe; the system simply misbehaves.

6. Using §1's criterion, decide whether a hypothetical "clear all mode registers" function should be a pin or a command. A command. It does not need to work when the command path is broken — a device whose command path is unusable cannot be usefully configured anyway, and the recovery path for that condition is RESET# itself. It is per-device and infrequent, which are exactly the properties Chapter 6.2 §6 identified as making a function encodable. The criterion gives a clear answer, which is what makes it useful.

11. Summary

RESET# cannot be encoded, and the reason is structural. A command requires a clock to be sampled against, a device that is sampling, and a configuration that makes the encoding interpretable. Reset is the signal you need when none of those can be assumed.

That yields a testable criterion: does a control function need to work when the command path is not working? Yes → it needs a dedicated wire, and CK and RESET# are the two that qualify. No → it is a candidate for encoding, and CKE, ODT and the command trio all were. This is why the module's encoding trend has a floor rather than being unbounded.

The discipline is asymmetric, and both halves are required. Assertion is asynchronous because it must work with the clock stopped — a synchronously asserted reset is inert in the situations reset exists for. Release is synchronous because deassertion at an arbitrary point relative to the clock can leave registers metastable, so different parts of the design leave reset on different cycles and a state machine can start from a state nobody made reachable.

And the fault that discipline prevents is invisible in simulation. Metastability is analog and has no RTL representation, so the incorrect construct passes every test. The synchroniser is validated by design review, lint rules and synthesis constraints — not by simulation. Knowing which safety mechanisms your tools cannot validate is worth more than any individual property.

Release is not readiness. There are three states: in reset, released but not initialised, and operational. The middle state requires mode-register configuration, impedance calibration and interface training — and before training the controller does not know when to launch or capture data. A controller modelling two states issues commands into the middle one, where the device's response is undefined rather than reported.

And the debugging lesson generalises. A probabilistic fault is a strong clue, because few mechanisms produce genuine randomness — metastability, marginal analog timing, and races are most of the list. So the first question is whether the fault is probabilistic or merely poorly characterised, because the answer selects the suspects.

12. What Comes Next

The module now turns to the data path, and everything changes.

Every signal so far has had fixed ownership — the controller side drives CK, CKE, CS#, the command pins, ODT and RESET#, and no DRAM ever drives any of them. Chapter 6.9 takes the first signal where that is not true.

DQ is bidirectional, and "bidirectional" is a nearly useless description of it. What matters is temporal ownership: who drives these wires right now, how ownership changes, and what guarantees the two sides never drive simultaneously. That is a state-machine problem, and it is where this module's RTL gets substantial.

Return to CK / CK# for the other signal that cannot be encoded, CKE for the exit-interval pattern §3 repeats, or DDR3 for the calibration and training the initialisation sequence runs. 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.