In short: In Verilog, wire models a continuously-driven net and reg simply names a variable that holds its value inside procedural blocks — the keyword choice is dictated by how a signal is assigned, not by whether the synthesized result is a flip-flop.
Few Verilog questions trip up newcomers — and interview candidates — as reliably as "what is the difference between reg and wire?" The naive answer, "reg is a register and wire is a wire," is both intuitive and wrong often enough to be dangerous. The real distinction lives in the language's assignment model, and understanding it clears up a surprising amount of confusion about what your RTL actually becomes in silicon after Synopsys Design Compiler or Cadence Genus gets hold of it.
Two assignment worlds, one language
Verilog has two fundamentally different ways to put a value onto a signal, and each demands a specific data-type family.
- Continuous assignment — the
assignstatement, or a module output port driven by a gate/instance. This models a permanent electrical connection: whenever any operand changes, the target updates. The target must be a net type, andwireis the net you will use 99% of the time. - Procedural assignment — anything inside an
alwaysorinitialblock. These blocks execute like software: statements run in order, values are stored, and the left-hand side must be able to hold a value between events. That storage is what avariabletype provides, and the classic variable isreg.
Key fact: You cannot drive a wire from inside an always block, and you cannot put a reg on the left of a bare assign. The compiler (Siemens Questa, Synopsys VCS, Cadence Xcelium) rejects both outright. This single legality rule explains 90% of real-world usage.
Why "reg" does not mean "register"
The name reg is a historical mistake that has confused students for three decades. It was chosen because procedural variables can model storage, but the keyword carries no synthesis semantics on its own. What matters is the assignment pattern inside the block:
- A
regassigned insidealways @(posedge clk)with a non-blocking<=synthesizes to a flip-flop — a real register. - The same
regassigned insidealways @(*)covering every input synthesizes to pure combinational logic — no storage element at all. - If that combinational block forgets a branch, the tool infers an unintended latch — still declared
reg, but now a bug.
So one declaration, reg [7:0] y;, can become a byte-wide register bank, an 8-bit adder's output wires, or eight transparent latches — depending entirely on surrounding code. Design Compiler reports this in its elaboration log; a line like Warning: inferred latch for 'y' is your cue that a combinational block is incomplete. This is exactly why experienced engineers read synthesis logs rather than trusting keyword intuition.
A side-by-side example
// wire + continuous assignment -> combinational net
wire [7:0] sum;
assign sum = a + b; // legal; sum is a net
// reg that becomes a FLIP-FLOP
reg [7:0] q;
always @(posedge clk)
q <= d; // sequential: real register
// reg that becomes COMBINATIONAL logic
reg [7:0] mux_out;
always @(*)
mux_out = sel ? a : b; // no storage; pure MUX
All three targets look structurally similar in the netlist viewer only after you inspect what the tool built. See our Verilog data types guide for the full taxonomy of nets and variables, and the blocking vs non-blocking assignment deep-dive for why <= versus = is the other half of this story.
Comparison at a glance
wire (net) | reg (variable) | |
|---|---|---|
| Legal assignment | assign, port/instance output | inside always / initial |
| Holds value? | No — reflects drivers live | Yes — retains until reassigned |
| Default value | z (high-impedance) | x (unknown) |
| Multiple drivers | Allowed (resolved, e.g. buses) | Not allowed from multiple blocks |
| Can be a module input | Yes | No (inputs are always nets) |
| Synthesizes to | Wires / comb logic | FF, latch, or comb logic |
Key fact: A module output can be declared output reg when it is driven procedurally, but a module input can never be reg — inputs are driven from outside, which is a continuous drive, so they are always nets.
The animated view: live net vs. stored value
q latches its value only when the edge arrives, while the input net tracks d at all times.SystemVerilog quietly fixed this
If the reg/wire split feels arbitrary, you are in good company — the IEEE committee thought so too. SystemVerilog (IEEE 1800) introduced logic, a single variable type that can be driven by one continuous or one procedural source. In modern flows you often write logic everywhere and let the tool enforce the single-driver rule. The classic reg/wire rules still matter, though: legacy IP, textbooks, and most entry-level interviews are pure Verilog-2001. Teams doing real tapeouts — such as the design engineers at Avecas VLSI design services — still read both idioms fluently because production codebases mix them for years.
Want to go from "I memorized the rule" to "I can read any netlist"? CourseTron's FPGA and RTL design track walks you through Verilog, SystemVerilog, and synthesis on real tools. Browse the courses →
Frequently asked questions
Is every reg synthesized into a flip-flop?
No. A reg becomes a flip-flop only when it is assigned under a clock edge (always @(posedge clk)). Assigned in a complete combinational block it becomes gates; assigned in an incomplete one it becomes an unwanted latch.
Can I use wire inside an always block?
You can read a wire inside an always block, but you cannot assign to one there. The left-hand side of a procedural assignment must be a variable (reg or logic).
Why is a module input never a reg?
An input is driven by whatever connects to it from the parent module — that is a continuous drive. Since only nets accept continuous drives, inputs are always nets (wire by default).
Should I just use logic and forget reg/wire?
In a SystemVerilog project, largely yes — logic is cleaner and the tools catch multi-driver mistakes. But you must still recognize reg/wire in legacy code and interviews, so learn both.