Verilog · Chapter 5.1.3 · Data & Variables
Wired Nets in Verilog (wand and wor)
Verilog's wire and tri resolution returns X whenever two drivers fight with conflicting values. That is a useful default, but a wrong electrical model for several real bus families. TTL open-collector buses, ECL open-emitter buses, and every distributed-AND or distributed-OR pattern from the discrete-logic era share one property: multiple drivers do not fight, their values combine through a logic function, AND for open-collector and OR for open-emitter, and the combined value is what the bus carries. The wand and wor net types are Verilog's built-in model for those buses. Instead of contention-aware resolution, they run the driver values through a logic AND or OR before producing the final net value. The mechanism is precise and the use cases are narrow, and the synthesis story decides whether you reach for these in modern RTL.
Foundation20 min readVerilogwandworWired LogicOpen-Drain
Chapter 5 · Section 5.1.3 · Data & Variables
1. The Engineering Problem
A digital-design intern is tasked with modelling an open-collector interrupt bus. Eight peripherals share one line; any peripheral pulling the line LOW indicates "I want service." When all peripherals release, an external pull-up resistor holds the line HIGH. The straightforward translation to Verilog:
wire irq_n;
assign irq_n = ~req_0;
assign irq_n = ~req_1;
// ... eight times
assign irq_n = ~req_7;The simulation runs. The waveform shows irq_n = X whenever more than one peripheral asserts. Lint warns about multi-driver contention on every cycle. The model is "working" — every cycle has a definite answer — but the answer is wrong. The intent was "any peripheral pulling LOW wins, and the bus shows the AND of all driver values." The model is producing contention X because wire resolution has no rule for "two 0s plus a 1 resolve to 0."
The fix is the language's wand net type:
wand irq_n;
assign irq_n = ~req_0;
assign irq_n = ~req_1;
// ...
assign irq_n = ~req_7;Same eight drivers, same eight assign statements — but now the net is wand, and the resolution function is logic AND. The bus value is 0 if any driver is 0; it's 1 only when every driver is 1. The model now matches the open-collector electrical behaviour, the simulator stops returning X on every multi-active cycle, and lint accepts the multi-driver pattern as legitimate. One keyword changed; the entire bus semantic changed with it.
This page is about that one keyword (and its OR-resolving sibling wor), the resolution rules they implement, the bus families they model, and the synthesizability story that determines whether you'll ever write wand or wor in shipping RTL.
2. Why Wired Nets Exist
Pre-CMOS bus families relied on distributed logic at the bus layer. The two big examples:
- TTL open-collector (DM74xx and equivalents, 1970s through 1990s). The output stage of every driver on the bus is a single NPN transistor with the collector tied to the bus and the emitter to ground. When a driver wants to assert, it turns the transistor ON and pulls the bus LOW. When it wants to release, it turns the transistor OFF and lets the bus float. An external pull-up resistor holds the bus HIGH when no driver is asserting. The bus carries the AND of all driver values: any single driver pulling LOW dominates; only when every driver releases does the bus rise. This is the wired-AND topology.
- ECL open-emitter (10K and 100K series, 1970s through 1990s). Symmetric to TTL open-collector but with the polarity flipped. The output stage is a single NPN transistor with the emitter tied to the bus and the collector to supply. When a driver asserts, it pulls the bus HIGH. The bus carries the OR of all driver values: any single driver asserting HIGH dominates; only when every driver releases does the bus fall. This is the wired-OR topology.
Both topologies were the bus discipline for whole generations of board-level systems — backplane interrupts, error reporting, distributed status registers, DRAM error-correction signal aggregation. The Verilog language's wand and wor keywords were added in the original 1985 spec specifically to model these buses without forcing every author to manually write the logic function in the resolution path.
Modern CMOS bus families do not use distributed logic at the bus layer — every shared net is either point-to-point (single driver) or tri-state (mutex-enforced multi-driver). The wired-AND and wired-OR patterns survive only in two narrow contexts:
- Legacy IP modelling — a Verilog model of an old TTL or ECL board may declare its bus net as
wandto preserve the original semantics. Without the keyword, the model producesX-soup whenever two drivers are active simultaneously. - External pull-up modelling on shared buses — the
wandkeyword is sometimes used to express "this bus is open-drain at the pad layer; the resolution function should AND the drivers." The 5.1.2signal-strengthspage covers the more general strength-aware approach to the same problem;wandis the simpler, narrower idiom.
The language keeps the keywords for backward compatibility and as a clean modelling primitive for the rare case that warrants them. In shipping RTL written this decade, you will almost never see them.
3. Mental Model
The mental-model has three consequences a working engineer carries:
- No contention.
wandandwornever returnXfrom conflicting values, because the resolution function does not consider the values as conflicting — it always returns a defined logic combination. - Z-tolerance. When a driver outputs
Zon awandnet, that driver contributes the identity of the AND function — namely1. (The bus floats, the pull-up wins, all drivers released →1.) Symmetrically, aZdriver on aworcontributes0. TheZvalue is treated as "this driver is not active" — not as "this driver is in a bad state." X-pessimism. When any driver outputsXon awandnet, the resolution returnsX(becauseXcould be either0or1, and the AND result depends on it). Same onwor.Xpropagates pessimistically — wired logic does not magically rescue an upstreamX.
The keyword choice is declarative. You are telling the simulator: "this net's drivers should be combined by AND" (or OR). You are not telling the synthesis tool how to build the bus — the synthesis tool may reject the net type entirely (§14), so the keyword's effect is at simulation time only.
4. The Resolution Functions
The IEEE 1364-2005 §6.1.3 truth tables for wand and wor are short but exact. They specify the resolved net value as a function of the two-driver inputs; multi-driver nets are resolved pairwise (the resolution function is associative).
4.1 wand resolution table
| Driver A | Driver B | Resolved net | Note |
|---|---|---|---|
0 | 0 | 0 | identity: 0 ∧ 0 = 0 |
0 | 1 | 0 | 0 dominates AND |
0 | Z | 0 | Z = identity (1); 0 ∧ 1 = 0 |
0 | X | 0 | X masked by 0 — any X-value ANDed with 0 is 0 |
1 | 0 | 0 | symmetric |
1 | 1 | 1 | identity: 1 ∧ 1 = 1 |
1 | Z | 1 | Z = identity (1); 1 ∧ 1 = 1 |
1 | X | X | X could be 0 or 1; AND could be 0 or 1 |
Z | Z | 1 | both released; pull-up wins |
Z | X | X | X dominates Z (X could be 0) |
X | X | X | both unknown |
The pattern reduces to three rules a working engineer carries by reflex:
- Any
0driver pulls the bus to0, regardless of what every other driver outputs. Zis treated as1(released → bus floats high → reads as1).Xpoisons the result only when all non-Xdrivers are1(because then theXis the variable that decides the outcome). If any other driver is0, the0wins and theXis masked.
4.2 wor resolution table
| Driver A | Driver B | Resolved net | Note |
|---|---|---|---|
0 | 0 | 0 | identity: 0 ∨ 0 = 0 |
0 | 1 | 1 | 1 dominates OR |
0 | Z | 0 | Z = identity (0); 0 ∨ 0 = 0 |
0 | X | X | X could decide; depends on value |
1 | 0 | 1 | symmetric |
1 | 1 | 1 | identity: 1 ∨ 1 = 1 |
1 | Z | 1 | 1 ∨ 0 = 1 |
1 | X | 1 | 1 ∨ anything = 1 (X masked by 1) |
Z | Z | 0 | both released; pull-down wins |
Z | X | X | X dominates Z |
X | X | X | both unknown |
The mirror-image rules:
- Any
1driver pulls the bus to1, regardless of every other driver. Zis treated as0(released → bus floats low → reads as0).Xpoisons the result only when all non-Xdrivers are0(because then theXdecides). Any1driver masks theX.
4.3 triand and trior
The language also defines triand and trior — direct synonyms for wand and wor with identical resolution rules. The tri- prefix mirrors the tri / wire pair: same semantics, different keyword to document multi-driver intent for tools that distinguish them.
In practice, lint and reviewer tools treat triand / trior the same as wand / wor. Use the shorter form. The four keywords exist for historical symmetry, not as a semantic distinction.
5. Syntax
The declaration grammar mirrors wire / tri exactly. Every modifier legal on those is legal here.
`default_nettype none
// <wand | wor | triand | trior> [signed] [strength] [range] name [= continuous-assign];
wand irq_n; // scalar wired-AND
wand [3:0] status_irq_n; // 4-bit wired-AND vector
wand signed [7:0] s_wand; // signed wired-AND (rare)
wand (pull1, strong0) pulled_irq_n; // strength specifier (rare)
wor common_error; // scalar wired-OR
wor [7:0] err_bus; // 8-bit wired-OR vector
triand legacy_irq_n; // synonym for wand
trior legacy_err; // synonym for wor
// Continuous-assign shorthand — same as `wire`
wand busy_b = mod_busy[0]; // declaration + first driverThree patterns the syntax forces on any working code:
- Net type is per-net. You declare the type once; every continuous driver of that net then participates in the wired-logic resolution. There is no way to mark an individual driver as "AND-only" or "OR-only" — the rule comes from the net's declaration.
- Width must match across drivers. A 4-bit
wandresolves bit-by-bit: each bit of the net runs its own resolution function over the corresponding bits of all drivers. Bit 0 of the resolved net = bit 0 of driver A AND bit 0 of driver B AND ... A driver narrower than the net is zero-extended (which on awandwould force the upper bits to0from that driver — usually a bug). - Strength specifiers compose with wired logic. A
wandwith onepull1driver and severalstrong0drivers behaves correctly: the AND function determines the value (0if anystrong0is active), and the strength is set by the strongest contributing driver. The strength axis from the 5.1.2 sub-page does not go away — it still ranks drivers for the value-selection.
5.1 Implicit type — there is none
Unlike wire (which is the implicit default for undeclared identifiers), wand and wor must always be explicitly declared. There is no compiler directive that makes a track default to wired logic — every wired-net declaration is a one-keyword choice the author makes at the point of declaration.
`default_nettype accepts wand or wor as its argument, which changes the implicit type for any undeclared identifier in that file. This is a rare-but-real pattern in legacy backplane models: `default_nettype wand at the top of a file declares that every otherwise-undeclared net in this file is a wired-AND. Use it only if every net in the file genuinely is one — which is rare; the right default for new code is `default_nettype none.
6. Visual Explanation
Three figures cover the wired-logic topology.
6.1 Visual A — wired-AND with pull-up
The canonical TTL open-collector / I²C topology. Multiple drivers, all NMOS pull-downs; one external pull-up resistor. The bus is the AND of all driver outputs.
Wired-AND topology (open-collector)
data flow6.2 Visual B — wired-OR with pull-down
The mirror-image ECL open-emitter topology. Drivers are PMOS / NPN pull-ups; external pull-down to ground. The bus is the OR of all driver outputs.
6.3 Visual C — wand vs wire on the same multi-driver pattern
The keyword choice is the entire difference. Same three drivers, same three values; declared as wire, the result is X on every conflicting cycle; declared as wand, the result is the AND.
7. Open-Collector IRQ Bus (Wired-AND)
The canonical use case. Multiple peripherals share one active-low interrupt line; any peripheral asserting 0 claims the line.
`default_nettype none
module wired_irq_bus (
input wire clk,
input wire rst_n,
input wire [3:0] periph_assert, // per-peripheral active-high request
output wand irq_n // wired-AND bus, active LOW
);
// Each peripheral drives 0 when it wants service; releases (Z) otherwise.
// The pull-up resistor at the board level is modelled implicitly by the
// wand resolution rule (Z contributes the AND identity, which is 1).
assign irq_n = periph_assert[0] ? 1'b0 : 1'bz;
assign irq_n = periph_assert[1] ? 1'b0 : 1'bz;
assign irq_n = periph_assert[2] ? 1'b0 : 1'bz;
assign irq_n = periph_assert[3] ? 1'b0 : 1'bz;
endmoduleWalk the resolution function for the three interesting states:
- No peripheral active. All four drivers output
Z. Thewandrule treats eachZas1for AND purposes. Result:1 ∧ 1 ∧ 1 ∧ 1 = 1. The line is HIGH — the de-asserted state of an active-low IRQ. - One peripheral active. Three drivers output
Z(identity1); one driver outputs0. Result:0 ∧ 1 ∧ 1 ∧ 1 = 0. The line goes LOW — IRQ asserted. - Two peripherals active. Two drivers output
0; two outputZ. Result:0 ∧ 0 ∧ 1 ∧ 1 = 0. Still LOW — exactly the wired-AND semantic: any number of0s combines to0.
The contrast with a wire-typed model is sharp: replace wand with wire, and the two-peripherals-active state resolves to 0 ∧ 0 = 0 for the value half, but the resolution function of wire doesn't compute the AND — it asks "are these conflicting?" Two 0s and two Zs on a wire actually resolves correctly to 0 (because Z loses to any non-Z and 0 ∧ 0 = 0). The interesting failure is when one peripheral is wrongly outputting 1 instead of Z: a wand resolves the 1 as a non-asserting contribution; a wire sees 1 vs 0 and returns X. The wand is more forgiving of legacy code that uses 1-vs-0 instead of Z-vs-0 to encode "released" vs "asserting."
8. Distributed-OR Error Bus (Wired-OR)
The symmetric ECL-style example. Multiple status modules report errors on a shared bus; the bus carries the OR of all reports.
`default_nettype none
module wired_error_bus (
input wire clk,
input wire rst_n,
input wire [7:0] module_error, // per-module error flag
output wor system_error // wired-OR bus, active HIGH
);
// Each module drives 1 when it has an error to report; releases (Z) otherwise.
// The pull-down resistor at the board level is modelled implicitly by the
// wor resolution rule (Z contributes the OR identity, which is 0).
assign system_error = module_error[0] ? 1'b1 : 1'bz;
assign system_error = module_error[1] ? 1'b1 : 1'bz;
assign system_error = module_error[2] ? 1'b1 : 1'bz;
assign system_error = module_error[3] ? 1'b1 : 1'bz;
assign system_error = module_error[4] ? 1'b1 : 1'bz;
assign system_error = module_error[5] ? 1'b1 : 1'bz;
assign system_error = module_error[6] ? 1'b1 : 1'bz;
assign system_error = module_error[7] ? 1'b1 : 1'bz;
endmoduleWalk the same three states:
- No module asserting. All eight drivers output
Z. OR identity is0. Result:0. The system reports "no error." - One module asserting. One driver outputs
1; seven outputZ. Result:1 ∨ 0 ∨ ... = 1. The system reports "error." - Multiple modules asserting. Any number of
1s combines to1. The bus carries "at least one module has an error" without identifying which — exactly the wired-OR aggregation semantic.
The pattern is the obvious one for any "summary status" signal — system-level interrupt aggregation, ECC error roll-up, fault-tolerance signalling. In modern RTL the equivalent is an explicit reduction OR: assign system_error = |module_error;. The wor form expresses the bus topology (multiple distributed drivers) where the explicit OR expresses the logical function; they produce the same result but model different physical realities.
9. Multi-Bit Wired Bus
Wired nets resolve bit-by-bit. A 4-bit wand has four independent resolution functions running in parallel — one per bit position. The interesting case is what happens when two drivers carry different widths.
`default_nettype none
module multibit_wand (
input wire [3:0] drv_a,
input wire [3:0] drv_b,
input wire a_active,
input wire b_active,
output wand [3:0] bus_q
);
// Each driver outputs its 4-bit value when active, all-Z when released.
assign bus_q = a_active ? drv_a : 4'bz;
assign bus_q = b_active ? drv_b : 4'bz;
endmoduleThe four bits of bus_q resolve independently. For bus_q[2]: take bit 2 of every active driver and AND them together (treating Z as 1). The bit-parallel resolution means a 4-bit wand is precisely four scalar wands in parallel — no surprises, no cross-bit interactions.
Width-mismatch edge case: if you drive a 4-bit wand with a 2-bit value (bus_q = 2'b10;), the simulator zero-extends to 4 bits. For a wand, the upper bits get 0 from this driver — which forces the AND result for the upper bits to 0, regardless of what other drivers contribute. Almost always a bug; lint will warn on the width mismatch.
For wor the symmetric edge case: zero-extension contributes 0 to the upper bits, but wor treats absent drivers as 0 (identity), so the zero-extension is "free" in the sense that it doesn't force the upper bits to a wrong value — but it does suppress the contribution from this driver on the upper bits, which can hide a missing driver bug elsewhere.
10. Simulation Behavior
The simulator runs the wired-logic resolution function whenever any driver of a wand or wor net changes value or strength. The internal data structures track every driver's (value, strength1, strength0) triple, exactly as for wire / tri — the only difference is the resolution function itself.
The resolution function operates per-bit for vector nets and runs on every event in the Active region of the IEEE 1364-2005 stratified scheduler. This means wired-logic resolution behaves like combinational logic: a glitch on one driver propagates through the resolution function in the same time slot, no #0 delay required.
The simulator output for a wand or wor net is identical in format to a wire — 0, 1, Z, or X per bit. The wired-logic semantic is invisible in the dump; only the resolved value changes. If you're debugging a wand net and seeing X, the question is which driver is producing the X that the AND function is forwarding — not whether the resolution function is misbehaving.
11. Waveform Analysis
Two waveforms cover the wired-logic resolution patterns.
11.1 Waveform #1 — wired-AND IRQ bus
Open-collector IRQ — three peripherals on one wand bus
12 cyclesThe interesting cycles are the transitions. From cycle 1 to cycle 2, P0 asserts (drives 0); the resolution function reruns, evaluating 0 ∧ Z ∧ Z = 0 ∧ 1 ∧ 1 = 0. The bus falls. From cycle 7 to cycle 8, P1 joins P0 — now two 0 drivers and one Z. The result is the same: 0. The wired-AND function is monotonic in 0-count: once any driver asserts 0, adding more 0-drivers doesn't change the answer.
What's invisible on the waveform but real in the simulator: the strength of irq_n changes between asserted and released cycles. While a peripheral is driving 0, the strength is strong0. When all release, the strength falls to the implicit pull-up strength (whatever the wand was declared with — strong1 by default, or pull1 if the declaration specified it).
11.2 Waveform #2 — wired-OR error bus
Open-emitter error bus — four modules on one wor bus
12 cyclesThe wired-OR pattern is the working-engineer's go-to for status aggregation. Notice that the bus does not say which module asserted — only that some module did. This is intentional: the bus topology was originally chosen on physical hardware specifically because adding more reporting modules required no change to the bus structure (drop another open-emitter driver on the same line; the existing nodes don't even know). In RTL, the explicit reduction-OR |err_bus produces the same result with cleaner semantics; the wor form is preferred only when the bus is the actual physical-layer construct being modelled.
12. Synthesis Insight
Wired nets are rejected by most modern synthesis tools when used in internal hierarchy.
Synthesis tools have to map every net to physical interconnect. For a wire with a single driver, that's trivial — a piece of metal connecting the driver to the consumer. For a wand or wor with multiple drivers, the tool would need either:
- A library cell that implements the wired logic natively. On modern ASIC standard-cell libraries, no such cell exists at the internal-hierarchy layer. The closest equivalent is an explicit
ANDorORgate from the standard cell library — which is what the tool may infer, but only if the language and the constraints allow it. - A multi-driver internal net. Same problem as internal tri-state (5.1.1) — no library cell supports it, so the tool rewrites to a mux or a wide AND/OR.
The practical outcome varies by tool:
- Synopsys Design Compiler and Cadence Genus typically reject
wand/worin synthesisable RTL with an explicit error. The error message names the construct and points the engineer to write an explicit AND/OR mux instead. - Xilinx Vivado and Intel Quartus historically allowed
wand/worat the top-level port boundary (where the pad cell carries the open-drain electrical behaviour) but rewrite internal occurrences to explicit AND/OR logic. The synthesis log lists the rewrite as a warning. - Verilator and most open-source simulators do not synthesise (they're simulators), but Yosys (the open-source synthesis tool) rejects
wand/worsimilarly to commercial flows.
The unanimous direction across tools: do not use wand or wor in internal synthesisable RTL. Use them only in:
- Testbench code modelling external buses with electrical wired logic.
- Top-level
inoutports of modules wrapping bidirectional chip pads that carry open-drain or open-emitter pads. - Legacy IP preserved unmodified for back-compatibility; new work moves to explicit logic.
The replacement idiom is straightforward:
// Original wand pattern:
wand irq_n;
assign irq_n = periph_assert[0] ? 1'b0 : 1'bz;
assign irq_n = periph_assert[1] ? 1'b0 : 1'bz;
// Synthesizable rewrite — explicit reduction AND of the inverted-assert signals:
wire [1:0] periph_release = ~periph_assert;
assign irq_n = &periph_release;
// Equivalently: assign irq_n = ~|periph_assert;The rewrite produces the same simulation behaviour, synthesises cleanly to a NOR-reduction tree, and reads as a single intent ("the line is low if any peripheral asserts") instead of distributed drivers. Reviewer-friendly, synthesis-friendly.
13. Industry Use Cases
The three places wand / wor actually show up in modern engineering work:
13.1 Legacy backplane RTL
Pre-2000s ASIC and board designs used wired logic at the backplane layer extensively — VME bus interrupt aggregation, PCI INTx open-drain lines, ISA IRQ summary, DRAM error-correction status roll-up. Verilog RTL written in that era declares these buses as wand or wor. Maintenance work on the IP preserves the keywords; greenfield work uses explicit logic.
13.2 Verification BFM for external bus families
A testbench modelling an external open-drain bus (I²C, OneWire, JTAG TDO with multiple devices, classic ECL backplanes) can declare the bus as wand (or wor) to express the resolution semantics directly. The alternative — explicit (pull1, highz0) strength specifiers on a plain wire — is the 5.1.2 sub-page's approach. Both are correct; wand is shorter when the strength axis isn't needed.
13.3 Open-drain top-level chip pads
A top-level inout port carrying an open-drain signal (e.g. an I²C SDA / SCL pin) can be declared wand on the chip-level wrapper module. The synthesis tool understands the pad-cell's electrical behaviour at the I/O ring layer; the wand declaration tells the simulator how to resolve the multi-driver state across the bonded peripherals during system-level simulation.
In each case, the keyword is doing a modelling job, not generating a circuit topology. The actual silicon comes from explicit pad-cell instantiation, explicit AND/OR logic, or external resistors — none of which the wand / wor keywords themselves produce.
14. Common Mistakes
Five pitfalls that catch engineers reading or writing wired-net code.
14.1 Mixing wand and wire on the same conceptual bus
The most common mistake. An engineer declares wand irq_n; at the bus level but then drives it with assign irq_n = oe ? data : 1'b1; — using 1'b1 for "released" instead of 1'bz. The 1 driver looks like an active contributor to the AND function, which suppresses any 0 from another driver and keeps the bus stuck at 1. The fix is 1'bz (release): the wand rule treats Z as the AND identity and lets the other drivers determine the result.
14.2 Using wand for a tri-state mux
A multi-driver tri-state mux pattern needs tri — the keyword that documents "intentional multi-driver with mutex contract" (5.1.1). Using wand instead changes the resolution semantic: a multi-driver wand resolves by AND, not by mutex. If the mux's drivers happen to carry 0 and 1 on the same cycle (e.g. for two selectors that overlap), the wand result is 0 — silently — instead of the X that a wire or tri would produce. The bug ships invisibly.
14.3 Writing wand/wor in synthesisable internal RTL
Synthesis tools either reject these net types in internal hierarchy or silently rewrite them as explicit AND/OR logic. The rewrite breaks the multi-driver shape — internal nets become single-driver point-to-point — and may diverge from the RTL simulation in subtle ways. Use wand / wor only in testbenches and at top-level pad-boundary ports.
14.4 Confusing wand with a logic AND gate
wand is a net type, not a gate. The resolution function happens at the bus layer, between the drivers; an actual and gate is a separate primitive. The two have different syntax (wand irq_n; declares a net; and u_and (out, a, b); instantiates a gate) and different semantics (a wand net is multi-driver; an and gate has a single output driver from its primitive).
14.5 Forgetting the per-bit resolution on vectors
A 4-bit wand resolves bit-by-bit. Each bit position has its own independent AND function over the corresponding bits of all drivers. Trying to reason about a 4-bit wand as if the entire 4-bit value were one quantity ("the bus carries the AND of 4'b1010 and 4'b0110") leads to confusion — the bus carries 4'b0010 because each bit ANDs independently. The bit-wise reading is correct; the as-an-integer reading is not.
15. Debugging Lab
Three wired-net debug post-mortems
16. Coding Guidelines
- Use
wand/woronly when the bus topology is genuinely wired-logic. Open-collector pad lines, ECL open-emitter, legacy backplane interrupts. Not as a general-purpose distributed-logic primitive. - Every wired-net driver outputs the asserting value or
Z. Use1'bzfor "released," not1'b1(on awand) or1'b0(on awor). Consistent driver semantics make the resolution behaviour predictable. - Internal synthesisable RTL uses explicit AND/OR, not
wand/wor. Synthesis tools either reject the net types or rewrite them — the rewrite breaks the multi-driver shape. Skip the keyword entirely; write the explicit reduction-AND or reduction-OR. - Reserve
wand/worfor testbench BFMs and top-level pad-boundary ports. These are the only contexts where the wired-logic semantic survives end-to-end without the synthesis tool intervening. - Don't mix
wand/worwithtrion the same net. They are distinct net types with distinct resolution rules; one wins (the declared type) and the other's intent is lost. If you need both wired-logic semantics and tri-state intent documentation, thewandkeyword wins — it documents both multi-driver intent (lint) and wired-AND resolution (simulator). - Vector wired nets resolve per-bit. A 4-bit
wandis four scalarwands in parallel. Don't reason about the vector as a single quantity; reason bit by bit. - Document the resolution intent. A one-line comment naming the bus type ("open-collector IRQ bus, wired-AND resolution per VME spec §2.4") tells the next engineer the keyword choice is intentional, not a typo for
wire. - Avoid
triandandtriorin new code. They are synonyms forwand/wor; modern style picks one form (wand/wor) for consistency.
17. Interview Q&A
18. Exercises
Three exercises that turn the wired-logic model into reflex.
Exercise 1 — Resolve the bus
For each of the following two-driver scenarios on a wand and on a wor of the same drivers, predict the resolved bus value.
| # | Driver A | Driver B | wand result | wor result |
|---|---|---|---|---|
| 1 | 0 | 1 | ? | ? |
| 2 | Z | 1 | ? | ? |
| 3 | Z | Z | ? | ? |
| 4 | 0 | X | ? | ? |
| 5 | 1 | X | ? | ? |
| 6 | Z | 0 | ? | ? |
| 7 | Z | X | ? | ? |
Hints. Look up §4.1 and §4.2 truth tables. Remember: Z is the AND identity (1) on a wand and the OR identity (0) on a wor.
Exercise 2 — Model a 4-device JTAG TDO bus
Write a synthesisable Verilog testbench module jtag_tdo_model that models a 4-device JTAG TDO bus. Each device drives the bus when selected; only one device is selected at a time. The bus is an open-drain line — declare it as wand. Inputs:
wire [3:0] device_selected— one-hot.wire [3:0] device_tdo— TDO bit from each device.
Output:
wand tdo_bus— the resolved TDO line.
Hints. Four assign statements; each device drives device_tdo[i] when device_selected[i] is HIGH, 1'bz otherwise. The wand resolution rule treats unselected devices' Z as 1, and the selected device's value (0 or 1) dominates the AND of value ∧ 1 ∧ 1 ∧ 1 = value.
Exercise 3 — Rewrite for synthesis
The following module compiles and simulates correctly but is rejected by Design Compiler. Identify why, and rewrite it using explicit logic so the synthesis tool accepts it.
module distributed_done (
input wire clk,
input wire rst_n,
input wire [3:0] agent_done,
output wand all_done
);
assign all_done = agent_done[0] ? 1'b1 : 1'bz;
assign all_done = agent_done[1] ? 1'b1 : 1'bz;
assign all_done = agent_done[2] ? 1'b1 : 1'bz;
assign all_done = agent_done[3] ? 1'b1 : 1'bz;
endmoduleWhat to produce. (a) Name the synthesis issue — what does Design Compiler object to? (b) Rewrite the module using a plain wire and explicit reduction logic that produces the same behaviour. (c) Identify a subtle behavioural difference between the wand version and the rewrite when some agent_done[i] is X.
19. Summary
Wired nets (wand, wor, and their triand / trior synonyms) are Verilog's built-in primitives for modelling distributed-logic buses — TTL open-collector, ECL open-emitter, and any topology where multiple drivers combine through logic AND or OR rather than through contention.
The mechanism is precise:
wandresolves by AND. Any driver outputting0pulls the bus to0;Zis treated as the AND identity (1);Xpoisons only when no0driver is present.worresolves by OR. Any driver outputting1pulls the bus to1;Zis treated as the OR identity (0);Xpoisons only when no1driver is present.triandandtriorare exact synonyms; modern code prefers the shorter form.
The use cases are narrow:
- Legacy bus modelling — VME, PCI INTx, ECL backplane.
- Top-level chip-pad open-drain / open-emitter ports.
- Testbench BFMs modelling external buses with wired-logic electrical behaviour.
The synthesis story is the reason wand / wor are rare in modern RTL: synthesis tools either reject them at internal-hierarchy nets or silently rewrite them as explicit AND/OR logic. Internal synthesisable RTL uses plain wire with explicit reduction-AND or reduction-OR; the wired-net keywords are reserved for non-synthesised contexts.
The day-to-day discipline:
- Match the keyword to the bus topology. Open-collector →
wand; open-emitter →wor; mutex-protected multi-driver →tri(5.1.1); single-driver →wire. - Drivers output
Zfor "released." Using1for released on awand(or0for released on awor) breaks the model's symmetry; the resolution function happens to produce the right answer most of the time, but the keyword loses its intent. - No
wand/worin internal synthesisable RTL. Either rewrite as explicit reduction logic, or keep the wired-net declaration at the top-level pad boundary only. - Document the bus type. A one-line comment naming the protocol or topology distinguishes intentional wired-logic use from typos for
wire.
The sibling sub-pages: 5.1.4 trireg Nets covers capacitive charge storage; 5.1.5 tri0 / tri1 Nets covers the implicit pull drivers; 5.1.6 supply0 / supply1 covers the supply strength rail ties.
Related Tutorials
- wire and tri Nets — Chapter 5.1.1; the contention-aware resolution function this page contrasts with.
- Signal Strengths — Chapter 5.1.2; the orthogonal strength axis that also rides on these resolution functions.
- Physical Data Types — Chapter 5.1; the parent overview of the net family.
- Variables & Data Types — Chapter 5; nets and variables together.
- Operator Usage — Chapter 4.3; the reduction-AND (
&) and reduction-OR (|) operators used in the synthesisable rewrite.