Data Types Interview Questions
Master SystemVerilog data types: logic vs wire, packed vs unpacked arrays, structs, unions, and type casting.
Beginner Level
Fundamentalsreg, logic, and
wire? When would you use each?wire: Used for structural connections. Can have multiple
drivers (resolved net). Primarily for connecting module ports and continuous assignments.
reg: Legacy Verilog type. Holds a value in procedural blocks.
Despite the name, it does NOT necessarily synthesize to a register—it depends on usage.
logic: SystemVerilog's 4-state replacement for both
reg and wire. Key restriction: can only have ONE driver. This
improves simulation performance and catches accidental multi-driver bugs at compile time.
Rule: Use logic everywhere unless you specifically need a
resolved net with multiple drivers (then use wire).
packed array and an
unpacked array. Give a one-line example of each.Packed Array: Dimensions declared BEFORE the variable name. Stored as a contiguous block of bits. Can be used in arithmetic and bit-select operations.
bit [7:0] packed_byte; // 8 contiguous bits
Unpacked Array: Dimensions declared AFTER the variable name. Each element may be stored separately. Cannot be directly assigned as a single bit-vector.
bit unpacked_byte [7:0]; // 8 separate bits (potentially non-contiguous)
Key Difference: packed_byte + 1 is valid arithmetic.
unpacked_byte + 1 is a compile error.
enum? How do you iterate over all values of an enum?
An enum defines a set of named constants, improving code readability and
preventing magic numbers.
typedef enum {IDLE, RUN, DONE} state_e;
state_e current_state;
// Iterate over all values:
state_e s = s.first();
do begin
$display("State: %s", s.name());
s = s.next();
end while (s != s.first());
Methods: .first(), .last(), .next(),
.prev(), .num(), .name().
Intermediate Level
Industry Standard== and === in
SystemVerilog? When would you specifically use ===?== (Logical Equality): Returns x if either operand
contains x or z. Used for standard comparison.
=== (Case Equality): Compares bit-by-bit including
x and z values. Returns 1'b1 or 1'b0
only—never x.
Use Case for ===: Checking if a signal is explicitly
x or z, e.g., during reset verification:
if (data_out === 4'bxxxx) $display("Output is undefined!");
if (tristate_bus === 8'bzzzz_zzzz) $display("Bus is high-Z!");
typedef struct packed with a 4-bit field and an
8-bit field. What is the total size? Can you treat the entire struct as a single
bit vector?A packed struct stores all fields contiguously. Total size = 4 + 8 = 12
bits.
typedef struct packed {
logic [3:0] tag; // 4 bits
logic [7:0] data; // 8 bits
} packet_t; // Total: 12 bits
packet_t pkt;
logic [11:0] raw_bits;
raw_bits = pkt; // Valid! Direct assignment.
pkt = 12'hABC; // Valid! Assign as bit-vector.
Gotcha: If the struct were unpacked, this direct cast would NOT
be allowed.
string
variable to build a log message inside a high-speed loop. The simulation is extremely slow.
Why, and what's the fix?Problem: In SystemVerilog, string is a dynamic type. Every
concatenation like msg = {msg, "new text"} allocates new memory and copies the
old string—an O(n²) complexity nightmare inside a loop.
Fix:
- Use
$sformatf()for one-shot formatting instead of incremental concatenation. - Or, move logging outside the critical loop.
- Or, use a queue of strings and join them once at the end.
// Slow:
string msg;
for (int i = 0; i < 1000; i++) msg = {msg, $sformatf("iter %0d ", i)};
// Fast:
$display("iter %0d to %0d processed", 0, 999);
Advanced Level
Expertlines a packed or unpacked structure? Can you pass it
to a DPI-C function directly?typedef struct packed {
logic valid; // 1 bit
logic [3:0] tag; // 4 bits
logic [31:0] data; // 32 bits
} cache_line_t; // Total: 37 bits per element
cache_line_t lines [4][8]; // 4 x 8 = 32 elements
Total: 32 elements × 37 bits = 1184 bits.
Structure: cache_line_t is packed, but
lines [4][8] is an unpacked array of packed structs.
DPI-C: Cannot be passed directly! DPI-C requires packed types or specific
open_array handling. You'd need to flatten it or use
svOpenArrayHandle.
$cast() system function. When would a static cast
fail but $cast() succeeds at runtime?$cast() performs a dynamic type check at runtime, primarily
used for class handle downcasting.
class Animal; endclass
class Dog extends Animal; endclass
Animal a = new Dog();
Dog d;
// Static cast: d = Dog'(a); // Compile warning/error – no type safety check.
// Dynamic cast:
if ($cast(d, a)) $display("Cast OK! d is now a valid Dog handle.");
else $display("Cast failed. a was not pointing to a Dog.");
Key Use: When you have a base-class handle that might point to a
derived-class object, and you need to access derived-class members. $cast()
succeeds only if the runtime type is compatible.
union in SystemVerilog? Create a union that
interprets the same 32 bits as either a shortreal, an int, or a
4-byte array.A union allows multiple data types to share the same memory. Useful for
type-punning (reinterpreting bits without conversion).
typedef union packed {
shortreal f; // IEEE 754 float
int i; // Signed 32-bit integer
byte b [4]; // 4 bytes
} multi_view_t;
multi_view_t data;
data.i = 32'h41200000; // Binary for 10.0 in IEEE 754
$display("As float: %f", data.f); // Should print 10.0
$display("Byte 0: 0x%h", data.b[0]);
Caveat: Packed unions require all members to have the same bit width. For unpacked unions, members can be different types but only one is valid at a time.
byte, shortint,
int, and longint? Are they signed or unsigned by default?| Type | Bits | Default Signedness | Range |
|---|---|---|---|
byte |
8 | Signed | -128 to 127 |
shortint
|
16 | Signed | -32768 to 32767 |
int |
32 | Signed | -2³¹ to 2³¹-1 |
longint |
64 | Signed | -2⁶³ to 2⁶³-1 |
Gotcha: All are signed by default. Use
byte unsigned to get an unsigned type. This affects arithmetic and comparison
operations significantly!