Introduction to Verilog
A complete guide to Verilog HDL — history, design levels, language constructs, data types and operators.
📜 History of Verilog
Verilog was one of the first modern hardware description languages, built to model, simulate, and eventually synthesize digital circuits.
The Beginning
Created by Prabhu Goel and Phil Moorby at “Automated Integrated Design Systems” (renamed Gateway Design Automation in 1985). Originally for simulation only — synthesis support was added later. Cadence Design Systems acquired Gateway in 1990, gaining rights to Verilog and the Verilog-XL simulator, the de-facto standard for the next decade.
Verilog-95
Cadence transferred Verilog to the public domain under Open Verilog International (OVI) — now Accellera — in response to VHDL’s growing popularity. IEEE standardized it as IEEE 1364-1995. Verilog-A (analog modeling) was also initiated around this time.
Verilog-2001
A major upgrade. Key additions: 2’s-complement signed nets, new operators (+, -, /, *, >>>), generate/endgenerate for parameterized instantiation, improved file I/O, and always @*. This remains the dominant version in commercial EDA tools.
Verilog-2005
Minor corrections, spec clarifications, and additions such as the uwire keyword. Verilog-AMS (Analog & Mixed Signal) was formalized as a companion standard.
SystemVerilog
Verilog and SystemVerilog were merged into one unified standard. SystemVerilog is a superset of Verilog-2005, adding powerful verification and modeling features drawing from Open Vera and SuperLog.
🏗 Levels of Design Description
Verilog supports four abstraction levels. One of its greatest strengths is that you can freely mix all four within the same design module.
assign. All assignments run concurrently.
assign y = a & b;
Fig 2 — Same AOI Gate at Each Abstraction Level
// Behavioral Level always @(a, b, c, d) begin y = ~((a & b) | (c & d)); end // Data Flow Level assign y = ~((a & b) | (c & d)); // Gate Level and g1(ab, a, b); and g2(cd, c, d); nor g3(y, ab, cd);
⚡ Concurrency
Real hardware is inherently parallel — transistors and gates act simultaneously. Verilog simulators model this through concurrent execution.
always and assign blocks run in parallel, unlike sequential C programs.`timescale 1ns/1ps to set simulation time units and precision per module.always @(posedge clk).🔬 Simulation & Synthesis
Simulation checks functional correctness — a testbench drives inputs and captures outputs. Synthesis translates verified RTL into hardware (FPGA or ASIC). Many behavioral constructs are not directly synthesizable; rewrite those at RTL level if needed.
✅ Functional Verification
Testing has two dimensions: functional tests and timing tests. Both use a testbench module that instantiates the design, drives inputs, and checks outputs.
instantiated inside TB
Testbenches are written at the behavioral level. Variables inside nested modules are accessed via hierarchical addressing (e.g., top.dut.signal_name).
🛠 System Tasks & PLI
System Tasks
Built-in routines prefixed with $, used during simulation only — not part of the synthesized hardware.
$display, $monitor, $strobe — print signal values during simulation.$fopen, $fwrite, $readmemh — read test vectors from or write results to files.$finish, $stop — end or pause simulation at a specific point.$time, $realtime to track progress. $random for constrained-random test generation.Programming Language Interface (PLI)
📦 The Module
Every Verilog design is built from modules — black boxes with named ports. Ports can be input, output, or inout.
(IC 7430)
Fig 6 — Module Definition & Instantiation
// Module definition (done once) module nand_gate ( input [7:0] in, output y ); assign y = ~(&in); endmodule // Positional instantiation nand_gate IC1 (bus_a, out_a); // Named port instantiation (preferred — less error-prone) nand_gate IC2 (.in(bus_b), .y(out_b)); nand_gate IC3 (.in(bus_c), .y(out_c));
🔤 Language Constructs & Conventions
Verilog source files are composed of 7 types of lexical tokens:
clk, CLK, and Clk are three different identifiers — just like C.Keywords
module // begins a module endmodule // ends a module begin end // procedural block boundaries if else // conditional branching always // procedural block (runs continuously) assign // continuous (data-flow) assignment wire reg // net and variable declarations
Identifiers
// ✅ Valid — start with letter or underscore clock enable gate_1 _reset data_32b // ❌ Invalid 1_name // starts with a digit $name // $ cannot be the first character name aa // space splits this into two separate tokens
Numbers — Format: <size>'<base><value>
4'b1010 // 4-bit binary 8'hFF // 8-bit hex (= 255 decimal) 6'd35 // 6-bit decimal 12'o777 // 12-bit octal 4'bx0z1 // x=unknown, z=high-impedance 8'b1010_1100 // underscore for readability (ignored by compiler)
Comments
// Single-line comment /* Multi-line comment spans multiple lines — cannot be nested */
🔵 Logic Values & Strengths
Every signal in Verilog can hold one of four logic values:
| Value | Meaning | Typical Scenario |
|---|---|---|
| 0 | Logic low / false | Normal driven-low state |
| 1 | Logic high / true | Normal driven-high state |
| x | Unknown / uninitialized | Power-on state, conflicting drivers, don’t-care |
| z | High impedance | Tri-state bus, floating wire |
z input to a gate behaves as x. Exception: MOS switches — a z input propagates as z to the output.Signal Strengths
When multiple sources drive the same net, the stronger source wins. Equal strengths driving opposite values produce x.
| Category | Strength Order (Strongest → Weakest) |
|---|---|
| Driving | supply > strong > pull > weak |
| Capacitive | large > medium > small |
| High-Z | highz — weakest of all, represents a floating state |
💾 Data Types
Verilog data types fall into two categories. Every signal must be declared before use.
NET Types — Connections
z if undriven.VARIABLE Types — Storage
$time).Fig 7 — Scalars vs Vectors
// Scalar (no range = 1 bit) wire wr; // 1-bit net reg flag; // 1-bit register // Vectors wire [7:0] data; // 8-bit bus; data[7]=MSB, data[0]=LSB reg [3:0] nibble; // 4-bit register // Signed vectors wire signed [4:0] num; // range: -16 to +15 // Part-selects data[0] // LSB only data[7:4] // upper nibble
Parameters
parameter WORD_SIZE = 16; parameter MEM_SIZE = 256, FACTOR = WORD_SIZE/2; // Override at instantiation time my_mem #(.WORD_SIZE(32), .MEM_SIZE(1024)) u1 ( ... );
⚙️ Operators
Verilog operators are similar to C, with three forms:
| Type | Form | Example | Description |
|---|---|---|---|
| Unary | op a | ~a | Bitwise NOT |
| Binary | a op b | a & b | Bitwise AND |
| Ternary | a ? b : c | sel ? x : y | If sel=1 → x, else → y |
Quick Reference
// Arithmetic a + b a - b a * b a / b a % b // Logical (1-bit result) a && b a || b !a // Bitwise (bit-by-bit, same width as operands) a & b a | b a ^ b ~a a ~^ b // ~^ = XNOR // Reduction (collapses a bus to 1 bit) &a // AND all bits |a // OR all bits ^a // XOR all bits — odd-parity check // Shift a << 2 // logical left shift a >> 2 // logical right shift a >>> 2 // arithmetic right shift (sign-preserving) // Concatenation & Replication {a, b} // join bits of a and b {4{a}} // replicate a four times // Equality a == b // logical equality (x/z → x result) a === b // case equality (x and z must match exactly)
