Skip to content

GLS · Chapter 2 · Netlists & Standard-Cell Libraries

Working Example: Reading a Counter Netlist

This capstone applies everything in the chapter to one real artifact: a synthesized 4-bit counter netlist. Starting from the counter's RTL in SystemVerilog, Verilog, and VHDL, it walks a representative gate-level netlist and reads it the way a working engineer does. You identify the state flip-flops and the increment logic using netlist anatomy, recognize the cells as instances from the standard-cell library, and understand that gate-level simulation runs their UDP models, that their specify arcs carry timing that stays placeholder until SDF, and that their sequential timing checks can drive a flop unknown. A representative waveform and simulator log show the counter sitting at unknown at power-up until reset is asserted, then counting cleanly. The debug session ties back to reset discipline: a counter stuck at unknown because a state flop never saw reset. All netlists are representative, and the power-up unknown is functional zero-delay behaviour, not a timing proof.

Foundation15 min readGLSNetlistCounterResetWorked Example

Chapter 2 · Section 2.6 · Netlists & Standard-Cell Libraries

Project thread — the D flip-flop of Chapter 1 becomes a counter here: several flops holding state, plus increment logic. Reading its netlist end-to-end is the capstone skill; the counter carries forward into the mini-SoC of later chapters, and its specify arcs get real timing in Chapter 3.

1. Why Should I Learn This?

Everything in Chapter 2 was in service of this: being able to open a synthesized netlist and read it — find the state, find the next-state logic, know which cells are library instances, know that GLS runs their models, and know how they behave at power-up and under reset. A counter is the smallest design where that whole skill matters (state + combinational logic + reset), and its power-up-X-until-reset signature is the single most important gate-level pattern to recognise on sight.

This capstone integrates 2.1–2.5 on one artifact and closes the chapter, advancing the project from a lone flip-flop to a counter. It also reconnects to the reset discipline of Chapters 0–1 — now visible directly in the netlist — and it sets up Chapter 3, where these specify arcs finally carry real timing numbers.

2. Real Silicon Story — the counter that powered up counting in sim but froze in silicon

A gate-level counter is simulated and 'works': in the waveform it counts 0, 1, 2, 3, … from the very first cycle. The team ships. In silicon, the counter sometimes powers up frozen or counting from a random value, causing intermittent failures downstream.

The simulation had been reading the netlist without the power-up-X lens of this chapter. Real state flip-flops power up unknown, and a gate-level run shows this — the counter should read X until reset forces the flops to a known value. The 'clean count from cycle one' in the original run came from a testbench that pre-loaded the flops (or a two-state simulation, 1.4) — masking the fact that the design lacked a proper reset on the counter's state. Reading the netlist correctly — spotting the state flops (2.1), knowing they are DFFRX1 with a reset pin from the library (2.2), and knowing their UDP starts at X until RN asserts (2.3) — would have shown the counter stuck at X with no reset, exactly matching the silicon's random power-up. The post-mortem lesson: a synthesized counter netlist must be read with the whole chapter's lenses — state flops (2.1) that are library cells (2.2) whose UDP models (2.3) power up X until reset — and its correct gate-level signature is X at power-up until reset, then counting; a run that 'counts from cycle one' without reset is masking a missing-reset bug that silicon will expose.

3. Concept — reading the counter netlist with all five lenses

A synthesized 4-bit counter netlist decomposes into two parts you can see:

  • State: the flip-flops. Four DFFRX1 instances (one per bit) — the counter's memory. Read with 2.1 (cell instances, ports D/CK/Q/RN), recognised as 2.2 library cells, simulated via their 2.3 UDP (power up X, reset via RN), timed by 2.4 arcs (CK => Q, placeholder until SDF), guarded by 2.5 checks ($setup/$hold + notifier).
  • Next-state: the increment logic. Combinational cells (XOR2X1, AND2X1, INVX1, …) computing count + 1 — the adder/increment. Read with 2.1 (gates + nets), library cells (2.2), UDP/primitive models (2.3), specify arcs (2.4).
  • Reset fan-out. The reset net (RN) driven to every state flop — the thing that turns power-up X into a known 0.
  • Behaviour: flops power up X (2.3) → X ripples through the increment logic → reset asserts → flops go 0 → counter counts 0,1,2,3,….
  • Scope: representative netlist (not exact tool output); power-up X here is functional, zero-delay (no SDF) — not a timing proof (0.3/0.4).

Here is the counter netlist, read structurally:

