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 driveCorner 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) orregexplicitly. - 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;
endAlways Block
- Executes repeatedly whenever trigger occurs.
Syntax:
always @(<sensitivity_list>) <statements>
Examples:
Combinational:
always @(*) y = a & b; // implied sensitivitySequential:
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
wirewithout 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