Module 1 — SystemVerilog Basics
A complete, example-driven walkthrough of SystemVerilog fundamentals: data types, variables vs nets, arrays of every flavor, strings, enums, structs, unions, and typedef — the building blocks every verification engineer needs before UVM.
📑 Table of Contents
1Introduction to SystemVerilog
SystemVerilog (IEEE 1800) is a unified hardware description and verification language (HDVL). It extends Verilog (IEEE 1364) with powerful constructs for design (interfaces, always_comb/always_ff, enhanced data types) and verification (classes, randomization, constraints, functional coverage, assertions).
It was created by merging two industry efforts — Accellera's Superlog/SystemVerilog 3.1 extensions and the OVM/VMM verification methodologies — into a single IEEE standard. Today it is the backbone of nearly every modern ASIC/FPGA verification environment, especially through UVM (Universal Verification Methodology), which is built entirely in SystemVerilog.
SystemVerilog lets one language do both RTL design and testbench verification — no more juggling Verilog for design and a separate language (like Vera or e) for verification.
What SystemVerilog Adds Over Verilog
- Design side:
logictype,always_comb/always_ff/always_latch, interfaces, packages, enhanced literals. - Verification side: classes & OOP, randomization (
rand/randc), constraints, mailboxes, semaphores, functional coverage (covergroup), assertions (SVA). - Data types: 2-state types, dynamic arrays, queues, associative arrays, strings, structs, unions.
2Verilog vs SystemVerilog
Verilog is primarily an RTL/gate-level design language; SystemVerilog is a superset built for both design and verification productivity.
| Aspect | Verilog (IEEE 1364) | SystemVerilog (IEEE 1800) |
|---|---|---|
| Primary Use | RTL design | Design + Verification (HDVL) |
| Data Types | reg, wire (4-state only) | logic, bit, byte, int, shortint, longint (2-state & 4-state) |
| OOP Support | None | Full classes, inheritance, polymorphism |
| Randomization | Not supported | rand, randc, constraint blocks |
| Arrays | Fixed-size only | Dynamic, queues, associative arrays |
| Assertions | Not native | SVA — immediate & concurrent assertions |
| Interfaces | Not available | interface construct with modports |
| Always Blocks | always | always_comb, always_ff, always_latch |
| Coverage | Not native | covergroup, coverpoint, cross coverage |
A common interview question: "Is SystemVerilog backward compatible with Verilog?" Yes — every legal Verilog-2001 construct is legal SystemVerilog, since SV is a strict superset.
3Data Types: 2-State vs 4-State Logic
Verilog's reg and wire are 4-state types: each bit can be 0, 1, X (unknown), or Z (high-impedance). SystemVerilog adds 2-state types that can only hold 0 or 1 — no X or Z.
| Feature | 4-State (logic/reg) | 2-State (bit/int/byte) |
|---|---|---|
| Possible Values | 0, 1, X, Z | 0, 1 only |
| Default Init | X | 0 |
| Simulation Speed | Slower | Faster |
| Memory Usage | Higher (2 bits/bit) | Lower (1 bit/bit) |
| Typical Use | RTL signals, DUT ports | Testbench counters, scoreboards |
| Detecting Uninitialized Reads | Yes (shows as X) | No (silently reads 0) |
Because 2-state variables reset to 0 instead of X, an uninitialized 2-state signal can silently mask a bug that a 4-state logic variable would have flagged as X. Use logic for DUT-facing signals and reserve bit/int for pure testbench bookkeeping.
logic vs reg vs wire
logic merges the roles of reg and single-driver wire — it can be driven by a continuous assignment, a procedural block, or a port connection, but it cannot have multiple drivers (for that you still need wire / tri).
4Variables and Nets
SystemVerilog data objects fall into two categories: nets (represent physical wires connecting structural elements) and variables (represent storage, updated procedurally).
| Aspect | Net (wire) | Variable (logic) |
|---|---|---|
| Represents | Physical wire/connection | Storage element |
| Driven By | Continuous assignment / gate / port | Procedural block (always/initial) or single continuous assign |
| Multiple Drivers | Allowed (resolved by strength/type) | Not allowed |
| Default Value | Z (high-Z) | X |
| Used For | Module interconnects | Registers, testbench state |
Use logic everywhere in RTL and TB except when you genuinely need multi-driver resolution (e.g., a bidirectional bus) — that's when wire/tri is required.
5Arrays: Packed vs Unpacked
SystemVerilog distinguishes between packed arrays (contiguous bits, treated as a single vector) and unpacked arrays (separate storage elements, like a C array).
| Aspect | Packed Array | Unpacked Array |
|---|---|---|
| Syntax Position | Before variable name [3:0] data | After variable name data [3:0] |
| Memory Layout | Contiguous bits (single vector) | Separate elements |
| Can Cast to Integer | Yes | No (not directly) |
| Typical Use | Bit-vectors, register fields | Memories, arrays of structs/objects |
| Bit-Select Whole Array | Yes | No |
Classic question: "Declare a memory of 1024 words, each 32 bits wide, and explain packed vs unpacked."
Answer: logic [31:0] mem [0:1023]; — [31:0] is packed (word width), [0:1023] is unpacked (number of words/addresses).
6Dynamic Arrays
Dynamic arrays are unpacked arrays whose size can be set and changed at run time using new[]. Unlike fixed arrays, their size isn't known at compile time.
size(), delete(), and array locator/reduction methods (sum(), find(), sort(), reverse()) all work on dynamic arrays, since they belong to SystemVerilog's general "array manipulation methods" available on unpacked array types.
Calling new[N] without the parenthesized old-array argument wipes existing contents. Always pass the old array — new[N](old_array) — if you need to preserve data while resizing.
7Queues
A queue is a variable-size, ordered collection — like a dynamic array with built-in FIFO/LIFO operations. Declared with $ as the unpacked dimension.
Queues are the go-to structure for scoreboards and transaction mailboxes in UVM-style testbenches — pushing expected transactions on one side and popping/comparing them against actual DUT outputs on the other.
| Structure | Resize | Fast Insert/Delete at Ends | Fast Random Access |
|---|---|---|---|
| Fixed Array | No | N/A | Yes |
| Dynamic Array | Yes (via new[]) | Slow | Yes |
| Queue | Automatic | Yes (push/pop) | Yes |
| Associative Array | Automatic | Yes (by key) | By key only |
8Associative Arrays
An associative array is a sparse, key-indexed collection — similar to a hash map/dictionary. Elements are allocated only when written, making it memory-efficient for large or sparse address spaces.
Directly reading a non-existent key, e.g. y = assoc["missing"], silently returns the default value and creates the entry. Always check with exists() first if you don't want to pollute the array.
9Strings
SystemVerilog's built-in string type is a dynamically-sized class-like type (not a fixed-width bit vector), with a rich set of built-in methods.
Unlike C, SystemVerilog strings don't need manual memory management or a null terminator — they grow/shrink automatically, similar to a queue of bytes under the hood.
10Enumerations
An enum creates a named set of integer constants, improving readability and enabling compile-time type checking versus using raw magic numbers.
Enums are strongly typed — you cannot assign an out-of-range integer to an enum variable without an explicit cast. This is a favorite interview trap: cur_state = 5; is illegal unless cur_state = state_e'(5);.
11Structures
A struct groups multiple, possibly different-typed fields into a single named entity — like a C struct or a bus of related signals.
A packed struct is stored as one contiguous bit vector (fields laid out MSB→LSB in declaration order) and can be directly assigned to/from an integer. An unpacked struct stores fields as separate variables and cannot be cast to a single vector without a manual pack.
12Unions
A union lets multiple fields share the same storage location (size = size of the largest member) — useful for reinterpreting the same bits as different types.
Ordinary (non-tagged) unions offer no type safety — writing one member and reading another is legal and simply reinterprets the bits. Use tagged unions when you need SystemVerilog to track which member is actually active.
13Typedef
typedef creates a new name (alias) for an existing type — improving readability, enabling reuse, and letting you forward-declare types used before their full definition.
Put all shared typedefs (enums, structs, common bus types) in a package and import it wherever needed — this is exactly how UVM-style testbenches share transaction and configuration types across environment, agents, and scoreboard.
🎯 Module 1 Recap
- SystemVerilog is a unified design + verification language, a strict superset of Verilog.
- Use
logic(4-state) for RTL/DUT signals; usebit/int(2-state) for fast testbench bookkeeping. - Nets (
wire) model physical wires with multi-driver resolution; variables (logic) model single-driver storage. - Packed arrays are contiguous bit-vectors; unpacked arrays are collections of separate elements.
- Dynamic arrays, queues, and associative arrays give you resizable, insertable, and sparse/keyed storage respectively.
- Built-in
string,enum,struct, anduniontypes make testbench code far more expressive than raw Verilog vectors. typedefis the glue that makes all these types reusable and shareable across a verification environment.
📚 Next up — Module 2: Procedural Constructs & Always Blocks (always_comb, always_ff, always_latch, tasks & functions)
↑ Back to Table of Contents
Comments
Post a Comment