4-bit counter netlist: four DFFRX1 state flops fed by XOR/AND increment logic, with a reset net fanning out to all flopscurrent countcount+1captured onCKreset -> 0clockIncrement logic(XOR/AND/INV)combinational: count + 1(2.1 gates, 2.2 cells, 2.3models)D inputsnext-state value into eachflop4x DFFRX1 state flopscount[0..3] — library cells(2.2), UDP power up X (2.3)Reset net (RN)fans out to EVERY flop —turns power-up X into known0Clock (CK)CK => Q arc (2.4),$setup/$hold checks (2.5)count[3:0] outputX at power-up until reset,then 0,1,2,3,...12
Figure 1 — a synthesized 4-bit counter netlist, read structurally (representative). The STATE is four DFFRX1 flip-flops (one per bit, count[0..3]) — library cells (2.2) whose UDP models (2.3) power up X until RESET. The NEXT-STATE increment logic (XOR/AND/INV cells) computes count+1 and feeds each flop's D. The RESET net (RN) fans out to every flop, turning power-up X into a known 0. GLS runs the cells' models: flops start X, X ripples through the increment gates, then reset forces 0 and the counter counts. Timing (specify arcs, 2.4) is placeholder until SDF (Ch3/4); this power-up X is functional zero-delay behaviour, not a timing proof.

4. Mental Model — a counter netlist is a ring of memory and math, blind until reset

5. Working Example — counter RTL (tri-HDL), representative netlist, and the waveform

The counter RTL, in three languages (simple design — all three sharpen the reading):

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// SystemVerilog — 4-bit up counter with synchronous active-low reset
module counter4 (input logic clk, input logic rst_n, output logic [3:0] count);
  always_ff @(posedge clk)
    if (!rst_n) count <= 4'd0;
    else        count <= count + 4'd1;
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Verilog-2001 — same counter
module counter4 (clk, rst_n, count);
  input clk, rst_n; output reg [3:0] count;
  always @(posedge clk)
    if (!rst_n) count <= 4'd0;
    else        count <= count + 4'd1;
endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- VHDL — same counter
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
entity counter4 is
  port (clk, rst_n : in std_logic; count : out unsigned(3 downto 0));
end entity;
architecture rtl of counter4 is
  signal cnt : unsigned(3 downto 0);
begin
  process (clk) begin
    if rising_edge(clk) then
      if rst_n = '0' then cnt <= (others => '0');
      else                cnt <= cnt + 1;
      end if;
    end if;
  end process;
  count <= cnt;
end architecture;

Synthesis maps this to a representative gate-level netlist — four flops plus increment logic:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Synthesized counter4 netlist — REPRESENTATIVE (shape only; not exact tool output)
module counter4 (clk, rst_n, count);
  input  clk, rst_n;
  output [3:0] count;
  wire   n0, n1, n2, n3;                         // next-state (count+1) nets
 
  // NEXT-STATE increment logic (count + 1) — combinational library cells (2.1/2.2/2.3)
  INVX1  u_i0 (.A(count[0]),               .Y(n0));                 // bit0 toggles
  XOR2X1 u_x1 (.A(count[1]), .B(count[0]), .Y(n1));                 // bit1 ^ carry
  XOR2X1 u_x2 (.A(count[2]), .B(/*carry*/), .Y(n2));               // higher bits...
  XOR2X1 u_x3 (.A(count[3]), .B(/*carry*/), .Y(n3));
 
  // STATE flip-flops — library cells (2.2), UDP models power up X until RN (2.3),
  // CK=>Q arc (2.4), $setup/$hold + notifier (2.5). Reset net rst_n -> RN on every flop.
  DFFRX1 u_q0 (.D(n0), .CK(clk), .RN(rst_n), .Q(count[0]));
  DFFRX1 u_q1 (.D(n1), .CK(clk), .RN(rst_n), .Q(count[1]));
  DFFRX1 u_q2 (.D(n2), .CK(clk), .RN(rst_n), .Q(count[2]));
  DFFRX1 u_q3 (.D(n3), .CK(clk), .RN(rst_n), .Q(count[3]));
endmodule

Reading it: u_q0..u_q3 are the state (2.1 instances, 2.2 cells); u_i0/u_x1.. are the increment logic; rst_n fans out to every flop's RN. GLS runs their models (2.3), so the representative waveform/log shows the signature life story:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# Representative GLS waveform / log (zero-delay, no SDF) — counter4
time  rst_n  clk        count[3:0]   note
----  -----  ---------  ----------   ---------------------------------------------
 0     0      -           xxxx       power-up: state flops UNKNOWN (UDP init, 2.3)
 5     0      posedge     0000       reset asserted (RN=0) -> every flop forced 0
15     1      posedge     0001       reset released -> increment logic active -> count+1
25     1      posedge     0010       0001 -> 0010
35     1      posedge     0011       counting cleanly: 2 -> 3
45     1      posedge     0100       3 -> 4 ...
# X at power-up UNTIL reset, then counts. This is FUNCTIONAL zero-delay behaviour,
# NOT a timing proof (specify arcs are placeholder until SDF, Ch3/4). (0.3/0.4)

