Skip to content

GLS · Chapter 1 · RTL vs Gate-Level Simulation

Working Example: A D Flip-Flop from RTL to Gates

This closing lesson makes the whole RTL-versus-gate-level chapter concrete on one design: a single D flip-flop taken end to end from RTL, through synthesis into a real standard-cell netlist, to a clean four-state gate-level simulation. You see the same flip-flop as behavioral RTL and as a library cell, and watch each divergence appear on it. The real cell powers up unknown, its internal name becomes a cell instance, its update takes a real clock-to-output delay, and any initial block you leaned on is gone. The debug walkthrough takes the flop to a clean run by telling the expected transient unknown at time zero, which reset clears, apart from a real persistent unknown caused by a reset gap. Master one flop and you have the pattern for everything larger.

Foundation13 min readGLSD Flip-FlopWorked ExampleFour-StateReset

Chapter 1 · Section 1.5 · RTL vs Gate-Level Simulation

Project thread — the D flip-flop we have followed since 0.1 now goes end-to-end: RTL to gates to a clean four-state GLS, applying every idea from 1.1–1.4 on one design. Chapter 2 reads real netlists; the counter is next.

1. Why Should I Learn This?

Ideas stick when you watch them play out on a concrete design from start to finish. This lesson is where the four divergence axes, the synthesis equivalence, the vanished constructs, and the four-state requirement stop being separate rules and become one continuous story on a single flip-flop — RTL, netlist, and a clean GLS run. Being able to take one simple design cleanly across the RTL-to-gates gap is the exact skill you scale to a counter, an FSM, and eventually a mini-SoC; the flip-flop is where you earn it.

This lesson is the chapter's synthesis — it ties 1.1–1.4 together — and it is the on-ramp to Chapter 2, where you read the real netlist and standard-cell library in depth.

2. Real Silicon Story — the flip-flop that taught the whole flow

A lead onboarding a new engineer does not start them on the big block. They hand over one D flip-flop and say: 'take this from RTL to a clean gate-level run, and explain every difference you see.' The engineer is briefly puzzled — 'it is one flop, what is there to see?' — and then discovers the whole gate-level world in miniature: the cell powers up X (initialisation), the signal is now U0.Q not dff.q (structure), it updates a fraction of a nanosecond after the edge once SDF is on (timing), and the initial q = 0; they added out of habit did nothing in the netlist (construct fidelity). They learn to run it four-state so the X is visible, and to see reset wash the X out into a clean steady state — and to tell that transient X apart from a persistent one. In an afternoon, on one flop, they have exercised every concept the big block will throw at them. The post-mortem lesson: the fastest way to understand gate-level simulation is to take the simplest sequential design — a D flip-flop — all the way from RTL to a clean four-state GLS run, because every divergence, transformation, vanished construct, and four-state subtlety appears on it in miniature; master the flop and you have the pattern for everything larger.

3. Concept — the whole chapter, on one flip-flop

Taking the D flip-flop from RTL to a clean GLS exercises every Chapter 1 idea at once:

  • Initialisation (1.1): the real flip-flop cell powers up X; a reset — not an initial — drives it to a known value.
  • Structure (1.1, 1.2): the behavioural always_ff becomes a library cell instance (DFFRX1 U0); the RTL signal name is gone, replaced by U0.Q.
  • Timing (1.1): with SDF, Q updates a real clk-to-q delay after the edge (in a functional/zero-delay run it updates at the edge).
  • Equivalence (1.2): for defined d and a proper reset, the netlist's captured value matches the RTL — synthesis preserved the defined-input function.
  • Construct fidelity (1.3): any initial q = ... in the design vanished — the initialiser must be reset.
  • Four-state (1.4): the run must be four-state to see the power-up X and confirm reset clears it.

The steady-state target: X at power-up → reset asserts → q known → captures d cleanly. Here is the flip-flop itself — the cell the whole story is about:

A D flip-flop with data D, posedge clock, asynchronous reset, output Q — the synthesized cell behind the RTL always_ffD flip-flop cell — D, CK (posedge), async reset, Q (powers up X until reset)D flip-flop cell — D, CK (posedge), async reset, Q (powers up X until reset)D-FF↑ posedge↑ posedgedDclkqQrst_n
Figure 1 — the D flip-flop at the centre of the walkthrough. Behavioural RTL (always_ff with an async reset) synthesizes to this real library cell: data D, clock CK (posedge), async reset RN, output Q. In gate-level simulation the cell powers up X (initialisation), so reset (RN) must drive Q to a known value; then each posedge captures D after a real clk-to-q delay (with SDF). The initialiser is RN (reset), not a vanished initial block, and the run must be four-state to see the power-up X and watch reset wash it out.

4. Mental Model — the flip-flop is the whole gate world in one cell

5. Working Example — the D flip-flop, end to end

Walk the flip-flop from RTL, through synthesis, to a clean four-state GLS run.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// STEP 1 — RTL (SystemVerilog): behavioural D flip-flop, initialised by RESET (not an initial block).
module dff (input logic clk, input logic rst_n, input logic d, output logic q);
  always_ff @(posedge clk or negedge rst_n)
    if (!rst_n) q <= 1'b0;   // reset drives a KNOWN value (the initialiser that survives synthesis, 1.3)
    else        q <= d;
endmodule

The same flip-flop in Verilog and VHDL — all three synthesize to the same cell and traverse the RTL-to-gates gap identically (start-X, renamed cell, real clk-to-q):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// STEP 1 — RTL (Verilog): same D flip-flop, reset-initialised.
module dff (input clk, input rst_n, input d, output reg q);
  always @(posedge clk or negedge rst_n)
    if (!rst_n) q <= 1'b0;
    else        q <= d;
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- STEP 1 — RTL (VHDL): same D flip-flop with async reset; reset is the initialiser (no signal-init trick).
process(clk, rst_n)
begin
  if rst_n = '0' then         q <= '0';
  elsif rising_edge(clk) then q <= d;
  end if;
end process;
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// STEP 2 — NETLIST (representative): synthesis maps always_ff -> a real library cell.
// Structure changed (U0, not dff.q); function preserved for defined d + proper reset (1.1/1.2).
module dff_netlist (input clk, input rst_n, input d, output q);
  DFFRX1 U0 (.D(d), .CK(clk), .RN(rst_n), .Q(q));   // RN = async reset; Q powers up X until RN asserts
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// STEP 3 — TESTBENCH (GLS-adapted, conceptual): drive reset, then data. Run FOUR-STATE (1.4).
initial begin
  clk = 0; rst_n = 0; d = 1;   // hold reset asserted at start
  #7  rst_n = 1;               // release reset -> q should be known (0) BEFORE first capture
  #8  d = 0;
  #40 $finish;
end
always #5 clk = ~clk;          // 100 MHz
initial $monitor("t=%0t rst_n=%b d=%b q=%b", $time, rst_n, d, q);
// Run four-state so the power-up X is VISIBLE and you can confirm reset washes it out.

The clean four-state GLS log tells the complete story — X, then reset, then correct capture:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# FOUR-STATE GLS — the whole chapter in one waveform:
t=0  rst_n=0 d=1 q=x      <- INITIALISATION: the real cell powers up X (1.1); four-state SHOWS it (1.4)
t=0  rst_n=0 d=1 q=0      <- RN (reset) drives Q to known 0 -> X WASHED OUT (transient, expected)
t=7  rst_n=1 d=1 q=0      <- reset released; q already known
t=10 (posedge)
t=10.3 q=1               <- captures d=1 after a real clk-to-q delay (TIMING, with SDF, 1.1)
t=15 d=0
t=20 (posedge) q=0       <- captures d=0 -> function matches RTL for defined d (EQUIVALENCE, 1.2)

