Skip to practice questions

Values, shape, storage, and layout

SystemVerilog Data Types

Choose a value system, object kind, container, and bit layout deliberately—then prove the boundaries where representation changes.

A practical guide to 2-state and 4-state values, nets and variables, packed and unpacked aggregates, dynamic containers, enums, unions, casts, and streaming.

17 direct practice links6 connected chaptersReviewed July 2026
Declaration microscopeRead value, packed shape, object, then elements.
;
lane[0]byte 1byte 0
lane[1]byte 1byte 0
lane[2]byte 1byte 0
lane[3]byte 1byte 0
Value domainlogic

Four-state values preserve 0, 1, X, and Z for debug and protocol checks.

Question-first preparation

Start with a curated practice sequence.

Begin with one representative question from each mechanism, then expand the complete directory when you need a targeted drill. Premium status is shown before you leave this guide.

Recommended start

One representative prompt from each major mechanism. Open any card in the live question bank.

  1. Q0034-state data typesSystemVerilog · EasyPractice
  2. Q016Packed and unpacked arraysData Structures · EasyPractice
  3. Q005Map packed words to unpacked bytesBit Manipulation · EasyPractice
  4. Q2884-state equalitySystemVerilog · EasyPractice
  5. Q647Nets and variablesSystemVerilog · EasyPremium
  6. Q557Match uninitialized values to their data typesSystemVerilog · EasyPremium
Complete question directoryFilter every stable practice link by mechanism.17 questions
Showing 17 questions across every track.Choose a track to narrow the practice set without changing its stable question links.
  1. Q0034-state data typesSystemVerilog · EasyPractice
  2. Q2884-state equalitySystemVerilog · EasyPractice
  3. Q647Nets and variablesSystemVerilog · EasyPremium
  4. Q557Match uninitialized values to their data typesSystemVerilog · EasyPremium
  5. Q558Compare values safely with X and ZVerification Utilities · EasyPremium
  6. Q016Packed and unpacked arraysData Structures · EasyPractice
  7. Q071Dynamic arrays and queuesData Structures · EasyPractice
  8. Q229Associative arraysData Structures · EasyPractice
  9. Q219Queue methodsData Structures · EasyPractice
  10. Q049Dynamic-array resizingData Structures · EasyPractice
  11. Q195Associative-array traversalData Structures · EasyPractice
  12. Q897Choose containers from testbench access patternsSystemVerilog Data Structures · EasyPremium
  13. Q005Map packed words to unpacked bytesBit Manipulation · EasyPractice
  14. Q394Resolve an indexed part-select from a baseSystemVerilog · EasyPremium
  15. Q1008Build parameterized pack and unpack helpersBit Manipulation · MediumPremium
  16. Q148Direct Programming Interface (DPI) 4-state data mappingVerification Utilities · MediumPractice
  17. Q776Pick a weighted random enumConstraints · EasyPremium

One declaration · four representation decisions

Follow every bit until its shape and ownership are unambiguous.

Value domain, object kind, dimensionality, storage, and serialization are separate decisions. Read them in order so a convenient declaration cannot hide a lossy conversion or aliased object.

  1. 01Represent

    Choose 2-state or 4-state observability and signedness.

  2. 02Shape

    Separate contiguous packed bits from indexed elements.

  3. 03Store

    Match fixed or dynamic storage to access and lifetime.

  4. 04Translate

    Prove casts, streams, and foreign-language boundaries.

01 · Value systems and objects

Separate what a value can represent from how an object is driven.

The fastest route to correct SystemVerilog is to make two decisions independently: the value domain of the data and the object semantics of the name that carries it.

Rule to say firstChoose 2-state versus 4-state for observability, then choose net versus variable for connectivity and ownership; never use logic as shorthand for “wire plus reg.”

Two independent axes

Value domain is not object kind

