← Back to the series

Verification, From First Principles — Part 4 of 10

From Verilog to SystemVerilog to UVM

Three names that get used almost interchangeably by beginners, but each one is a different layer, solving a different problem the layer below it couldn't.

Verilog: describing hardware

Verilog is a hardware description language (HDL). Its job is to describe circuit behavior in a way a synthesis tool can turn into actual logic gates — flip-flops, muxes, adders. A simple counter looks like this:

counter.v module counter ( input wire clk, input wire rst_n, output reg [3:0] count ); always @(posedge clk or negedge rst_n) begin if (!rst_n) count <= 4'd0; else count <= count + 4'd1; end endmodule

Verilog is fine for describing hardware. It's clumsy for verifying it. It has no classes, no dynamic arrays, no built-in randomization, no object-oriented structure — all things that become essential once your testbench itself grows into a real piece of software.

SystemVerilog: a verification language grafted onto Verilog

SystemVerilog is a superset of Verilog — every legal Verilog file is also legal SystemVerilog — that adds a large set of verification-focused features: classes, inheritance, dynamic and associative arrays, constrained randomization, functional coverage constructs, and assertions. This is what lets a testbench be written like actual object-oriented software instead of a flat pile of always-blocks.

packet.sv class packet; rand bit [7:0] data; rand bit [3:0] addr; constraint c_addr { addr inside {[0:15]}; } function void display(); $display("addr=%0d data=%0d", addr, data); endfunction endclass module tb; packet pkt; initial begin pkt = new(); repeat (5) begin pkt.randomize(); pkt.display(); end end endmodule

That packet class is a self-contained, reusable object with its own randomization constraints — the constrained-random approach from Part 3, expressed directly in the language. This is a genuine leap over plain Verilog. But notice what's still missing: nothing here says how a testbench should be structured — where the driver lives, how a scoreboard should be connected, how phases like "build" and "run" should be sequenced. Every team that used only SystemVerilog ended up inventing its own answer to those questions, which made testbenches hard to reuse across projects, or even across teams in the same company.

UVM: a standard structure, built out of SystemVerilog classes

UVM (Universal Verification Methodology) doesn't add new language syntax on top of SystemVerilog — it's a library of SystemVerilog base classes, plus a set of conventions, that answers exactly the structural question SystemVerilog left open. It defines standard building blocks — uvm_driver, uvm_monitor, uvm_sequence, uvm_scoreboard, uvm_env — and a standard way for them to be built, connected, and run, called phasing (build_phase, connect_phase, run_phase, and a few more — Part 7 walks through this in detail).

Because every UVM environment follows the same structure, an engineer who has seen one UVM testbench can find their way around a completely different one, at a different company, verifying a completely different protocol — the components have different names, but the shape is the same. That reusability, more than any single technical feature, is why the next part of this series is about why the industry converged on UVM specifically.

LayerWhat it adds
VerilogDescribes hardware behavior for synthesis
SystemVerilogAdds classes, randomization, coverage, assertions — verification as software
UVMStandard structure and reuse on top of SystemVerilog's class library

Takeaway

Verilog describes hardware. SystemVerilog gives you the object-oriented tools to build a serious testbench. UVM is that toolset, organized into a standard, reusable structure that the whole industry recognizes. Each layer solves a problem the one below it left open.