← Design Verification Interviews

Interview Question · Concept

Putting an Integer in an Enum

L0 FresherL1 Juniorsystemverilogenumscasting

The Question

The interviewer asks

You read an opcode from a register as an int and need it in an op_t enum variable. How do you assign it, and what can go wrong?

Reveal the Model Answer

A plain assignment from int to an enum is a compile error, so you must cast. A static cast op_t'(raw) is unchecked: it stores whatever value arrives, even one with no name. $cast(op, raw) checks that the value is a member, returns 0 if not and leaves op unchanged. Use $cast with its return value tested whenever the value comes from the DUT.

A Static Cast and a Checked ConversionTwo ways to turn raw bus bits into the enum op_t (IDLE, READ, WRITE). Arrows show values moving; each token is the code being converted.
A static cast and a checked conversionTwo ways to turn raw bus bits into the enum `op_t` (IDLE, READ, WRITE). Arrows show values moving; each token is the code being converted. bus bits raw logic [1:0] from thebus cast Static castop_t'(raw) copies the bits,checks nothing check Checkedconversion $cast, or a case overthe labels enum op op_t: IDLE, READ,WRITE error Rejected reported; op keepsits value any codecode with a labelno label
  1. Static cast of 3

    The static cast copies 3 into op without looking at it. op now holds a value with no label, and op.name() returns an empty string.

    Follow the calls, values and waits
    1. data 3: raw → Static cast op_t'(raw)
    2. data 3: Static cast op_t'(raw) → op
  2. Checked conversion of 2

    The checked conversion compares 2 with the labels first. WRITE has code 2, so the value is accepted and op becomes WRITE.

    Follow the calls, values and waits
    1. data 2: raw → Checked conversion
    2. data WRITE: Checked conversion → op
  3. Checked conversion of 3

    Code 3 matches no label, so it is rejected. op keeps its old value, WRITE, and the checker can report the reserved code.

    Follow the calls, values and waits
    1. data 3: raw → Checked conversion
    2. data 3: Checked conversion → Rejected
  4. Unknown bits

    2'bx1 matches no label either, so it is rejected as well. With an int base type, a static cast would have turned the same bits into 1, a legal READ.

    Follow the calls, values and waits
    1. data x1: raw → Checked conversion
    2. data x1: Checked conversion → Rejected
Read the diagram as text
  • raw: logic [1:0] from the bus
  • Static cast op_t'(raw): copies the bits, checks nothing
  • Checked conversion: $cast, or a case over the labels
  • op: op_t: IDLE, READ, WRITE
  • Rejected: reported; op keeps its value
  • raw → Static cast op_t'(raw)
  • raw → Checked conversion
  • Static cast op_t'(raw) → op: any code
  • Checked conversion → op: code with a label
  • Checked conversion → Rejected: no label

Only the checked path stops a code that has no label.

The value 3 has no name in op_t. A static cast and $cast side by side.

RUNVerilator · simulator service
Edit the code, then run it
Expected: static cast: op=3 name="" $cast refused 3, op2 is still READ

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Fresher)

A good fresher answer knows that a direct assignment from int does not compile. It names both kinds of cast: the static cast and $cast.

Cross-Questions

Where the interviewer goes next. Open a node to practise that follow-up.