Value domainObject kindVariableRetains a value; one procedural owner is the normal contract.NetRepresents connectivity and resolves its active drivers.
4-state0 · 1 · X · Z remain observable
2-stateOnly 0 · 1 remain observable
  1. 014-state variablelogic

    Stores 0, 1, X, or Z; normally one procedural owner.

  2. 024-state netwire logic

    Carries resolved values from continuous or module drivers.

  3. 032-state variablebit

    Stores binary values; assigning X/Z collapses diagnostic state.

  4. 042-state netwire bit

    A resolved connection with a 2-state data type; contention information is coerced at the declared boundary.

4-state variablelogic

Stores 0, 1, X, or Z; normally one procedural owner.

int
32-bit · 2-state
A compact simulation value when X/Z observability is not required.
integer
32-bit · 4-state
A legacy 4-state integral type; it is not an alias for int.
logic
4-state variable type
Object context still determines whether the declaration is a net or variable.

Read declarations in two passes: first the data type and value domain, then the object kind and driver model.

01

Observe

List the values that must remain observable, the number of drivers, and whether resolution is part of the interface contract.

02

Decide

Use 4-state logic where X/Z exposes initialization, contention, or tri-state behavior; use 2-state types where those states are intentionally collapsed.

03

Failure

A 2-state conversion can hide an X, while a variable with multiple procedural writers creates an ownership error rather than net resolution.

04

Prove

Lint driver ownership, assert knownness at protocol boundaries, and test conversions with 0, 1, X, and Z—not only nominal binary values.

The four-state model is diagnostic information

X can mean uninitialized, conflicting, unknown, or intentionally pessimistic data; Z represents high impedance on resolved connectivity. Those meanings are valuable at control and interface boundaries. A 2-state assignment cannot preserve them, so conversion is a deliberate loss of information.

Core integral families
TypeWidthStatesDefault signednessTypical use
bituser-shaped2unsignedCompact models and flags
logic / reguser-shaped4unsignedRTL state and observability
byte82signedCharacters and small arithmetic
shortint162signedCompact arithmetic
int322signedLoop variables and models
integer324signedLegacy 4-state arithmetic
longint642signedWide arithmetic

Nets resolve; variables retain

A net represents connectivity and may combine multiple drivers according to its net type. A variable stores the last assignment and should have a clear writer. In ports, spell out both object and data type when ambiguity would affect ownership.

  • Use wire logic for an explicitly four-state net and logic for a procedurally assigned variable.
  • Continuous assignments and module outputs naturally drive nets; procedural blocks assign variables.
  • wand and wor encode wired resolution, but ordinary datapaths should not rely on accidental multi-driver resolution.
  • Treat signedness as part of the interface: unsized literals and mixed signed expressions can change extension and comparison behavior.
Make connectivity and storage explicitsystemverilog
wire logic resolved_irq;
logic      sampled_irq;
bit        model_enable;

assign resolved_irq = irq_a;
assign resolved_irq = irq_b; // net resolution is intentional

always_ff @(posedge clk) begin
  sampled_irq <= resolved_irq; // one procedural owner
end

assert property (@(posedge clk) model_enable |-> !$isunknown(sampled_irq));

Explain it out loud

Interview reasoning checkpoints

Strong answer

No. logic is a four-state variable data type. A declaration can still be a net or a variable depending on syntax and context, and that object kind controls driving and resolution.

Reason it through
  1. Identify the data domain: four-state logic preserves X and Z.
  2. Identify the object: a net models connectivity; a variable models stored procedural state.
  3. Check ownership: multiple procedural writers are not made safe by changing reg to logic.
Interviewer lens

A strong answer separates data type from object kind and mentions driver ownership.

Common trap

Saying “logic can always be driven from anywhere” ignores port defaults, continuous drivers, and single-writer intent.

Strong answer

Both are 32-bit signed integral types, but int is 2-state and integer is 4-state. Choose based on whether X/Z observability is part of the model.

Reason it through
  1. A four-state source assigned to int loses X/Z information.
  2. That loss may be useful for performance in a reference model but dangerous at a verification boundary.
  3. Use explicit casts and knownness assertions when crossing the domains.
