Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Start Here6
  • SystemVerilog Language Foundations28
  • Object-Oriented SystemVerilog for Verification30
    • Classes, Objects & Handles
    • Inheritance and Polymorphism
      • extends and super
      • Virtual dispatch
      • Casting with $cast
      • Contracts and polymorphic containers
    • Static, Encapsulation & Parameterized Classes
    • Virtual Interfaces: the Class-to-Pins Bridge
    • Events, Semaphores, Mailboxes and Processes
    • OOP Patterns for Testbenches
  • Constraint Randomization — Interview-Critical Deep Dive36
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Inheritance and Polymorphism
  1. Topics
  2. SystemVerilog
  3. Object-Oriented SystemVerilog for Verification
  4. Inheritance and Polymorphism
  5. Casting with $cast

Part 2 · OOP for Verification · Intermediate

Casting with $cast

Implicit upcasts, checked downcasts with $cast, and the sibling-cast rule.

On this page

    Why this matters

    A function-form $cast failed, nobody checked its result, and the null handle crashed the run three lines later, far from the real mistake.

    After this lesson you can: upcast freely, downcast with $cast in function or task form, and predict when a cast fails.

    Up is free, down needs proof

    Assigning a derived handle to a base handle is an implicit, always-safe upcast. Every axi_txn is a bus_txn, so code expecting the base contract is satisfied.

    The reverse claim needs runtime proof. Direct downcast assignment is a compile error, so all downcasts go through $cast, which checks the object's real type.

    Up is free, down needs $cast, sideways never works.

    Two failure behaviors

    $cast used as a function returns 1 on success and 0 on failure, leaving the destination untouched. Used as a task, a failed cast is a simulator runtime error.

    Reach for the function form on mixed streams where a miss is normal. Reserve the task form for casts that must succeed, where failure means a wiring bug.

    Form

    On success

    On failure

    Function: if ($cast(d, s))

    Destination views the same object.

    Returns 0; destination keeps its old value.

    Task: $cast(d, s);

    Same reference transfer, no copy.

    Simulator runtime error.

    Siblings

    Never succeeds.

    Shared parent creates no sideways path.

    Common mistakes

    Common pitfall

    Casting between siblings always fails at runtime. The check $cast performs is whether the object's class is the destination class or derived from it, and a sibling is neither.

    Interview

    Likely questions: why one direction compiles and the other does not, the two $cast forms, and whether $cast copies.

    • Upcast is provably safe; downcast depends on the runtime object, so it must be checked.

    • Task failure is a runtime error; function failure returns 0 with the destination untouched.

    • $cast moves a reference, never a copy; success views the same object through a derived handle.

    Check yourself Function-form $cast fails and the code ignores the return value. What does the destination hold?

    Its old value, often null. Always branch on the return value before touching the destination.

    Testbench

    Predict first In the bench, b points at an axi_txn. What do $cast(a2, b) and $cast(h, b) return, with a2 an axi_txn handle and h an ahb_txn handle?

    1 and 0. The object really is an axi_txn, so the first cast succeeds; ahb_txn is a sibling, so the second fails and leaves h null.

    Upcast, both $cast forms, sibling rejection, and enum conversion in one self-checking block. $cast also checks an int-to-enum conversion: it returns 0 for a value with no named member, such as 7 here.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class bus_txn;
      bit [31:0] addr;
    endclass
    
    class axi_txn extends bus_txn;
      bit [3:0] qos;
    endclass
    
    class ahb_txn extends bus_txn;
      bit [7:0] hprot;
    endclass
    
    typedef enum {IDLE, BUSY, DONE} state_e;
    
    Terminal
    PASS: upcast, checked downcast, sibling rejection, enum cast all hold

    Remember

    • Derived to base is automatic; base to derived needs $cast.

    • Function form returns 0 and leaves the target alone; task form is a run-time error.

    • Siblings never cast to each other.

    Rule of thumb: check every function-form $cast before using its target.

    How this was checked

    Run with Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown, with no warnings. These class benches were run on Verilator only.

    Related topics

    • Next: Contracts and polymorphic containers

    Previous

    42 / 259

    Next: Contracts and polymorphic containers

    Up next

    Up nextContracts and polymorphic containers

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • extends and super