This is a clean gate-level run: the power-up X is visible (four-state), transient (reset clears it before it is used), the structure is the cell (U0), the timing is real, and the captured values match RTL for defined d. Every Chapter 1 idea appears — and none of the differences is a bug. The next section is the judgement that makes it clean: telling the expected transient X from a real one.

6. Debugging Session — taking the flip-flop to a clean run (transient X vs real X)

1

Bringing the D flip-flop to a clean four-state GLS run hinges on one judgement — the X at time zero is an expected transient that reset clears, unless a reset gap makes it persist, which is the real bug

TRANSIENT X (EXPECTED) vs PERSISTENT X (RESET GAP)
Symptom

The first four-state GLS of the flip-flop shows q = X at time zero. Two very different situations look identical for one instant: in the healthy case, reset immediately drives q to a known value; in the buggy case, q stays X. The question — and the whole skill — is telling them apart at a glance.

Root Cause

The X at time zero is the initialisation axis (1.1): a real flip-flop cell powers up unknown, and four-state simulation (1.4) correctly shows it. That instantaneous X is expected and not a bugprovided reset then drives the flop to a known value before it is used. So the diagnosis is entirely about duration: a transient X that reset washes out is the expected initialisation behaviour; an X that persists past reset is a real defect — a reset gap (the flop is not actually on the reset, or reset releases before driving it, or — the 1.3 trap — the design leaned on a vanished initial and has no real reset). In the healthy netlist, RN (the async reset) is connected and asserted at start, so Q goes to 0 in the same instant and the X vanishes. In the buggy netlist, RN is not driven (or the design used an initial that vanished), so nothing washes the X out and it spreads. Both start with q = X; only the persistent one is the bug. This single judgement — transient (expected) vs persistent (reset gap) — is the core of reading any gate-level power-up, and it is why four-state matters (a two-state run would show neither X and hide the distinction entirely).

Fix

Read the duration of the X, not just its presence: confirm reset washes out the power-up X before the flop's value is used (healthy — leave it), and treat an X that survives reset as a real reset gap (fix — connect the flop to the reset, correct the release timing, or add the real reset the vanished initial was masking, 1.3). Re-run four-state and confirm the flop reaches a known steady state and captures defined d correctly (matching RTL, 1.2). The lesson, and the close of the chapter: taking a design cleanly from RTL to gates comes down to distinguishing expected divergence from a real bug — for a flip-flop, the power-up X is an expected transient (initialisation) that reset must clear, and only a persistent X (reset gap) is a defect; you must run four-state to see the X at all, keep the initialiser a reset (not a vanished initial), and expect the structure and timing to differ. Scale this exact gesture — see the X, watch reset clear it, confirm defined function — to the counter next, and to every larger design.

7. Common Mistakes

  • Reading the power-up X as a bug. For a flop it is the expected transient (initialisation) — only an X that persists past reset is a defect (reset gap).
  • Running the walkthrough two-state. You would see neither the power-up X nor the transient-vs-persistent distinction — run four-state (1.4).
  • Initialising the flop with an initial block. It vanishes in synthesis (1.3); the initialiser must be reset, or the flop powers up X with nothing to clear it.
  • Expecting dff.q in the netlist. The signal is a cell instance (U0.Q) after synthesis (structure axis) — do not treat the renamed signal as missing.
  • Assuming a timing difference is a bug. A real clk-to-q after the edge (with SDF) is the timing axis, expected — not a defect.

8. Industry Best Practices

  • Learn the flow on one flip-flop first. Every gate-level behaviour appears on it in miniature — master it before scaling up.
  • Run four-state, initialise by reset, expect real structure/timing. The three non-negotiables for a clean gate-level run.
  • Judge a power-up X by duration. Transient (reset clears it) is expected; persistent (survives reset) is a reset-gap bug.
  • Confirm defined-input function matches RTL. Equivalence is for defined inputs — a mismatch there is the one that signals a real synthesis/constraint problem.
  • Scale the same gesture upward. See the X, watch reset clear it, verify defined function — the counter, FSM, and SoC repeat this, larger.