Interviewer lens

The key distinction is state domain, not width or signedness.

Common trap

Calling int four-state because logic is commonly used beside it.

02 · Fixed arrays and dimensionality

Packed dimensions shape bits; unpacked dimensions shape elements.

Range placement changes arithmetic, slicing, assignment compatibility, memory inference, and the order in which bits travel through a conversion.

Rule to say firstRead dimensions from the identifier outward for elements and from the type inward for contiguous bits; never infer byte order from an ascending or descending declaration alone.

Shape before syntax

One declaration, two coordinate systems

lane[0]
byte 1byte 0
Packed left-to-right significance follows declared ranges.
lane[1]
byte 1byte 0
lane[2]
byte 1byte 0
lane[3]
byte 1byte 0
  1. 01Packed plane[1:0][7:0]

    Sixteen contiguous bits; integral operators and slices apply.

  2. 02Element planelane [0:3]

    Four independently indexed packed elements.

  3. 03Total storage64 bits

    $bits reports the complete fixed-size object.

Packed plane[1:0][7:0]

Sixteen contiguous bits; integral operators and slices apply.

Packed
Integral
Supports arithmetic, reduction, concatenation, and part-selects.
Unpacked
Elements
Supports array methods and natural memory-style indexing.
Range direction
Index convention
It does not by itself define memory endianness.

A multidimensional declaration is a layout contract. Name each axis before writing a cast, slice, port, or DPI adapter.

01

Observe

Mark every packed dimension before the identifier and every unpacked dimension after it, including typedef-expanded dimensions.

02

Decide

Use packed arrays for vectors and fields that participate in integral operations; use unpacked arrays for independently indexed elements or memories.

03

Failure

Treating an unpacked byte array as a word creates assignment errors or an unintended reordering at the adapter.

04

Prove

Check $bits, $dimensions, $left, $right, $low, $high, and explicit boundary examples with non-symmetric values.

Packed versus unpacked is a semantic choice

Packed arrays form one contiguous integral value. Unpacked arrays are collections of values. Both can have many dimensions, and typedefs can hide part of the shape, so APIs should document element type and dimension order.

The identifier divides bit dimensions from element dimensionssystemverilog
typedef logic [7:0] byte4_t [0:3];

logic [1:0][7:0] lane [0:3];
byte4_t bytes;

initial begin
  assert ($bits(lane) == 64);
  lane[2][1] = 8'hA5;
  lane[2][0][3 +: 4] = 4'hC;
end

Query the declaration instead of duplicating it

Array query functions make generic code resilient to range direction and typedef changes. For a mixed array, dimension numbers enumerate unpacked dimensions first and then packed dimensions, so name the queried dimension instead of assuming a memory layout.

  • For logic [7:0] lane [0:3], dimension 1 is unpacked [0:3] and dimension 2 is packed [7:0].
  • $increment reports range direction: +1 for a descending range and -1 for an ascending range. Subtract it from an index to move from $left toward $right.
  • Use $dimensions and $unpacked_dimensions to validate an adapter before applying a dimension-specific query.
Useful shape queries
QueryAnswersReview use
$bits(expr)Total packed storage in bitsSerialization and DPI widths
$dimensions(expr)Total dimensionsGeneric shape checks
$unpacked_dimensions(expr)Unpacked dimensionsMemory and array adapters
$size(expr, n)Elements in dimension nBounds-independent loops
$left / $rightDeclared endpointsDirection-preserving traversal
$low / $highNumeric endpointsOrder-independent range checks
$increment(expr, n)+1 descending, -1 ascendingSubtract it to move from $left to $right

Explain it out loud

Interview reasoning checkpoints

Strong answer

Packed dimensions create one contiguous integral value; unpacked dimensions create a collection of elements. That difference controls operators, slicing, assignment compatibility, and often implementation intent.