That xxxx0000 (on reset) → 0001, 0010, … is the healthy signature. The next section shows the broken one.

6. Debugging Session — a counter stuck at X (a state flop that never saw reset)

1

A gate-level counter stays stuck at X and never counts — one (or all) of its state flops never sees reset (an unconnected/ungated RN or a reset-gap), so the flop's UDP never leaves X and the X circulates through the increment logic forever

COUNTER STUCK AT X = A STATE FLOP THAT NEVER SAW RESET
Symptom

The gate-level counter powers up xxxx and stays xxxx — it never transitions to 0000 and never counts — even though a reset is being asserted on the design's reset port. The waveform is a flat line of X on count[3:0].

Root Cause

A state flop never saw reset, so its UDP (2.3) never left X — and because the flops feed the increment logic which feeds back to the flops (the ring), that X circulates forever: X + 1 = X. Reading the netlist with the chapter's lenses localises it. Spot the state flops (2.1): are they DFFRX1 — cells with an RN reset pin (2.2) — or did synthesis infer flops without reset (DFFX1, no RN) because the RTL's reset was mis-coded or optimised away (1.2/1.3)? If they have RN, is the design's rst_n actually connected to every flop's RN, or does the reset fan-out miss one (a broken net, a gating cell holding RN inactive)? Or is it a reset-gap (Chapter 0/1): reset is connected but never actually asserted in the stimulus window, so the flops are never forced. In each case the flop's UDP has no reason to leave X — its reset row (2.3) never fires — so it stays X, and the ring keeps every bit X. This is exactly the gate-level manifestation of the reset discipline from Chapters 0–1, now visible in the netlist: a DFFX1 with no RN, or an RN that never asserts, is a flop that cannot recover from power-up X. It is not a simulator bug; the model is correctly reporting that an un-reset state element is unknown.

Fix

Trace the reset in the netlist: confirm the state cells are reset flops (DFFRX1 with RN), confirm rst_n reaches every flop's RN (full fan-out, no missing/gated connection), and confirm the stimulus actually asserts reset for long enough to force the flops (closing any reset-gap, Ch0/1). Fix the source — restore the reset in RTL if synthesis dropped it (1.2/1.3), repair the broken reset net, or assert reset properly in the testbench. Once every state flop sees an asserted RN, its UDP reset row fires, the flops go 0000, the X clears from the ring, and the counter counts 0,1,2,3,… — the healthy signature of section 5. The capstone lesson: read a counter netlist as state flops (2.1, library cells 2.2, UDP models 2.3) + increment logic in a ring; the flops power up X and only reset clears it — so a counter stuck at X means a state flop never saw an asserted reset (no RN, broken fan-out, or reset-gap), the reset discipline of Chapters 0–1 read directly in the netlist. Scope note: this X behaviour is functional, zero-delay (no SDF) — it is a reset/X finding, not a timing one (timing comes in Chapter 3/4); do not conflate it with a timing proof (0.3/0.4).

7. Common Mistakes

  • Expecting a counter to count from cycle one. State flops power up X; only reset clears it — X until reset is the correct signature.
  • A 'clean count, no reset' run masking a bug. A pre-loaded testbench or two-state sim (1.4) can hide a missing reset the netlist would expose.
  • Not checking the reset reaches every flop. A missing/gated RN on one state cell keeps the whole ring X (X + 1 = X).
  • Confusing a DFFX1 (no reset) for a DFFRX1. Synthesis may infer un-reset flops if RTL reset was dropped (1.2/1.3) — read the cell's pins.
  • Reading the power-up X as a timing result. It is functional, zero-delay behaviour — timing (SDF) comes in Chapter 3/4 (0.3/0.4).

8. Industry Best Practices

  • Read a netlist as state + next-state logic. Find the flops (memory) and the combinational logic (math) first — the whole chapter hangs on that decomposition.
  • Verify reset fan-out to every state flop. Confirm rst_n reaches each RN, and that the stimulus asserts reset — the counter's X-to-0 depends on it.
  • Recognise the healthy signature. X at power-up → 0 on reset → clean count; treat a 'counts from cycle one, no reset' run as suspect.
  • Identify cells by their library type and pins. DFFRX1 (with RN) vs DFFX1 (none) — the pins tell you whether a flop can recover from X.
  • Keep the timing scope honest. Power-up X/reset is functional, zero-delay; timing arrives with SDF (Chapter 3/4) — do not read it as a timing proof.

Senior Engineer Thinking

  • Beginner: "The counter shows xxxx at the start — the netlist is broken."
  • Senior: "State flops power up X — that's correct. Does it clear on reset? If it stays X, a flop never saw an asserted RN: no reset pin (DFFX1?), broken fan-out, or a reset-gap. Let me trace rst_n to every flop's RN in the netlist."

