Verilog Data Types

Core Data Type Categories

A variable in Verilog belongs to one of two fundamental data types: Net and Register.

  • Net: Represents physical connections between hardware elements. They must be continuously driven by a source, such as a gate output or a continuous assignment. They cannot be used to store a value on their own.
  • Register: Represents a variable that can store a value. They retain the last value assigned to them until another assignment changes it. They are used within procedural blocks.

Logic Values and Signal Strengths

Verilog uses a 4-state logic system to model the behavior of real hardware.

  • 4-State Logic Values

    • 0: Represents a logic zero state or a false condition.
    • 1: Represents a logic one state or a true condition.
    • x: Represents an unknown or uninitialized logic state.
    • z: Represents a high-impedance state, indicating that a net is not being driven.
  • Initialization

    • All unconnected nets are initialized to a value of z.
    • All register variables are initialized to a value of x.
  • Signal Strengths

    • Verilog supports 8 strength levels to resolve conflicts when multiple drivers are connected to the same net.
    • If two signals of unequal strengths drive a wire, the stronger signal will prevail.
    • Strength levels are particularly useful for detailed modeling of MOS-level circuits.
    • The levels, from strongest to weakest, are: supply, strong, pull, large, weak, medium, small, and highz.

Net Data Types

Nets represent connections between hardware elements and are continuously driven by the outputs of the devices they are connected to.

  • General Properties

    • They are 1-bit values by default unless declared as vectors.
    • The default value of a net is z.
    • The wire data type is the most common type of net.
  • Types of Nets

    • wire and tri: These are functionally equivalent. When multiple drivers are connected to a wire or tri net, their outputs are shorted together. If the drivers have conflicting values, the result is x unless strengths are used.
    • wand (wired-AND) and wor (wired-OR): These net types model resolved signals. If multiple drivers are connected, an implicit AND or OR gate is inserted at the connection to determine the net’s value.
      • Example: If two assign statements drive a wire f, the result is indeterminate. If they drive a wand f, the result is the logical AND of the two driving expressions. f = (A & B) & (C | D)
    • supply0 and supply1: These model power supply connections, representing ground (VSS) and power (VDD) respectively. They have the highest signal strength (supply).

Register Data Types

A register is a variable that holds a value. Unlike nets, they do not need to be continuously driven. The term “register” in Verilog does not necessarily mean it will map to a physical hardware register during synthesis.

  • Register Data Type Categories

    • reg: The most widely used register type. Used to model both sequential and combinational logic.
    • integer: A general-purpose register used for manipulating quantities, often as a loop counter.
    • real: Used to store floating-point numbers.
    • time: Used to store simulation time; this is not synthesizable.
  • The reg Data Type

    • Default value is x.
    • Can be assigned a value in synchronism with a clock or asynchronously.
    • Its size must be explicitly declared (default is 1-bit).
    • It is treated as an unsigned number in arithmetic expressions.
    • It must be used when modeling sequential hardware elements like counters and shift registers.
  • The integer Data Type

    • A general-purpose register used for manipulating quantities.
    • More convenient than reg for tasks like loop counting.
    • Treated as a 32-bit 2’s complement signed integer.
    • The synthesis tool may try to determine a smaller required size based on data flow analysis.
  • The real Data Type

    • Used to store floating-point numbers.
    • When a real value is assigned to an integer, the number is rounded to the nearest integer.
    • Example: real pi = 314.159e-2; integer x; x = pi; // x gets value 3
  • The time Data Type

    • Simulation is carried out with respect to simulation time.
    • The time data type can store this simulation time.
    • The system function $time returns the current simulation time.

Vectors and Arrays

  • Vectors

    • Nets or reg type variables can be declared as vectors of multiple bit widths.
    • Vectors are declared by specifying a range [range1:range2], where range1 is the most significant bit (MSB) and range2 is the least significant bit (LSB).
    • Example: wire [7:0] sum; // MSB is sum[7], LSB is sum[0]
    • Parts of a vector can be addressed (part-select).
    • Example: reg [31:0] IR; reg [5:0] opcode; opcode = IR[31:26];
  • Arrays and Memories

    • Multi-dimensional arrays can be declared.
    • Memories are typically modeled as a 1-D array of registers.
    • Each element of the array is a word addressed by a single index.
    • Example: reg [15:0] mem_word[0:1023]; // 1K memory of 16-bit words

Constants and Parameters

  • Specifying Constant Values

    • A constant can be specified in a sized or unsized form.
    • Syntax for sized form: <size>'<base><number>
    • Examples: 4'b0101, 12'hB3C
    • Unsized numbers (e.g., 25) are treated as 32-bit signed numbers by default.
  • Parameters

    • A parameter is a constant with a given name, used to create flexible and reusable designs.
    • The size of a parameter is decided from the constant value itself (default is 32 bits if not specified).
    • Example: parameter N = 7; output [0:N] count;

Hardware Realization and Synthesis

A key concept in Verilog is how abstract data types are mapped to physical hardware during synthesis.

  • Net Synthesis

    • A net data type (wire, wand, etc.) always maps to a physical wire during synthesis.
  • Register Synthesis

    • A register data type (reg, integer) can map to either a wire or a storage cell (latch or flip-flop), depending on the context in which it is used.
  • When a reg becomes a wire:

    • If a reg variable is used in a procedural block (always) that describes purely combinational logic, it will be synthesized into combinational logic (wires and gates). This happens when the reg’s output value depends only on the current values of the inputs listed in the sensitivity list.
    • Example: In an always @(A or B or C) block, the statement f1 = ~(A & B); makes f1 a wire (equivalent to a NAND gate).
  • When a reg becomes a Storage Cell (Latch):

    • A latch is inferred when a procedural block implies that a reg variable needs to hold its state under certain conditions. This typically occurs due to:
      • Incomplete if-else or case statements: If a path through the logic does not assign a value to the reg, it must hold its previous value, which requires a latch.
      • Feedback: When a reg is assigned a value that is a function of itself, creating a feedback loop.
    • Example (incomplete if): In an always @(load or data) block, if (!load) d_out = data;. Since there is no else clause, d_out must be latched when load is high.
    • Example (feedback): f2 = f1 ^ f2;. This statement implies f2 must store its previous value to compute the new one, inferring a latch.
  • When a reg becomes a Storage Cell (Flip-Flop):

    • A flip-flop is inferred when a reg is assigned a value inside an always block that is sensitive to a clock edge (posedge clk or negedge clk). This describes synchronous, edge-triggered behavior.
    • Example: always @(posedge clk) begin count <= count + 1; end will synthesize count as a register (a series of flip-flops).