Reason it through
  1. Locate dimensions relative to the identifier.
  2. Ask whether the design needs bit arithmetic or element-oriented storage.
  3. Make any crossing explicit with loops, concatenation, assignment patterns, or streaming.
Interviewer lens

Use a concrete declaration and explain where its bits and elements live.

Common trap

Reducing the distinction to syntax without explaining operations or layout.

Strong answer

No. Those ranges define index direction and significance within a SystemVerilog object. Memory byte order is a separate interface convention that must be specified at the boundary.

Reason it through
  1. Range direction tells which index is left and right.
  2. Endianness tells how multi-byte values map to addressed bytes.
  3. Use an asymmetric test word such as 32'hA53C1B7E to validate the adapter.
Interviewer lens

The answer should separate language indexing from architecture-level byte order.

Common trap

Assuming a range direction automatically defines memory layout.

03 · Dynamic storage

Choose a container by access pattern, lifetime, and ownership.

Dynamic arrays, queues, and associative arrays all grow at run time, but they solve different problems and have different copying, ordering, and missing-entry semantics.

Rule to say firstUse dynamic arrays for resize-infrequent contiguous collections, queues for ordered ends, and associative arrays for sparse key lookup; make aliasing explicit when elements are class handles.

Access-pattern selector

Three dynamic containers, three contracts

  1. 01Dynamic arraynew[N]

    Indexed collection; explicit allocation and resize.

  2. 02Queue[$]

    Ordered sequence with push/pop at the ends.

  3. 03Associative array[key_t]

    Sparse map with key-based lookup and ordered traversal rules.

Dynamic arraynew[N]

Indexed collection; explicit allocation and resize.

Resize
new[N](old)
Copies the retained prefix; allocation without old discards prior contents.
Queue bound
[$:max]
A bounded queue exposes an architectural capacity.
Traversal
first(ref key)
Returns success and writes the key through its argument.

Container selection is part of the model's algorithm and resource contract, not a cosmetic syntax preference.

01

Observe

Measure how data is inserted, removed, indexed, traversed, resized, and passed across subroutine boundaries.

02

Decide

Select the narrowest container whose methods match the dominant operation, then define bounds and failure handling.

03

Failure

An unbounded queue hides backpressure, a resized dynamic array silently loses elements, and an associative traversal that ignores the success return can use a stale key.

04

Prove

Assert capacity, check every method return, test empty and missing-key cases, and verify whether copied elements are values or shared object handles.

Allocation and resizing are observable operations

A dynamic array must be allocated before indexed use. Resizing with new_size and an optional source preserves only the overlapping prefix. Queue operations shift logical positions, while associative arrays allocate entries on demand.

Check every boundarysystemverilog
int dyn[];
int q[$:7];
int score[string];
string key;

dyn = new[4];
foreach (dyn[i]) dyn[i] = i * 10;
dyn = new[6](dyn);             // keep first four values

if (q.size() < 8) q.push_back(42);
if (!score.exists("pkt7")) score["pkt7"] = 0;

if (score.first(key)) begin    // return is success; key is an output
  do $display("%s=%0d", key, score[key]);
  while (score.next(key));
end

Copying a container does not deep-copy its object graph

Pass-by-value copies the container value. For integral elements that means independent data; for class-handle elements it copies handles, so both containers still refer to the same objects. Pass by ref when the caller's container shape must change, and clone elements when independent objects are required.

Container decision guide
NeedBest starting pointBoundary to review
Known compile-time sizeFixed unpacked arrayRange direction
Runtime size, random accessDynamic arrayResize and allocation
FIFO/deque behaviorQueueBound and empty access
Sparse numeric or string keysAssociative arrayexists and traversal
Shared mutable objectsAny handle containerClone versus alias

Methods return information—do not throw it away

