Back to study plans
Module 2 · 4 weeks · Design Verification

SystemVerilog Hands-On

Get fluent in the verification language interviewers actually probe: dynamic data structures, OOP for reusable testbench components, constrained randomization, interfaces and clocking blocks, processes and IPC, and finally SystemVerilog assertions and functional coverage.

4 weeks·25 assignments·~17 h of work·Intermediate

By the end you can

  • Model transactions with classes, deep copy and polymorphism
  • Write constrained-random stimulus with solve-before and distributions
  • Drive a DUT through an interface with a clocking block
  • Specify behavior with SVA and measure it with functional coverage

0 / 25 assignments done

Move each assignment through the stages — progress saves automatically.

0-day streak
W1

Data types & structures

0/6

The containers testbenches live on — queues, dynamic and associative arrays, packed structs/unions — plus packages and a DPI call.

Core45 min· Data types and arrays

Queues, dynamic and associative arrays

Model a small scoreboard store three ways: a queue used as a FIFO of expected items, a dynamic array you grow at runtime, and an associative array keyed by an address. Add, look up, and delete entries and print the contents.

Requirements

  • Queue push_back/pop_front used as an ordered expected-list
  • Dynamic array sized at runtime with new[]
  • Associative array keyed by a wide address with exists()/delete()
  • A short demo that adds, finds and removes entries

You'll be able to

  • Pick the right SV container for a verification task
  • Use queue, dynamic and associative array methods correctly

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core40 min· Data types and arrays

Packed struct and union for a packet header

Define a packed struct for a protocol header (fields like addr, len, opcode, parity) and a union that views the same bits as a raw vector. Pack a header, corrupt one bit through the union view, and detect it.

Requirements

  • A packed struct with named bit-fields
  • A union giving a raw [N-1:0] view of the same storage
  • Round-trip: struct → bits → struct is lossless
  • A parity field computed and checked

You'll be able to

  • Use packed structs/unions for bit-accurate modeling
  • Reason about layout and byte/bit ordering

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Starter35 min· Packages and DPI

Package and a DPI-C helper

Put shared typedefs and a parameter in a package, import it into two modules, and import one C function via DPI to compute a reference checksum. Call the C function from SystemVerilog and use its result.

Requirements

  • A package with at least one typedef and one parameter
  • Two consumers importing the package
  • One import "DPI-C" function with a matching C signature
  • The DPI result used in a comparison

You'll be able to

  • Share definitions cleanly with packages
  • Call external C reference models through DPI

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core40 min· Data types and arrays

Array locator and reduction methods

Given a queue of transactions, use the built-in array methods with a `with` clause instead of hand-written loops: find and find_index the reads, sum the lengths, get min/max address, and sort/rsort by address.

Requirements

  • find/find_index with a `with` predicate
  • sum/min/max reductions with `with`
  • sort and rsort using a key expression
  • No manual loop where a built-in method exists

You'll be able to

  • Use SystemVerilog array methods idiomatically
  • Replace loops with locators and reductions

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Starter30 min· Data types and arrays

String parsing and formatting

Parse a command line such as WR 0x40 12 into an opcode, address and length using $sscanf, then build a formatted log line with $sformatf. Reject a malformed line without crashing.

Requirements

  • Convert hex/decimal text to numeric values
  • Use string methods (len, substr, toupper) where useful
  • Format output with $sformatf including zero-padded hex
  • A malformed line is rejected gracefully

You'll be able to

  • Process and format strings in SystemVerilog
  • Convert between text and numeric values

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core40 min· Data types and arrays

Streaming operators for pack/unpack

Serialize a packed header struct into a byte queue and reconstruct it using the streaming operators. Show that a round trip is lossless and how the streaming direction changes byte order.

Requirements

  • Pack a struct to a byte queue with the >> stream
  • Unpack back into an identical struct
  • Demonstrate << reversing the order
  • A round-trip equality check

You'll be able to

  • Serialize and deserialize with streaming operators
  • Reason about bit and byte ordering

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

W2

Object-oriented testbench building blocks

0/6

The class patterns every UVM component is built on — a transaction with deep copy and compare, and a base/derived hierarchy using polymorphism.

Core50 min· Object-oriented programming

Transaction class with deep copy and compare