WhyWhat IfProve ItBreak ItCompare

  1. Putting an Integer in an Enum
  2. Break ItAn Enum Whose Default Is Not a MemberL1 JuniorL2 Mid-Level

    What does this print? The enum's members are 1, 2 and 4.

    systemverilog
    module tb;
      typedef enum int {START = 1, RUN = 2, STOP = 4} st_t;
      st_t s;                     // never assigned
      initial $display("default s=%0d name=\"%s\"", s, s.name());
    endmodule
    
    Reveal the Model Answer

    It prints default s=0 name="". An unassigned enum variable takes the default of its base type, here 0 for int, which is not one of the members. A decoder that expects a member then meets a value with no name. Give the variable an explicit initial member, or reset it.

    RUNVerilator · simulator service
    Edit the code, then run it
    Expected: default s=0 name=""

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "An enum variable starts at its first member."

    It starts at the base type's default: 0 for two-state, x for four-state. That equals the first member only when the first member is 0.

    Source IEEE 1800-2017 §6.19

  3. ComparePacked Structs, Packed Unions and Tagged UnionsL1 JuniorL2 Mid-Level

    Compare a packed struct, a packed union and a tagged union. The bus word is either a read command or a write command.

    Reveal the Model Answer

    A packed struct lays every field side by side, so it suits a header whose fields are all present. A packed union gives several views of the same bits. You can write through the read view and read through the write view, with no check. A tagged union also stores which member is valid. Reading the wrong member is an error, so it suits a command that is one kind or the other.

    Two Names for the Same 16 BitsA packed union hdr_u gives two names to one set of 16 bits. Arrows connect each member to those bits; tokens are values written or read.
    Two names for the same 16 bitsA packed union `hdr_u` gives two names to one set of 16 bits. Arrows connect each member to those bits; tokens are values written or read. member u.raw logic [15:0], the wireview storage Shared bits one 16-bit vector member u.f.kind bits 15:12 member u.f.addr bits 11:0 write or readbits 15:12bits 11:0
    1. Write the wire view

      u.raw = 16'h5A10 stores 16 bits. A packed union has only this one set of bits, and every member is a name for it.

      Follow the calls, values and waits
      1. data 5A10: u.raw → Shared bits
    2. Read the field view

      u.f.kind reads the top 4 bits, 5, and u.f.addr reads the low 12 bits, A10. No slicing code was needed.

      Follow the calls, values and waits
      1. data 5: Shared bits → u.f.kind
      2. data A10: Shared bits → u.f.addr
    3. Write one field

      u.f.addr = 12'hFFF overwrites bits 11 to 0 only. The top nibble, which u.f.kind reads, still holds 5.

      Follow the calls, values and waits
      1. data FFF: u.f.addr → Shared bits
    4. Read the wire view again

      u.raw now reads 16'h5FFF. Writing one member changed what the other member reads, and nothing records which member was written last.

      Follow the calls, values and waits
      1. data 5FFF: Shared bits → u.raw
    Read the diagram as text
    • u.raw: logic [15:0], the wire view
    • Shared bits: one 16-bit vector
    • u.f.kind: bits 15:12
    • u.f.addr: bits 11:0
    • u.raw → Shared bits: write or read
    • Shared bits → u.f.kind: bits 15:12
    • Shared bits → u.f.addr: bits 11:0

    Each member is a different view of the same bits, so keep union reads close to the code that captured the bus.

    Self-Check

    Tick each key point you covered in your answer.

    Half-Truth

    "A union saves memory, so use it for every variant packet."

    A packed union gives no protection: reading the wrong member just reinterprets the bits. If the code must know the kind, a tagged union or a class hierarchy says so explicitly.

    Source IEEE 1800-2017 §7.3.2

  4. WhyWhy Testbenches Use Enums for States and OpcodesL0 Fresher

    Why bother with an enum instead of localparam constants for opcodes?

    Reveal the Model Answer

    An enum is a type: assignments from unrelated integers need a cast, so a mixed-up value fails to compile. Its values carry names, so $display with %s and name(), and most waveform viewers, show WRITE instead of 2. Iteration methods such as first() and next() also let a test walk every legal value.

    Self-Check

    Tick each key point you covered in your answer.

    Half-Truth

    "Enums are only for readability."

    The cast rule is a type check that catches real bugs, and the methods let tests enumerate the legal values.

    Source IEEE 1800-2017 §6.19.5

  5. What IfWalking Every Member of an EnumL0 FresherL1 Junior

    What if a test must try every opcode? How do you loop over the enum?

    Reveal the Model Answer

    Start at first(), step with next(), and stop after last(). This covers every member, even after someone adds a new opcode. A loop over the integers 0 to N would hit gaps or miss new values. num() gives the member count, which a check can use.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Loop until next() returns an invalid value."

    next() wraps from the last member back to the first. The loop never sees an invalid value and never ends.

    Source IEEE 1800-2017 §6.19.5

  6. Prove ItSolve 1.4.2: State-Transition ValidatorSimulator-graded

    Show it, don't just say it: this Silicon Lab problem is graded by the simulator.

    Open Problem 1.4.2

What People Get Wrong

Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.

Misconception

"A static cast to an enum checks the value."

Only $cast checks. The twin static-casts 3 into a type whose members are 0, 1 and 2 and gets a value whose name() is empty.

Run It

A static cast of 3 into an enum with members 0, 1 and 2.

RUNVerilator · simulator service
Edit the code, then run it
Expected: FAIL: the static cast stored 3, a value with no enum name
See the Fix
module tb;
  typedef enum logic [1:0] {IDLE, READ, WRITE} op_t;
  op_t op = IDLE;
  int  raw = 3;
  initial begin
    if (!$cast(op, raw)) $display("PASS: $cast rejected 3 and op stayed %s", op.name());
  end
endmodule

Prints: PASS: $cast rejected 3 and op stayed IDLE

Misconception

"A failed $cast sets the variable to its first member."

The destination keeps its previous value, which is why stale values survive when the return value is ignored.

Source IEEE 1800-2017 §6.24.2

Tool as Truth

"Icarus would not run $cast, so it must not be standard."

$cast is standard; Icarus 12 does not implement it. The course runs this on Verilator for that reason.

Source Lesson 1.4 simulator note (Icarus Verilog 12 lacks $cast)

Learn It, Then Prove It