delete, size, insert, push, pop, exists, first, last, next, and prev encode the container's state transitions. A pop on an empty queue or use of a missing associative entry should be handled as a protocol decision, not left to an accidental default.

  • foreach follows the declared index order; do not assume numeric ascending order for every declaration.
  • Associative iteration order is defined by the index type's ordering, not insertion order.
  • Wildcard-index associative arrays reduce type safety and portability; prefer a specific key type.
  • A queue is not a synchronization primitive—concurrent producers still need a mailbox, semaphore, or explicit protocol.

Explain it out loud

Interview reasoning checkpoints

Strong answer

Use a dynamic array for runtime-sized indexed storage, a queue for ordered insertion and removal, and an associative array for sparse key lookup. Then constrain capacity and define empty or missing access.

Reason it through
  1. Start from the dominant access operation, not just whether size changes.
  2. Account for allocation, ordering, and traversal guarantees.
  3. Verify the worst-case memory and backpressure behavior.
Interviewer lens

Good answers connect the language feature to algorithmic complexity and resource intent.

Common trap

Using an unbounded queue for every dynamic collection.

Strong answer

It copies the queue container, but class handles inside are still aliases to the same objects. A deep copy requires cloning each referenced object.

Reason it through
  1. Separate container storage from element representation.
  2. Integral elements are values; class variables are handles.
  3. Choose pass-by-reference only when the callee should change the caller's queue itself.
Interviewer lens

The expected distinction is shallow container copy versus deep object copy.

Common trap

Saying either “everything aliases” or “everything is independent.”

04 · Structures and unions

Use aggregates to make layout and validity explicit.

Structures group simultaneously valid fields. Unions overlay alternatives. Packing determines whether the aggregate has a contiguous, portable bit representation.

Rule to say firstUse a packed struct for a protocol word, an unpacked struct for a semantic record, and a tagged union when the active alternative must travel with the value.

One word, named fields

A corrected 32-bit instruction layout

  1. 01op3 bits · 5

    word[31:29]

  2. 02rd5 bits · 5

    word[28:24]

  3. 03rs15 bits · 7

    word[23:19]

  4. 04rs25 bits · 16

    word[18:14]

  5. 05imm14 bits · 14'h1B7E

    word[13:0]

op3 bits · 5

word[31:29]

Sample
32'hA53C1B7E
Asymmetric data makes ordering mistakes visible.
Packed union
Equal width
Every member occupies the same packed storage.
Unpacked aggregate
Semantic shape
It may synthesize, but has no guaranteed contiguous bit layout.

Named packed fields can replace manual slicing while keeping an exact on-wire representation.

01

Observe

Ask whether fields coexist, whether alternatives are mutually exclusive, and whether the object crosses a bit-level interface.

02

Decide

Choose struct versus union for validity and packed versus unpacked for representation; add an explicit discriminator when interpretation can vary.

03

Failure

Reading an inactive unpacked-union member is not a portable bit reinterpretation, and unequal-width packed-union members are illegal.

04

Prove

Assert $bits and member widths, round-trip asymmetric samples, and validate the discriminator before consuming a union member.

Packed structures are integral values

Members are laid out from left to right in declaration order. The first member occupies the most-significant portion of the packed aggregate. Packed structures can be sliced, compared, cast, and transferred as one bit stream.

Decode by layout, then prove the widthsystemverilog
typedef struct packed {
  logic [2:0]  op;
  logic [4:0]  rd;
  logic [4:0]  rs1;
  logic [4:0]  rs2;
  logic [13:0] imm;
} inst_t;

inst_t inst = inst_t'(32'hA53C_1B7E);

