Data Types and Procedural Constructs in Verilog
Data Types
Nets
- Purpose: represent physical connections (wires).
- Declared with keywords:
wire
,tri
,wand
,wor
,supply0
,supply1
, etc. - Driven by: continuous assignments or module/gate outputs.
- Cannot hold value unless driven.
- Default initialization =
z
(high-impedance).
wire a, b, sum;
assign sum = a ^ b; // continuous drive
Corner case: multiple drivers → resolved by net type (wired-AND, wired-OR, etc.). If conflict without wired type → x
.
Net Types
Net | What it models / resolves | Notes |
---|---|---|
wire | plain resolved wire | default for ports (unless declared otherwise) |
tri | tri-state wire | same as wire (historical name) |
tri0 | tri-state with weak pull-down when undriven | handy for default 0 on bus |
tri1 | tri-state with weak pull-up when undriven | handy for default 1 on bus |
wand | wired-AND resolution | multiple drivers ANDed bitwise |
wor | wired-OR resolution | multiple drivers ORed bitwise |
triand | tri-state wired-AND | z participants ignored; else ANDed |
trior | tri-state wired-OR | z participants ignored; else ORed |
trireg | charge-storage net | holds last driven value when all drivers go z (decay optional via strengths/delays) |
supply0 | power net tied to logic 0 (strong0) | cannot be driven by logic |
supply1 | power net tied to logic 1 (strong1) | cannot be driven by logic |
uwire | unresolved wire (Verilog-2005) | compile error if multiply driven (great to catch fan-in mistakes) |
Registers
- Represent variables/storage elements.
- Declared with
reg
. - Hold last assigned value until updated.
- Used in procedural blocks (
initial
,always
). - Default initialization =
x
(unknown).
reg q;
always @(posedge clk) q <= d; // storage
⚠️ reg
does not imply flip-flop; inference depends on procedural style.
Register Types
Type | Width / Signedness | Typical use |
---|---|---|
reg | user-defined width (default 1-bit, unsigned unless declared signed ) | general procedural variable (flops/latches/comb as coded) |
integer | 32-bit signed | loop counters, arithmetic temporaries |
time | 64-bit unsigned | simulation time storage |
real | double-precision floating-point | testbench math (unsynthesizable) |
realtime | alias of real | testbench timing calcs |
event | event handle | testbench synchronization |
Parameters
- Compile-time constants.
- Used for configurability & readability.
parameter WIDTH = 8;
reg [WIDTH-1:0] data;
- Can be overridden:
- By name:
my_module #(.WIDTH(16)) u1 (...);
- By defparam:
defparam u1.WIDTH = 16;
(discouraged).
- By name:
- localparam = constant that cannot be overridden.
Examples:
// Parameter declaration
module m #(parameter WIDTH=8, parameter SIGNED=0) (
input [WIDTH-1:0] a, b,
output [WIDTH-1:0] y
);
localparam HALF = WIDTH/2; // cannot be overridden
assign y = a + b;
endmodule
// Overriding parameters
// 1) By name (preferred)
m #(.WIDTH(16), .SIGNED(1)) u1 (...);
// 2) By position (use with care; order matters as declared)
m #(16, 1) u2 (...);
Choosing Data Types for Ports
- input/output/inout must be declared as
wire
(default) orreg
explicitly. - Rules:
- Combinational outputs →
wire
. - Sequential outputs (from
always
) →reg
. - Bidirectional buses →
inout wire
.
- Combinational outputs →
module example(input wire clk,
input [7:0] a, b,
output reg [7:0] sum,
inout wire bus);
Continuous Assignment
- Syntax:
assign <net> = <expr>;
- Drives nets only.
- Updates whenever RHS changes.
assign y = a & b; // combinational logic
assign #5 y = a ^ b; // with delay
⚠️ Cannot assign to reg
with assign
.
Procedural Constructs
Initial Block
- Executes once at time 0.
- Used in testbenches (stimulus, init values).
initial begin
clk = 0;
forever #5 clk = ~clk;
end
Always Block
- Executes repeatedly whenever trigger occurs.
Syntax:
always @(<sensitivity_list>) <statements>
Examples:
Combinational:
always @(*) y = a & b; // implied sensitivity
Sequential:
always @(posedge clk or posedge rst) if (rst) q <= 0; else q <= d;
Named Blocks
- Group statements with a name → can be disabled.
always begin : block1
a = b + c;
if (stop) disable block1;
end
💡Remember
- Uninitialised
reg
=x
. - Unconnected
wire
=z
. - Multiple drivers on
wire
without resolution =x
. - Division by 0 =
x
. - Procedural assignments:
- Blocking (
=
) → sequential. - Non-blocking (
<=
) → parallel, preferred in sequential logic.
- Blocking (
Concept understood? Let's apply and learn for real