Verilog · Chapter 11.1 · Gate-Level Modeling
Predefined Gate Primitives in Verilog — and, or, not, xor & Tri-State Gates
Verilog ships with a set of built-in gate primitives, logic gates you can instantiate directly with no definition needed. They are the alphabet of gate-level structural modeling: the multi-input logic gates such as and, nand, or, nor, xor, and xnor, the buffers and inverters buf and not, and the tri-state gates that drive a high-impedance value under control. This lesson drills their syntax, including the terminal-ordering rule that the output comes first, the multi-input and multi-output forms, and the tri-state control behaviour, and how they wire together into structural circuits. You read gate primitives far more often than you write them, since synthesized netlists are made of them, so the goal here is fluency in recognizing and reasoning about gate-level structure rather than authoring functional RTL this way.
Foundation15 min readVerilogGate PrimitivesStructuralTri-StateNetlistRTL Design
Chapter 11 · Section 11.1 · Gate-Level Modeling
1. The Engineering Problem
Open a synthesized netlist and you see thousands of lines like `and U123 (n45, n12, n33);`. To read it — to follow how the gates connect, debug a gate-level simulation, or understand a library cell — you must know the gate primitives and the one rule that governs them:
Verilog's built-in gate primitives instantiate logic gates directly, with the output terminal first and inputs after. Reading gate-level structure means knowing the primitives and this terminal order.
This page teaches the primitives — the logic gates, buffers, and tri-state gates — and how they compose. It is the vocabulary for reading the netlist level.
2. Mental Model — Gates Instantiated Like Tiny Modules
3. Multi-Input Logic Gates
The core logic gates take any number of inputs and produce one output:
and (y, a, b); // y = a & b
and (y, a, b, c, d); // y = a & b & c & d (any number of inputs)
nand (y, a, b); // y = ~(a & b)
or (y, a, b); // y = a | b
nor (y, a, b); // y = ~(a | b)
xor (y, a, b); // y = a ^ b
xnor (y, a, b); // y = ~(a ^ b)- The first terminal is the output, the rest are inputs.
- They accept two or more inputs —
`and (y, a, b, c, d)`is a 5-input AND. The function extends naturally (AND of all inputs, OR of all inputs, XOR/parity of all inputs). - These are the structural equivalents of the bitwise operators (10.4) on scalars —
`and (y, a, b)`is the gate-level form of`assign y = a & b;`.
4. Buffers and Inverters
buf (buffer) and not (inverter) have one input but may drive multiple outputs — so their terminal order is reversed: outputs first, the single input last.
not (y, a); // y = ~a
buf (y, a); // y = a (drives/strengthens the signal)
not (y1, y2, a); // TWO outputs, one input: y1 = ~a, y2 = ~a
buf (z1, z2, z3, a); // three outputs, one input`not`inverts;`buf`passes through (used to drive a signal to multiple loads or strengthen it).- The last terminal is the single input; all earlier terminals are outputs. This is the inverse of the logic-gate convention — a frequent point of confusion.
- The multi-output form is a structural convenience (fan-out from one input).
5. Tri-State Gates
The tri-state gates drive their output or put it in high-impedance (z) based on a control input — the structural form of a tri-state driver (Chapter 5):
bufif1 (y, a, ctrl); // y = ctrl ? a : 1'bz (drive when ctrl=1)
bufif0 (y, a, ctrl); // y = ctrl ? 1'bz : a (drive when ctrl=0)
notif1 (y, a, ctrl); // y = ctrl ? ~a : 1'bz (inverting, drive when ctrl=1)
notif0 (y, a, ctrl); // y = ctrl ? 1'bz : ~a (inverting, drive when ctrl=0)- Terminals: output, input, control —
`bufif1 (out, in, ctrl)`. `bufif1`drives when control is 1, high-impedance otherwise;`bufif0`is the opposite polarity; the`notif`variants invert the data.- These build tri-state buses: multiple
`bufif`gates driving a shared net, one enabled at a time (the shared net is atri, Chapter 5.1.1). If two drive at once, the net contends.
6. Building Structural Circuits
Gate primitives compose into circuits by wiring their terminals through internal nets:
module mux2_gates (
input a, b, sel,
output y
);
wire nsel, a_path, b_path;
not (nsel, sel); // nsel = ~sel
and (a_path, a, nsel); // a when sel=0
and (b_path, b, sel); // b when sel=1
or (y, a_path, b_path); // combine
endmoduleThis 2:1 mux is four gate instances and three internal nets — the structural equivalent of `assign y = sel ? a : b;` (Chapter 13.2). Notice the verbosity: four lines and three named nets for what dataflow does in one line. That contrast is exactly why gate-level is reference, not authoring: you read this in a netlist, but you write the dataflow form.
Visual A — gate primitives wire into a structural circuit
7. Industry Perspective
- Netlists are gate primitives (or cells). A synthesized netlist instantiates standard-cell modules (or, for simple cases, gate primitives) wired by nets — reading it is reading gate-level structure.
- Tri-state gates model real bus drivers.
`bufif`structures model on-chip and off-chip tri-state buses, where multiple drivers share a net under enable control. - Hand gate-level is rare and deliberate. Engineers occasionally hand-instantiate a specific gate (a particular cell, a clock buffer, a tri-state driver) where they need exact control, but functional logic is written in dataflow/behavioural.
- Terminal order is a reading discipline. Knowing output-first for logic gates and output(s)-first/input-last for buffers is essential to correctly follow signal flow in a netlist.
8. Common Mistakes
- Misreading the output terminal as an input — the output is first for logic gates (§2/§3).
- Confusing buf/not terminal order — buffers/inverters put outputs first and the single input last (§4).
- Tri-state contention — two
`bufif`gates enabled onto one net at once contend (§5). - Hand-writing gate-level for functional logic — verbose and error-prone; use dataflow (§6).
- Expecting to define primitives — they are built in; no module definition (Ch 11 overview).
9. Debugging Lab
Two gate-primitive debug post-mortems
Pitfall 1 — output and input terminals swapped
module and_gate (input a, b, output y);
// Intent: y = a & b. But the terminals are in the wrong order.
and (a, y, b); // BUG: 'a' treated as output, 'y' as input
endmodule
// The first terminal of 'and' is the OUTPUT. Here 'a' is in the output
// position, so the gate drives 'a' (an input port!) from y & b — backwards
// and illegal (driving an input).A gate-level AND fails to compile (driving an input port) or, if the signals were internal, computes the wrong thing — the gate appears to drive the wrong net. The logic 'looks' like an AND of a and b.
Terminal order. For a logic-gate primitive, the FIRST terminal is the OUTPUT and the rest are inputs. Writing 'and (a, y, b)' puts 'a' in the output position, so the gate tries to drive 'a' from 'y & b' — backwards from the intended 'y = a & b', and illegal when 'a' is an input port.
The fix is to put the output terminal first: and (y, a, b).
module and_gate (input a, b, output y);
and (y, a, b); // output first: y = a & b
endmodule
// Output terminal first, inputs after. (For buf/not it is reversed:
// outputs first, the single input last.)Pitfall 2 — two tri-state drivers enabled at once
module bus_driver (
input a, b, en_a, en_b,
output y
);
// Intent: a or b drives the bus 'y', one at a time. But both enables
// can be high together.
bufif1 (y, a, en_a);
bufif1 (y, b, en_b); // both bufif1 drive 'y' when en_a & en_b
endmodule
// If en_a and en_b are both 1, both buffers drive 'y' at once. Where a and
// b disagree, the shared net contends and resolves to x.A tri-state bus shows x (unknown) values intermittently — specifically when two sources are enabled simultaneously and disagree. With one enable high at a time it works.
Tri-state contention. Two bufif1 gates drive the same net 'y'. When both controls (en_a, en_b) are high, both buffers drive at once; where their data disagree, the shared net (a tri) resolves to x. A tri-state bus requires that AT MOST ONE driver is enabled at any time — the enables must be mutually exclusive.
The fix is to guarantee one-at-a-time enables (e.g. drive them from a one-hot decoder, 13.2) so only one bufif drives the bus.
module bus_driver (
input a, b, sel,
output y
);
// Mutually-exclusive enables from a single select:
bufif1 (y, a, ~sel); // a drives when sel=0
bufif1 (y, b, sel); // b drives when sel=1
endmodule
// Exactly one buffer is enabled for any 'sel', so the bus never contends.10. Interview Q&A
11. Exercises
Exercise 1 — Read the gate
Give the function of each: (a) and (y, a, b, c); (b) nor (y, a, b); (c) not (z, x); (d) bufif0 (y, d, en); (e) xor (p, a, b, c).
Exercise 2 — Identify the output
For each instance, name the output terminal: (a) or (w, x, y, z); (b) buf (a, b); (c) not (m, n, p); (d) nand (q, r, s).
Exercise 3 — Build structurally
Write a gate-level (structural) half adder: sum = a ^ b, carry = a & b, using gate primitives.
Exercise 4 — Fix the gate-level bugs
Identify and fix each: (a) and (a, b, y) intending y = a & b; (b) not (a, y1, y2) intending two inverted outputs of one input.
12. Summary
Verilog's built-in gate primitives instantiate logic gates directly for structural (gate-level) modeling:
- Multi-input logic —
and,nand,or,nor,xor,xnor: output terminal first, then any number of inputs. - Buffers/inverters —
buf,not: output(s) first, single input last; can fan out to multiple outputs. - Tri-state —
bufif0/1,notif0/1: output, input, control; drive or high-impedance, for tri-state buses with mutually-exclusive enables.
The discipline this page instils:
- Output terminal first for logic gates (and outputs-first/input-last for buffers) — the key reading rule.
- One enable at a time on a tri-state bus — multiple drivers contend.
- Read gate-level, author dataflow — netlists are gate primitives; new RTL is not.
The next page adds timing: Chapter 11.2 Gate Delays covers the delay specifications you can put on gate primitives — rise, fall, and turn-off delays, the min:typ:max form, and why they are a simulation-only modeling tool.
Related Tutorials
- Gate-Level Modeling — Chapter 11 overview; the structural-modeling context for these primitives.
- Bitwise Operators — Chapter 10.4; the dataflow equivalents of the logic gates.
- wire and tri Nets — Chapter 5.1.1; the nets that wire gates and the tri-state bus.
- Dataflow Practical Examples — Chapter 13.2; the same circuits at the higher dataflow abstraction.