initial begin
  assert ($bits(inst_t) == 32);
  assert (inst.op  == 3'd5);
  assert (inst.rd  == 5'd5);
  assert (inst.rs1 == 5'd7);
  assert (inst.rs2 == 5'd16);
  assert (inst.imm == 14'h1B7E);
end

Union members describe alternative views

All members of a packed union must have the same packed width. An unpacked union does not promise a portable raw-bit overlay, and reading a member other than the one most recently written is undefined. A tagged union binds a legal member tag to the stored alternative where supported.

Aggregate semantics
FormMembers validBit layoutBest use
Unpacked structAllImplementation-dependentSemantic records
Packed structAllContiguous, declared orderPackets and registers
Unpacked unionOne activeNot a portable bit viewTyped alternatives
Packed unionOne interpretationEqual-width overlayExact reinterpretation
Tagged unionTag-selected memberTagged alternativeSafe variants

Explain it out loud

Interview reasoning checkpoints

Strong answer

Pack it when the fields must form one exact integral representation for a register, packet, cast, or port. Leave it unpacked when it is primarily a semantic record and physical layout is not the contract.

Reason it through
  1. Determine whether the aggregate crosses a bit-oriented boundary.
  2. If it does, define field order, width, signedness, and reserved bits.
  3. Assert $bits and round-trip a non-symmetric sample.
Interviewer lens

Mention that unpacked structs can still synthesize; packing is about representation, not synthesizability alone.

Common trap

Claiming every synthesizable struct must be packed.

Strong answer

No. Packed-union members must have equal packed width. If alternatives differ, use padding, a surrounding packed struct with a tag, or a tagged-union representation.

Reason it through
  1. A packed union provides multiple interpretations of the same storage.
  2. Different widths would leave ambiguous storage and assignment behavior.
  3. Use $bits checks near typedefs so a member change fails loudly.
Interviewer lens

The answer should distinguish packed and unpacked unions and mention active-member validity.

Common trap

Using an unpacked union as a portable type-punning mechanism.

05 · Semantic scalar types

Encode legal state spaces instead of memorizing raw numbers.

Enums, strings, time, real-valued types, and forward declarations improve intent when their conversion and tool-boundary rules are made explicit.

Rule to say firstKeep states typed, cast raw values deliberately, validate membership, and convert special simulation types at explicit model boundaries.

Typed state transition

Raw bits enter through a validation gate

  1. 01Raw encodinglogic [1:0]

    Protocol or register representation.

  2. 02Explicit caststate_t'(raw)

    Makes the representation change visible.

  3. 03Membership checkinside {IDLE, BUSY, DONE}

    Rejects unnamed encodings.

  4. 04Named behaviorstate.name()

    Readable control and diagnostics.

Raw encodinglogic [1:0]

Protocol or register representation.

Enum default
Base-type default
It is not automatically the first declared label.
byte
Signed by default
8'hFF interpreted as byte is -1 unless declared unsigned.
real
Not packed
It cannot be a member of a packed union or packed struct.

A type name improves readability only when illegal raw encodings remain observable and checked.

01

Observe

Identify values that form a closed named set, text that is testbench-only, time units that can be rounded, and types that require forward references.

02

Decide

Use enums for legal states, strings for dynamic text, time/realtime for temporal models, and typedef-forward declarations to break declaration-order dependencies.

03

Failure

An unchecked cast can create an unnamed enum value, byte signedness can turn 255 into -1, and time precision can silently round a delay.

04

Prove

Use inside or name-based checks, specify timeunit/timeprecision, test boundary characters, and keep real/string use outside synthesizable bit-level interfaces.

Enums are constraints with names

An enum defines a base integral type and a set of labels. Automatic progression, explicit encodings, .first, .last, .next, .prev, .num, and .name improve models, but a cast can still create a base value without a matching label.

Validate after crossing a raw boundarysystemverilog
typedef enum logic [1:0] {
  IDLE = 2'b00,
  BUSY = 2'b01,
  DONE = 2'b10
} state_t;

logic [1:0] raw_state;
state_t state;

always_comb begin
  state = state_t'(raw_state);
  assert (state inside {IDLE, BUSY, DONE})
    else $error("illegal state %b", raw_state);
end

Strings and special types belong at deliberate boundaries

A string is a dynamic sequence of bytes with methods for length, comparison, conversion, case, and formatting. time is a 64-bit unsigned four-state integral type; realtime is real-valued. shortreal and real model floating values but are not packed hardware fields.

  • Specify timeunit and timeprecision in each reusable scope so literal delays have a stable meaning.
  • Use $sformatf for constructed diagnostics and explicit ato*/itoa-style conversions when text crosses into numbers.
  • Use chandle for opaque foreign handles and void for intentionally discarded expression results.
  • Forward typedefs allow mutually referential class declarations; parameterized classes still need compatible specialization.
Special-type boundary checks
TypeStrengthBoundary risk
enumNamed legal statesCast can create unnamed value
stringDynamic text and methodsEncoding and synthesis support
timeIntegral simulation timeUnit and precision rounding
realtime / realFractional modelsNot a packed bit representation
chandleOpaque DPI handleLifetime and ownership live outside SV
voidDiscarded result / no return valueA task itself has no return type

Events and forward declarations are handle-level promises

An event variable is a handle to a synchronization object. Assigning one event variable to another aliases that object, so a trigger through either handle wakes waiters on the shared event. A forward class typedef similarly introduces only a class type name: it permits handle declarations before the full class, but not construction, member access, or assumptions about an incomplete definition.

  • Event assignment does not copy a pulse or create history; both handles refer to the same event object from that point forward.
  • A transient -> trigger can still be missed by a waiter that starts later; use a persistent protocol when delivery must survive timing.
  • A forward declaration must be resolved by a compatible full declaration in the same scope, including matching parameterization where applicable.
  • Before the full class definition, use the incomplete type only where a class handle type is sufficient.
Alias one event; forward-declare one classsystemverilog
typedef class packet_node;

event data_ready;
event ready_alias = data_ready;
packet_node pending; // a handle is legal before the full definition

initial fork
  begin @data_ready;   $display("shared event observed"); end
  begin #1 -> ready_alias; end
join

class packet_node;
  packet_node next;
  int payload;
endclass

Explain it out loud

Interview reasoning checkpoints

Strong answer

A raw integral value generally requires an explicit cast, and the cast does not guarantee the value matches a named label. Validate membership after untrusted inputs.

Reason it through
  1. The enum base type defines representation.
  2. The label set defines intended legal values.
  3. A cast bridges representation but does not prove legality.
Interviewer lens

Mention both type safety and the possibility of unnamed encodings.

Common trap

Assuming the enum variable always contains one of its declared labels.

Strong answer

No. Its default comes from the enum's base type: X for a four-state base or zero for a two-state base. That value may or may not correspond to the first label.

Reason it through
  1. Initialization follows the representation type.
  2. Declaration order does not override the base-type default.
  3. Reset or initialize state explicitly and assert legal state.
Interviewer lens

This tests whether the candidate separates enum naming from storage semantics.

Common trap

Relying on the first declared label as implicit reset state.

06 · Conversion and bit-stream layout

Make every representation crossing directional and testable.

Casting, assignment patterns, concatenation, part-selects, and streaming operators answer different questions. Choosing the right one prevents a visually plausible but bit-reversed adapter.

Rule to say firstUse casts for type interpretation, patterns for aggregate construction, and streaming for ordered serialization; document left alignment, slice size, signedness, and truncation.

Bit-stream adapter

Shape → order → width → interpretation

  1. 01Source shapebyte data[4]

    Unpacked elements have a declared traversal order.

  2. 02Stream order{>>8{data}}

    Right-stream in eight-bit slices.

  3. 03Target width40 bits

    A 32-bit stream occupies the left; eight zero bits fill the right.

  4. 04Typed viewpacket_t'(...)

    Cast only after layout is established.

Source shapebyte data[4]

Unpacked elements have a declared traversal order.

Indexed select
base +: width
Width is constant; index direction is explicit.
Assignment pattern
'{default: ...}
Constructs aggregate members, not a raw concatenation.
Streaming fill
Left aligned
If target is wider, remaining right-hand bits are zero.

Treat serialization as a named interface with its own assertions instead of scattering clever casts through the design.

01

Observe

Record source width, target width, packed order, element order, slice size, and whether the operation should reorder or only reinterpret.

02

Decide

Use indexed part-selects for fixed-width windows, assignment patterns for named/default fields, and streaming for general pack or unpack operations.

03

Failure

A wider streaming target is left-aligned and zero-filled on the right; assuming right alignment produces a valid-looking but wrong packet.

04

Prove

Round-trip non-palindromic data, assert $bits, compare each field, and test width mismatch, signed extension, and X/Z propagation.

Casts change type; they do not invent a protocol

A sized cast establishes width, a signed or unsigned cast changes arithmetic interpretation, and a type cast applies a destination type. None of those choices by itself specifies the byte order of an unpacked array or validates an enum encoding.

Build, stream, and round-trip explicitlysystemverilog
typedef struct packed {
  logic [7:0] kind;
  logic [7:0] len;
  logic [15:0] payload;
} packet_t;

byte unsigned bytes [0:3] = '{8'hA5, 8'h3C, 8'h1B, 8'h7E};
byte unsigned roundtrip [0:3];
logic [31:0] word;
logic [39:0] wide;
packet_t packet;

initial begin
  word   = {>>8{bytes}};
  wide   = {>>8{bytes}}; // 32-bit stream at [39:8], right-filled with 8'h00
  packet = packet_t'(word);
  {>>8{roundtrip}} = word;
  assert (roundtrip == bytes);
end

Part-selects state direction without variable width

base +: width selects upward from base; base -: width selects downward. The base may vary at run time, but width must be constant. This is safer than manually recomputing two range endpoints.

Representation tools
ToolPrimary jobQuestion to ask
type'(expr)Interpret as destination typeAre width and legality valid?
N'(expr)Resize to N bitsIs extension signed or unsigned?
'{field: value}Construct aggregateAre all members assigned?
{a, b}Concatenate packed valuesWhat is leftmost significance?
base +: W / -: WFixed-width windowWhich index direction?
{>>slice{expr}}Serialize / deserializeWhat are order and fill?

DPI representation needs an adapter contract

Two-state open arrays may map efficiently to native C element storage; four-state vectors require aval/bval-style representation so X/Z is not lost. ABI layout, element direction, ownership, and simulator lifetime must be defined rather than inferred from a C cast.

  • Use DPI helper APIs for open arrays instead of assuming contiguous native layout.
  • Do not pass pointers to temporary simulator storage beyond the call's valid lifetime.
  • Keep conversion at one boundary module and test it from both languages.
  • Include X and Z samples for four-state data mapping tests.

Explain it out loud

Interview reasoning checkpoints

Strong answer

The stream is placed at the left side of the target and unused bits on the right are zero-filled. Do not assume ordinary right-aligned numeric assignment.

Reason it through
  1. Compute the stream width independently from target width.
  2. Apply the streaming concatenation's alignment rule.
  3. Assert exact target slices with a non-symmetric sample.
Interviewer lens

A strong response states the alignment and fill direction, not only that padding occurs.

Common trap

Treating streaming as if it were an ordinary unsigned integer cast.

Strong answer

base +: width selects a constant-width range toward increasing indices; base -: width selects toward decreasing indices. The base can vary, but the width must be constant.

Reason it through
  1. Start with the declared index direction.
  2. Choose the desired base index and direction.
  3. Validate the first and last legal base values.
Interviewer lens

Look for the constant-width requirement and a correct directional example.

Common trap

Writing :+ or :-, or assuming +: always means more-significant bits.

Standards and primary references

Check the contract at its source.

IEEE Std 1800-2023 — SystemVerilogNormative language reference for data types, arrays, expressions, casts, and aggregates.Accellera SystemVerilog draft — 2-state and 4-state typesHistorical specification material describing the integral value systems and type families.Accellera clarification — packed-union widthsLanguage-committee discussion of the equal-width requirement for packed-union members.Accellera clarification — streaming alignmentClarifies stream assignment alignment and fill when source and target widths differ.Accellera tagged-union proposalBackground for discriminated union semantics and member validity.