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
DFFRX1instances (one per bit) — the counter's memory. Read with 2.1 (cell instances, portsD/CK/Q/RN), recognised as 2.2 library cells, simulated via their 2.3 UDP (power upX, reset viaRN), 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, …) computingcount + 1— the adder/increment. Read with 2.1 (gates + nets), library cells (2.2), UDP/primitive models (2.3),specifyarcs (2.4). - Reset fan-out. The reset net (
RN) driven to every state flop — the thing that turns power-upXinto a known0. - Behaviour: flops power up
X(2.3) →Xripples through the increment logic → reset asserts → flops go0→ counter counts0,1,2,3,…. - Scope: representative netlist (not exact tool output); power-up
Xhere is functional, zero-delay (no SDF) — not a timing proof (0.3/0.4).
Here is the counter netlist, read structurally:
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):
// 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// 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-- 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:
// 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]));
endmoduleReading 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:
# 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 xxxx → 0000 (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)
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 RESETThe 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].
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.
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 —Xuntil 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
RNon one state cell keeps the whole ringX(X + 1 = X). - Confusing a
DFFX1(no reset) for aDFFRX1. Synthesis may infer un-reset flops if RTL reset was dropped (1.2/1.3) — read the cell's pins. - Reading the power-up
Xas 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_nreaches eachRN, and that the stimulus asserts reset — the counter'sX-to-0depends on it. - Recognise the healthy signature.
Xat power-up →0on reset → clean count; treat a 'counts from cycle one, no reset' run as suspect. - Identify cells by their library type and pins.
DFFRX1(withRN) vsDFFX1(none) — the pins tell you whether a flop can recover fromX. - 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
xxxxat the start — the netlist is broken." - Senior: "State flops power up
X— that's correct. Does it clear on reset? If it staysX, a flop never saw an assertedRN: no reset pin (DFFX1?), broken fan-out, or a reset-gap. Let me tracerst_nto every flop'sRNin 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 (
DFFRX1withRN), not un-reset (DFFX1). - Verified
rst_nfans out to every flop'sRNand that the stimulus asserts reset. - Recognised the healthy signature (
Xat power-up →0on reset → clean count) and treated stuck-at-Xas 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
- Simulate the representative
counter4netlist with no reset asserted — observecount[3:0]sit atxxxxand never count (theXring). - Observe: the flops' UDP (2.3) never left
X;X + 1 = Xcirculated forever. - Change: assert
rst_n = 0for a couple of cycles at the start, then release it. - Expect:
xxxx→0000on reset →0001, 0010, 0011, …— clean counting. Then delete theRNconnection on one flop and re-run: that bit staysXand (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
Xand count only after reset forces them to a known value." - Senior: "I read the netlist as a ring: state flops (library
DFFRX1cells whose UDP models GLS runs) plus increment logic. They power upX; only reset clears it. So a counter stuck atXis a reset problem — a flop with noRN, a broken reset fan-out, or a reset-gap — which I trace directly in the netlist. And I remember the power-upXis 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
DFFRX1instances — memory) plus increment logic (XOR/AND/INVcells —count + 1) in a clocked ring, using all five lenses: anatomy (2.1), library cells (2.2), UDP models (2.3),specifyarcs (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
Xat power-up until reset, then counting: flops power up unknown (2.3),Xcirculates (X + 1 = X), reset forces0, then0,1,2,3,…. - A counter stuck at
Xmeans a state flop never saw an asserted reset — noRNpin (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:
Xat power-up →0on reset → count (X + 1 = Xuntil reset). Stuck atX= a flop never saw an asserted reset (noRN, broken fan-out, or reset-gap — Ch0/1). Representative netlist; power-upXis functional zero-delay, not a timing proof. Chapter 2 complete; next: Chapter 3 — gate-level timing basics.