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

NetWhat it models / resolvesNotes
wireplain resolved wiredefault for ports (unless declared otherwise)
tritri-state wiresame as wire (historical name)
tri0tri-state with weak pull-down when undrivenhandy for default 0 on bus
tri1tri-state with weak pull-up when undrivenhandy for default 1 on bus
wandwired-AND resolutionmultiple drivers ANDed bitwise
worwired-OR resolutionmultiple drivers ORed bitwise
triandtri-state wired-ANDz participants ignored; else ANDed
triortri-state wired-ORz participants ignored; else ORed
triregcharge-storage netholds last driven value when all drivers go z (decay optional via strengths/delays)
supply0power net tied to logic 0 (strong0)cannot be driven by logic
supply1power net tied to logic 1 (strong1)cannot be driven by logic
uwireunresolved 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

TypeWidth / SignednessTypical use
reguser-defined width (default 1-bit, unsigned unless declared signed)general procedural variable (flops/latches/comb as coded)
integer32-bit signedloop counters, arithmetic temporaries
time64-bit unsignedsimulation time storage
realdouble-precision floating-pointtestbench math (unsynthesizable)
realtimealias of realtestbench timing calcs
eventevent handletestbench 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).
  • 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) or reg explicitly.
  • Rules:
    • Combinational outputswire.
    • Sequential outputs (from always) → reg.
    • Bidirectional busesinout wire.
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.

Concept understood? Let's apply and learn for real

Practice now