Senior Engineer Thinking

  • Beginner: "The flop is X at t=0 in GLS — the netlist is broken."
  • Senior: "It is X for one instant — that is a real cell powering up, shown because I ran four-state. Does reset wash it out before it is used? If yes, expected. If it persists, that is a reset gap — the real bug."

The senior reads the duration of the X and the reason for each difference, not the mere presence of a difference — the judgement the whole chapter built toward.

Silicon Impact

Getting this judgement wrong runs both ways. Treat the expected transient X as a bug and you waste effort 'fixing' a correctly-working flop (and may mask reset by over-forcing). Miss a persistent X — dismiss it as 'just the usual power-up X' — and a real reset gap ships: the flop comes up unknown in silicon, causing intermittent boot failures and field returns (Ch0's escape, now on a concrete design). The whole value of Chapter 1 is landing this distinction reliably: expected divergence is free to accept, a persistent X is a respin if it escapes. On one flop the stakes are small; the habit you build here is what keeps the mini-SoC's thousands of flops off the return pile.

Engineering Checklist

  • Ran the flip-flop's GLS four-state so the power-up X is visible.
  • Initialised the flop by reset, not an initial block.
  • Confirmed reset washes out the transient power-up X before the value is used.
  • Treated any X that persists past reset as a real reset-gap bug.
  • Verified the netlist captures defined d matching RTL (equivalence), and accepted the expected structure/timing differences.

Try Yourself

  1. Take the flip-flop from RTL to a four-state gate-level run (RTL, then the representative cell), reset asserted at start.
  2. Observe: q is X at t=0, then reset drives it to 0 (transient), then it captures d after the edge.
  3. Change: disconnect reset (or remove the reset branch) and re-run.
  4. Expect: the start-X now persists — a reset gap. Telling that persistent X from the healthy transient is the whole skill, and it scales unchanged to the counter next.

Any four-state Verilog/VHDL simulator suffices — no paid tool. Commercial simulators/SDF add real timing (Chapter 4) but are not needed to see this.

Interview Perspective

  • Weak: "The flop is X at t=0 in GLS, so the netlist is broken."
  • Good: "A real cell powers up X; four-state shows it, and reset should wash it out before the value is used."
  • Senior: "I judge the X by duration: a transient reset clears is expected; an X that survives reset is a reset gap — the real bug. And I run four-state, or I'd see neither."

Quick Revision

The flip-flop is the whole gate world in miniature. RTL → real cell (structure/name change) → power-up X (initialisation) → reset washes it out → captures defined d (equivalence), run four-state so the X is visible. Clean run = X, then reset, then correct capture. Transient X = expected; persistent X = reset gap (bug). Next: Chapter 2 reads real netlists and standard-cell libraries — with the counter as the next design.

9. Interview / Review Questions

10. Key Takeaways

  • A single D flip-flop taken from RTL to a clean four-state GLS run exercises every Chapter 1 idea — initialisation, structure, timing, construct fidelity, and the four-state requirement — in miniature.
  • The clean-run story: RTL (reset-initialised) → real cell (renamed structure) → power-up X (initialisation, visible only in four-state) → reset washes the X out (transient) → captures defined d after a real clk-to-q (timing), matching RTL for defined inputs (equivalence).
  • Every difference from RTL here is an expected divergence, not a bug — the structure (U0.Q), the timing (delayed update), and the transient power-up X.
  • The one essential judgement: a transient X that reset clears is expected; an X that persists past reset is a real reset-gap bug — and you must run four-state to see the X and make the call (a two-state run hides it).
  • Initialise by reset (never initial), expect the structure and timing to differ, verify defined-input function matches RTL, and scale the same gesture — see the X, watch reset clear it, confirm defined function — to the counter next. This closes the RTL-vs-gate-level chapter; Chapter 2 reads real netlists and standard-cell libraries.