The senior reads the counter as a ring of state + math, expects power-up X, and treats stuck-at-X as a reset question traced directly in the netlist.

Silicon Impact

This capstone reading skill is what catches the reset-gap escape before tape-out. A counter (or any state machine) whose flops never see an asserted reset powers up at a random value in silicon — intermittent freezes, wrong start states, downstream corruption — the exact failure the opening story described. Gate-level simulation shows this as stuck-at-X, but only if the run is read correctly: expecting power-up X, demanding it clear on reset, and tracing rst_n to every state flop's RN. A run that masks it (pre-loaded flops, two-state sim) hides a bug that silicon will find. Reading the netlist end-to-end — state flops (2.1) as library cells (2.2) with UDP models (2.3) that power up X until reset — turns a vague 'it works in sim' into a specific reset-coverage check. That is the difference between a counter that starts reliably on every power-up and one that occasionally comes up counting from garbage.

Engineering Checklist

  • Read the netlist as state flops + increment logic (2.1), cells identified as library instances (2.2).
  • Confirmed the state cells are reset flops (DFFRX1 with RN), not un-reset (DFFX1).
  • Verified rst_n fans out to every flop's RN and that the stimulus asserts reset.
  • Recognised the healthy signature (X at power-up → 0 on reset → clean count) and treated stuck-at-X as a reset question.
  • Kept scope honest: power-up X/reset is functional, zero-delay — timing (SDF) comes in Chapter 3/4 (not a timing proof).

Try Yourself

  1. Simulate the representative counter4 netlist with no reset asserted — observe count[3:0] sit at xxxx and never count (the X ring).
  2. Observe: the flops' UDP (2.3) never left X; X + 1 = X circulated forever.
  3. Change: assert rst_n = 0 for a couple of cycles at the start, then release it.
  4. Expect: xxxx0000 on reset → 0001, 0010, 0011, … — clean counting. Then delete the RN connection on one flop and re-run: that bit stays X and (via the increment logic) can poison the higher bits — the missing-reset bug, read in the netlist.

Any Verilog simulator runs this (cell models are the standard UDP/specify forms). Real library cells are vendor/PDK artifacts, but the anatomy, models, and power-up-X-until-reset behaviour are identical to the representative netlist. No paid tool is required.

Interview Perspective

  • Weak: "The counter netlist just counts — flops and some gates."
  • Good: "State flops hold the count, increment logic computes count+1; the flops power up X and count only after reset forces them to a known value."
  • Senior: "I read the netlist as a ring: state flops (library DFFRX1 cells whose UDP models GLS runs) plus increment logic. They power up X; only reset clears it. So a counter stuck at X is a reset problem — a flop with no RN, a broken reset fan-out, or a reset-gap — which I trace directly in the netlist. And I remember the power-up X is functional zero-delay behaviour; timing comes with SDF later, and GLS isn't a timing proof."

9. Interview / Review Questions

10. Key Takeaways

  • Read a synthesized counter netlist as state flip-flops (the DFFRX1 instances — memory) plus increment logic (XOR/AND/INV cells — count + 1) in a clocked ring, using all five lenses: anatomy (2.1), library cells (2.2), UDP models (2.3), specify arcs (2.4), timing checks (2.5).
  • Every cell is a standard-cell library instance whose Verilog model GLS runs (2.2/2.3) — so gate-level behaviour (including X) is governed by those models, not by abstract logic.
  • The correct power-up signature is X at power-up until reset, then counting: flops power up unknown (2.3), X circulates (X + 1 = X), reset forces 0, then 0,1,2,3,….
  • A counter stuck at X means a state flop never saw an asserted reset — no RN pin (DFFX1), broken reset fan-out, or a reset-gap — the reset discipline of Chapters 0–1 read directly in the netlist.
  • Scope stays honest: the netlist is representative (not exact tool output), and power-up X/reset is functional, zero-delay behaviour — not a timing proof (timing/SDF comes in Chapter 3/4). This closes Chapter 2; next, Chapter 3 gives these arcs real timing.

Quick Revision

Read a counter netlist = state flops + increment logic in a ring, via all five lenses (anatomy 2.1, cells 2.2, UDP models 2.3, arcs 2.4, checks 2.5). Every cell is a library instance whose model GLS runs. Signature: X at power-up → 0 on reset → count (X + 1 = X until reset). Stuck at X = a flop never saw an asserted reset (no RN, broken fan-out, or reset-gap — Ch0/1). Representative netlist; power-up X is functional zero-delay, not a timing proof. Chapter 2 complete; next: Chapter 3 — gate-level timing basics.