Write a transaction class with rand fields, plus copy(), clone(), compare() and a display() method. Demonstrate that a deep copy is independent of the original (mutating one doesn't change the other), unlike a handle assignment.

Requirements

  • rand fields plus a constructor
  • copy() performs a field-by-field deep copy
  • compare() returns a match result and a diff message
  • A demo proving handle-assignment aliases but copy() does not

You'll be able to

  • Distinguish shallow (handle) copy from deep copy
  • Provide the copy/compare/print methods components rely on

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core45 min· Object-oriented programming

Inheritance and polymorphism: base and derived driver

Create a base driver class with a virtual drive() method and two derived drivers that override it. Store them through base handles in an array and call drive() polymorphically so the correct override runs.

Requirements

  • A base class with a virtual method
  • Two subclasses overriding that method
  • Base-handle array holding derived objects
  • A loop calling the virtual method (dynamic dispatch)

You'll be able to

  • Use virtual methods for run-time polymorphism
  • Explain why 'virtual' is required for the override to run

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core40 min· Object-oriented programming

Parameterized generic container class

Write a parameterized stack class with a type parameter and push/pop/size/is_empty, then specialize it for an int and for a transaction handle to show the same code is type-safe for both.

Requirements

  • A type parameter with a sensible default
  • Type-safe push/pop/size/is_empty
  • Two specializations (a scalar and a class handle)
  • A short demo exercising both

You'll be able to

  • Write reusable parameterized classes
  • Specialize a generic class for multiple types

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Starter30 min· Object-oriented programming

Static members: a transaction counter

Add a static counter and a per-object unique id to a transaction class so every object is numbered and you can query how many were created, plus a static method that reports the count.

Requirements

  • A static count incremented in the constructor
  • A per-object unique id derived from the static
  • A static reporting method
  • A demo showing the count is shared across instances

You'll be able to

  • Use static members for shared state
  • Give each object a unique id

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core45 min· Object-oriented programming

Abstract class and a simple factory

Define an abstract base transaction with a pure virtual method, two concrete subclasses, and a factory function that returns the right subclass by an enum — the pattern UVM's factory formalizes.

Requirements

  • A virtual (abstract) class with a pure virtual method
  • Two concrete subclasses implementing it
  • A factory function returning a base handle by kind
  • Polymorphic use of the returned objects

You'll be able to

  • Use abstract classes and pure virtual methods
  • Build a type-selecting factory

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core35 min· Object-oriented programming

Safe downcasting with $cast

Downcast a base handle to a derived handle with $cast, handling both the success and failure cases, and explain why a direct assignment from base to derived doesn't compile.

Requirements

  • A successful $cast when the object is the derived type
  • A handled failure when it is not
  • An explanation of why the direct assign is illegal
  • No run-time crash on the failing path

You'll be able to

  • Downcast safely with $cast
  • Explain compile-time vs run-time type checks

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

W3

Randomization, constraints & interfaces

0/6

Generate legal, interesting stimulus with constraints, then hand it to a DUT through an interface and a clocking block.

Core50 min· Randomization and constraints

Constrained-random packet with solve-before and dist

Build a packet class whose length and address are constrained (e.g. aligned addresses, length weighted toward small packets, no crossing a boundary). Use solve-before where an ordering dependency exists and a dist for weighting.

Requirements

  • At least three interacting constraints
  • A dist clause to weight a field
  • A solve-before to control a dependent field's distribution
  • A short randomize() loop showing the legal spread

You'll be able to

  • Write realistic constrained-random stimulus
  • Control ordering and weighting with solve-before and dist

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Stretch45 min· Randomization and constraints

Classic constraints: sum-to-N and all-unique

Solve two staple interview constraints: randomize an array of K elements that sums to exactly N, and randomize an array whose elements are all unique within a range. Prove both hold over many randomizations.

Requirements

  • An array-sum constraint producing a total of exactly N
  • A uniqueness constraint (no repeats) over a bounded range
  • A checker that fails loudly if either property is violated
  • Runs cleanly for many seeds with no solver failures

You'll be able to

  • Express aggregate and relational constraints on arrays
  • Use the unique construct and array reductions

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core45 min· Interfaces and clocking

Interface, clocking block and virtual interface

Bundle a DUT's pins into an interface with a clocking block and a testbench modport, then drive and sample the DUT from a class through a virtual interface — with no race between the driver and the DUT.

Requirements

  • An interface grouping the DUT signals
  • A clocking block with input/output skews
  • A modport for the testbench side
  • A class driving/sampling via a virtual interface handle

You'll be able to

  • Connect class-based stimulus to RTL cleanly
  • Avoid driver/DUT races with clocking-block skews

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core40 min· Randomization and constraints

Inline constraints and rand/constraint_mode

Override a class's constraints for a single call with randomize() with {}, then use rand_mode(0) to freeze a field and constraint_mode(0) to switch off a constraint block at run time — showing the effect of each.

Requirements

  • An inline randomize() with {} that tightens a field
  • rand_mode(0) freezing a field at its current value
  • constraint_mode(0) disabling a named constraint
  • A demonstration of each toggle's effect

You'll be able to

  • Steer randomization per call
  • Enable and disable fields and constraints at run time

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Starter30 min· Randomization and constraints

pre_randomize and post_randomize hooks

Use post_randomize() to compute a derived field (a parity or CRC over the randomized data) so the object is always self-consistent after randomize(), and pre_randomize() to set up a guard the constraints depend on.

Requirements

  • pre_randomize sets up dependent state
  • post_randomize computes a derived field
  • The derived field is correct after every randomize()
  • A check across several randomizations

You'll be able to

  • Use the randomize hooks correctly
  • Compute fields that depend on randomized values

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core40 min· Randomization and constraints

randc and weighted distributions

Use randc to cycle through all values of a field with no repeats until the range is exhausted, and a dist with := and :/ weights to bias another field. Tally many draws to show randc's no-repeat property.

Requirements

  • A randc field cycling its full range before repeating
  • A dist-weighted rand field
  • A tally proving no repeats within a randc cycle
  • A note on rand vs randc cost

You'll be able to

  • Use randc for exhaustive cycling
  • Weight randomization with dist

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

W4

Processes, assertions & functional coverage

0/7

Concurrency and synchronization, then the two ways interviews check you can specify and measure behavior: SVA and covergroups.

Core45 min· Processes and IPC

fork/join, mailbox and semaphore

Build a tiny producer/consumer: a producer thread generates items into a mailbox, a consumer thread drains them, and a semaphore guards a shared resource. Show fork/join_any and fork/join_none behavior and terminate cleanly.

Requirements

  • A mailbox passing items between two threads
  • A semaphore protecting a shared section
  • A demonstration of join, join_any and join_none differences
  • Clean shutdown with no hung threads

You'll be able to

  • Coordinate concurrent threads with mailboxes and semaphores
  • Choose the right fork/join variant

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core50 min· SystemVerilog assertions

SVA: assert a request/grant handshake

Write concurrent assertions for a simple handshake: every req must eventually get an ack within N cycles, ack must not appear without a pending req, and a captured value must be stable while req is high. Use implication, $rose and $past.

Requirements

  • An overlapping/non-overlapping implication where appropriate
  • A bounded-response property (ack within N cycles)
  • Use of $rose/$fell and $past
  • Both an assert and a matching cover for one property

You'll be able to

  • Specify temporal behavior with SVA
  • Use implication and sampled-value functions correctly

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Stretch40 min· SystemVerilog assertions

SVA sequences with consecutive repetition

Specify a multi-cycle protocol fragment with a named sequence: a start pulse, then a burst of exactly K back-to-back valid beats, then done. Use consecutive repetition [*K] and compose sequences.

Requirements

  • A named sequence using [*K] consecutive repetition
  • Sequence composition with ##1 / within
  • An assertion that the full pattern holds after start
  • A cover to prove the pattern is exercised

You'll be able to

  • Build reusable named sequences
  • Use repetition operators to describe bursts

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core50 min· Functional coverage

Functional coverage: covergroup, bins and cross

Write a covergroup for a transaction: coverpoints for opcode and length with explicit bins (including illegal/ignore bins), and a cross between opcode and a length range. Sample it from stimulus and report coverage.

Requirements

  • Coverpoints with explicit, illegal and ignore bins
  • A cross of two coverpoints
  • Sampling triggered on a real event
  • A note on what 100% of this covergroup would prove

You'll be able to

  • Model functional intent with covergroups
  • Use bins, illegal_bins and crosses correctly

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Core40 min· Processes and IPC

Events: trigger, wait and wait_order

Synchronize threads with named events: one triggers with ->, others wait with @ or wait(ev.triggered), and enforce an ordering with wait_order. Show why @ can miss an event that wait(triggered) catches.

Requirements

  • -> to trigger and @ to wait
  • wait(ev.triggered) to avoid a missed-edge race
  • wait_order enforcing a required sequence
  • A demonstration of the @ vs triggered difference

You'll be able to

  • Synchronize threads with events
  • Avoid missed-event races

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Stretch45 min· Functional coverage

Coverage: transition bins and cross filtering

Extend a covergroup with transition bins on an FSM state coverpoint (A then B then C) and a cross that uses binsof/intersect with ignore_bins to drop illegal combinations, then read which transitions were missed.

Requirements

  • Transition bins on a state coverpoint
  • A cross filtered with binsof/intersect
  • ignore_bins removing illegal combinations
  • An interpretation of the missed transitions

You'll be able to

  • Cover state transitions, not just states
  • Filter illegal cross combinations

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Stretch45 min· SystemVerilog assertions

Assertions: local variables and disable iff

Write a property that captures the request's data into a local variable and checks the response carries the same value N cycles later, with disable iff(!rst_n) so a reset in the middle doesn't cause a false failure.

Requirements

  • A local variable captured on the antecedent
  • A check that the response matches the captured value
  • disable iff for reset
  • A cover proving the scenario is exercised

You'll be able to

  • Carry values through a property with local variables
  • Guard properties against reset

Submitting your solution link marks this assignment done.

Reference solutionPackUnlock with a pack

A full worked solution with a step-by-step walkthrough — included with the domain pack and All-Access. Try it yourself first.

Put it to work

Drill the matching interview questions, then see where this module sits in the full Design Verification roadmap.