Verilog & SystemVerilog DISCUSSION

Verilog reg versus wire, and SystemVerilog logic: which type do I declare for a signal?

Started by sherhasankhan Verilog reg and wireSystemVerilog logicnets and variablescontinuous assignmentmultiple drivers
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Verilog reg versus wire, and SystemVerilog logic: which type do I declare for a signal?

sherhasankhan Verilog & SystemVerilog Forum
#1

The compiler keeps correcting my declarations. Assigning a wire inside an always block is an error, using assign on a reg is an error, and connecting a reg to the output port of an instantiated module is an error as well. Meanwhile a signal declared reg and assigned in always @* synthesises to plain gates with no register anywhere.

What do reg and wire actually mean, how do I know which one a signal needs, and does SystemVerilog's logic make the distinction go away?

Community replies 5

Re: Verilog reg versus wire, and SystemVerilog logic: which type do I declare for a signal?

#2

The two keywords describe how a signal gets its value in the language, not what hardware it becomes. A wire is a net: it has no storage of its own and continuously reflects whatever drives it, either a continuous assign or the output port of a module instance. A reg is a variable: it holds the last value a procedural statement gave it, so anything assigned inside an always or initial block must be a variable.

Whether a reg becomes a flip-flop depends only on the block. Assigned in always @(posedge clk) it is a register; assigned in always @* with a value on every path it is combinational logic.

Re: Verilog reg versus wire, and SystemVerilog logic: which type do I declare for a signal?

#3

So the decision is mechanical:

  • Assigned in an always or initial block: reg.
  • Driven by assign: wire.
  • Connected to an output port of a submodule instance: wire, because the instance drives it continuously.
  • Module inputs are always nets. Module outputs are output reg if the module assigns them procedurally, plain output if it uses assign.

Undeclared names used in a port connection become implicit one-bit wires, which silently truncates buses. Putting `default_nettype none at the top of each file turns that into an error.

Re: Verilog reg versus wire, and SystemVerilog logic: which type do I declare for a signal?

#4

SystemVerilog's logic removes most of the bookkeeping. It is a four-state type, the same thing as reg under a better name, but a logic variable may also be driven by one continuous assign or by one module output port. You can declare nearly everything logic and stop thinking about it.

The condition is a single driver. A logic variable driven from two places, two assign statements or an assign plus an always block, is a compile error. That is a useful check, since two drivers on one ordinary signal is almost always a bug, and a wire would accept it quietly and show X when the drivers disagree.

Re: Verilog reg versus wire, and SystemVerilog logic: which type do I declare for a signal?

#5

You still need a net type where several drivers are intended: bidirectional inout ports and tri-state buses, for example assign data = oe ? dout : 8'bz; with data declared as wire.

One pitfall when converting old code: wire y = a & b; is a declaration with a continuous assignment, so y tracks a and b. logic y = a & b; is a variable with an initial value, computed once at time zero and never updated. After replacing wire with logic, such lines must be split into a declaration and a separate assign.

Re: Verilog reg versus wire, and SystemVerilog logic: which type do I declare for a signal?

#6

Two related type choices in SystemVerilog. bit is a two-state type that starts at 0 and cannot hold X or Z. In design code it hides exactly the problems you want to see, such as a register that was never reset, so keep design signals four-state and use bit and int in testbench code.

And since the type no longer says anything about intent, state it with the block keyword: always_ff for registers, always_comb for combinational logic, always_latch for intended latches. Tools then check that the contents of the block match what you declared.

TEP COMMUNITY