SystemVerilog is not only a verification language. Most new RTL is written in it, because it fixes real weaknesses of Verilog: one data type for every signal, blocks that state what hardware you mean, enums for state machines, structs and packages for shared types, and interfaces for busy port lists.
This tutorial goes through SystemVerilog topic by topic, and many topics are about classes, randomization and coverage, which never reach silicon. This page is the short route for designers: the articles that matter for synthesizable RTL, in a sensible order, with the sections to read where an article covers both design and verification.
5 min read | Reading guide
What You'll Learn
- Which SystemVerilog articles cover the synthesizable subset used for RTL design
- A reading order that builds from data types to blocks, connections and design patterns
- Which sections to read in articles that cover both design and verification
- Which parts of SystemVerilog a designer can safely skip
Before You Start
This guide assumes you can already write RTL in Verilog: modules, ports, always blocks and nonblocking assignments. SystemVerilog is a superset of Verilog, so all of that still works. What follows is what SystemVerilog adds on top for design.
If you want the why first, read SystemVerilog for Design vs. Verification in the tutorial introduction.
1. Data Types
The first thing to change in your RTL is how signals are declared. These articles replace the reg and wire confusion and let you give values names and structure.
- SystemVerilog logic: one 4-state type for almost every signal, driven from a procedural block or a continuous assignment.
- bit, byte and int: the 2-state types. Read Signed and Unsigned, then prefer
logicin RTL so X values from a missing reset stay visible in simulation. - Enumeration: named values with type checking, the basis for readable state machines and opcodes.
- typedef and alias: give a type a name once and reuse it across modules.
- Structure: group related fields. Focus on Packed Structures, which map onto a plain bit vector and are what RTL uses for buses and register fields.
- Union: two views of the same bits. Read the packed, untagged union sections; tagged unions are rarely used in synthesis.
- Packed Arrays and Unpacked Arrays: multi-dimensional vectors and memories. In SystemVerilog Arrays, only static arrays are for design; dynamic and associative arrays and queues are testbench types.
2. Procedural Blocks and Decisions
These are the constructs that describe logic. They let tools check that the code matches the hardware you meant.
- always_comb, always_latch and always_ff: the most important change for RTL. Each block states its intent, and tools warn when the code does not match it. You can skip Using These Blocks in Verification.
- unique and priority case: replace synthesis pragmas with checked keywords. Read Using unique and priority case in Digital Design.
- unique and priority if-else: the same idea for if-else chains. Read Using unique and priority if in Digital Design.
- Loops: only
forandforeachwith fixed bounds describe hardware. Read Loops in Design vs Verification;forever,whileandrepeatare for testbenches. - Functions and Tasks: automatic functions with ANSI-style arguments are useful for repeated combinational logic. Tasks that consume time and pass-by-reference arguments are testbench features.
3. Modules, Ports and Connections
Large designs spend many lines on port lists and wiring. These features cut that down and keep shared definitions in one place.
- Implicit Port Connections:
.nameand.*connect ports whose names match the signals. Read Using These Shortcuts in Design and Verification. - Package: share types, parameters and functions between modules. Read Design Notes: Packages and Synthesis.
- $unit Compilation Scope: why declarations outside any package cause trouble in multi-file builds, and why packages are the safer choice.
- Module Type Parameters: one module definition that works with different data types per instance.
- Interface, Interface Syntax and Connections and Modport: bundle a bus into one port and give each side its directions. Skip the clocking block sections, which are for testbenches.
- Interface Parameters and Interface Array: size an interface per instance, and connect replicated blocks or lanes.
Check your synthesis tool before using interfaces across the top level of a block. Most tools support them inside a design, but some flows still expect plain ports at block boundaries.
4. Design Patterns
- FSM Enum Modeling: the standard way to write state machines, with an enum state type and
unique case, and a lock-up bug to avoid. - Streaming Operators: pack and unpack structs and byte streams in one expression, useful in datapath and protocol logic.
5. Assertions in RTL
Designers write assertions too: a few checks inside the RTL catch misuse of a block at the exact cycle it happens, in simulation and in formal tools. Synthesis ignores them.
- SystemVerilog Assertions: what assertions are and the difference between immediate and concurrent ones.
- Immediate Assertions: read Immediate Assertion in Design.
- Concurrent Assertions and disable iff: multi-cycle checks such as "a request is acknowledged", switched off during reset.
To take assertions further, the Formal Verification tutorial shows how the same properties are proven for every input.
What Designers Can Skip
These parts of the tutorial are for testbenches and never appear in synthesizable RTL:
- Classes, inheritance, polymorphism and everything object-oriented
- Randomization and constraints
- Functional coverage: covergroups, coverpoints and bins
- Dynamic arrays, associative arrays, queues and strings
fork/join, mailboxes, semaphores and events- Program blocks, clocking blocks and virtual interfaces
- DPI and file I/O
They are worth learning later if you need to read or debug a testbench, but none of them is needed to write RTL.
Summary
In this guide, you learned:
- SystemVerilog is used for RTL design as well as verification, through a well-defined synthesizable subset
- Start with
logic, enums, typedefs and packed structs, then move toalways_comb/always_ffandunique/priority - Packages, implicit port connections and interfaces with modports cut down repeated declarations and wiring
- Enum-based FSMs and a few assertions in the RTL are standard practice
- Classes, randomization, coverage and dynamic data types are for testbenches and can be skipped for design