SystemVerilog & Verilog Tricky Interview Questions Part1

Coding Snippets with Detailed Answers

📌 Question 1: Byte Loop Overflow

byte a;
 
for(a = 0; a < 150; a++) begin
    $display("Value is a %d", a);
end

Question: How many times will this loop execute?

Answer: Infinite loop! ♾️

Explanation:

  • byte is a signed 8-bit type with range: -128 to 127
  • Loop starts at a = 0
  • When a reaches 127 and increments, it overflows to -128
  • Since -128 < 150, the loop continues indefinitely
  • The loop will never terminate because a can never reach 150

Fix: Use int or check for signed overflow:

int a;  // or byte unsigned a;

📌 Question 2: Mixed Data Types with X

bit[7:0] a = 7;
logic[7:0] b = 'x;
int c;
integer d;

initial begin
    c = a + b;
    d = a + b;
end

Question: What is the output of c and d?

Answer:

  • c = X (unknown)
  • d = X (unknown)

Explanation:

  • bit is a 2-state type (0, 1)
  • logic is a 4-state type (0, 1, X, Z)
  • When b = 'x, all bits are X
  • Any arithmetic with X propagates X
  • Both int and integer will contain X since the operation involves X
  • Note: int is 2-state but can contain X during simulation when assigned from 4-state logic

Corrected version of question with subtraction:

c = a - b;  // c = X
d = a - b;  // d = X

Result is the same – both are X.

📌 Question 3: Signed vs Unsigned Comparison

bit [7:0] a = 8'hFF;
byte b = 8'hFF;

initial begin
    if (a > b)
        $display("a is greater");
    else if (a < b)
        $display("b is greater");
    else
        $display("Equal");
end

Question: What will be displayed?

Answer: “a is greater”

Explanation:

  • bit [7:0] a = 8'hFF → unsigned, value = 255
  • byte b = 8'hFF → signed, value = -1 (two’s complement)
  • Comparison: 255 > -1 → TRUE
  • SystemVerilog promotes both to largest size and signedness during comparison
  • Since one is unsigned and one is signed, comparison uses signed arithmetic
  • -1 (b) is extended to match size: still negative
  • 255 > -1, so “a is greater”

📌 Question 4: Array Size Confusion

logic [7:0] mem [0:255];

initial begin
    $display("Array size: %0d", $size(mem));
    $display("Element size: %0d", $bits(mem[0]));
end

Question: What will be displayed?

Answer:

  • Array size: 256
  • Element size: 8

Explanation:

  • mem is an unpacked array with 256 elements (0 to 255)
  • $size(mem) returns number of elements = 256
  • Each element is logic [7:0] = 8 bits
  • $bits(mem[0]) returns 8

📌 Question 5: Blocking vs Non-Blocking Assignment

reg [3:0] a, b, c;

initial begin
    a = 4'h5;
    b = 4'h3;
    
    a = b;
    b = a;
    
    $display("a = %h, b = %h", a, b);
end

Question: What are the values of a and b?

Answer:

  • a = 3
  • b = 3

Explanation:

  • Blocking assignments execute sequentially
  • a = b; → a becomes 3
  • b = a; → b becomes 3 (current value of a)
  • Both end up with value 3

Now with non-blocking:

initial begin
    a <= b;
    b <= a;
    #1 $display("a = %h, b = %h", a, b);
end

Result: a = 3, b = 5 (values swap)

📌 Question 6: For Loop with Logic

logic [3:0] i;

initial begin
    for (i = 0; i < 20; i++) begin
        $display("i = %0d", i);
    end
    $display("Final i = %0d", i);
end

Question: How many iterations and what is final value?

Answer:

  • 16 iterations (0 to 15)
  • Final i = 0

Explanation:

  • logic [3:0] is 4-bit, can hold values 0-15
  • Loop runs from 0 to 15
  • When i = 15 and increments, it wraps to 0 (4-bit overflow)
  • At i = 0, condition 0 < 20 is true, but we’ve already printed 0-15
  • Actually, infinite loop! Because i wraps from 15 to 0

Correct Answer: Infinite loop – it keeps cycling 0→15→0→15…

📌 Question 7: Queue Operations

int queue[$] = {1, 2, 3, 4, 5};

initial begin
    queue.delete(2);
    queue.push_front(0);
    $display("Queue: %p", queue);
    $display("Size: %0d", queue.size());
end

Question: What will be displayed?

Answer:

  • Queue: {0, 1, 2, 4, 5}
  • Size: 5

Explanation:

  • Initial queue: {1, 2, 3, 4, 5}
  • delete(2) removes element at index 2 (value 3): {1, 2, 4, 5}
  • push_front(0) adds 0 at front: {0, 1, 2, 4, 5}
  • Final size: 5

📌 Question 8: Dynamic Array Sizing

int dyn[];

initial begin
    dyn = new[5];
    foreach(dyn[i]) dyn[i] = i * 2;
    
    dyn = new[3](dyn);
    
    $display("Size: %0d", dyn.size());
    $display("Elements: %p", dyn);
end

Question: What is the output?

Answer:

  • Size: 3
  • Elements: {0, 2, 4}

Explanation:

  • Initially creates array of size 5: {0, 2, 4, 6, 8}
  • new[3](dyn) resizes to 3, copying first 3 elements
  • Elements beyond index 2 are discarded
  • Result: {0, 2, 4}

📌 Question 9: String Comparison

string s1 = "Hello";
string s2 = "hello";

initial begin
    if (s1 == s2)
        $display("Equal");
    else if (s1.toupper() == s2.toupper())
        $display("Case insensitive equal");
    else
        $display("Not equal");
end

Question: What will be displayed?

Answer: “Case insensitive equal”

Explanation:

  • s1 == s2 → “Hello” != “hello” (case sensitive)
  • s1.toupper() → “HELLO”
  • s2.toupper() → “HELLO”
  • “HELLO” == “HELLO” → TRUE

📌 Question 10: Packed Array Indexing

bit [3:0][7:0] data = 32'hDEADBEEF;

initial begin
    $display("data[0] = %h", data[0]);
    $display("data[3] = %h", data[3]);
    $display("data[1][4] = %b", data[1][4]);
end

Question: What will be displayed?

Answer:

  • data[0] = EF
  • data[3] = DE
  • data[1][4] = 1

Explanation:

  • bit [3:0][7:0] is packed array: 4 bytes
  • Storage: [3]=DE [2]=AD [1]=BE [0]=EF (big-endian indexing)
  • data[0] = rightmost byte = EF
  • data[3] = leftmost byte = DE
  • data[1] = BE = 8’b10111110
  • data[1][4] = bit 4 of BE = 1

📌 Question 11: Associative Array

int assoc[string];

initial begin
    assoc["apple"] = 10;
    assoc["banana"] = 20;
    assoc["apple"] = 30;
    
    $display("Size: %0d", assoc.num());
    $display("apple: %0d", assoc["apple"]);
end

Question: What is the output?

Answer:

  • Size: 2
  • apple: 30

Explanation:

  • Associative arrays use unique keys
  • First assignment: assoc[“apple”] = 10
  • Second assignment: assoc[“banana”] = 20
  • Third assignment: overwrites assoc[“apple”] = 30
  • Only 2 unique keys exist: “apple” and “banana”

📌 Question 12: Randomization with Constraint

class Packet;
    rand bit [3:0] addr;
    rand bit [7:0] data;
    
    constraint c1 { addr < 10; }
    constraint c2 { data inside {[0:50]}; }
endclass

Packet p = new();

initial begin
    repeat(3) begin
        p.randomize() with { addr == 5; data > 40; };
        $display("addr=%0d, data=%0d", p.addr, p.data);
    end
end

Question: What are the possible outputs?

Answer:

  • addr will always be 5
  • data will be between 41-50

Explanation:

  • Inline constraint addr == 5 overrides c1
  • Inline constraint data > 40 combines with c2
  • Combined constraint: data inside {[0:50]} AND data > 40
  • Result: data ∈ [41, 50]

📌 Question 13: Always Block Race

reg clk = 0;
reg [3:0] a, b;

always #5 clk = ~clk;

always @(posedge clk) begin
    a <= a + 1;
    b = a;
end

initial begin
    #100;
    $display("a = %0d, b = %0d", a, b);
end

Question: What is the relationship between a and b?

Answer: b is always one cycle behind a

Explanation:

  • a <= a + 1 is non-blocking, schedules update
  • b = a is blocking, reads current value of a
  • At each clock edge:
    • b gets old value of a
    • a gets updated after NBA region
  • If a = 5, then b = 4

📌 Question 14: Case Statement with X

logic [1:0] sel = 2'b1x;
logic [3:0] out;

always_comb begin
    case(sel)
        2'b00: out = 4'h1;
        2'b01: out = 4'h2;
        2'b10: out = 4'h3;
        2'b11: out = 4'h4;
        default: out = 4'hF;
    endcase
end

Question: What is the value of out?

Answer: out = 4’hF (default case)

Explanation:

  • sel = 2'b1x contains X
  • Regular case requires exact match
  • 2’b1x doesn’t match any specific case
  • Falls through to default

If using casez or casex:

casez(sel)
    2'b1?: out = 4'h3;  // This would match!
endcase

📌 Question 15: Parameter Override

module counter #(parameter WIDTH = 4) (
    input logic clk,
    output logic [WIDTH-1:0] count
);
    always_ff @(posedge clk)
        count <= count + 1;
endmodule

module top;
    logic clk;
    logic [7:0] cnt;
    
    counter #(8) c1 (.clk(clk), .count(cnt));
endmodule

Question: What is the width of count in instance c1?

Answer: 8 bits

Explanation:

  • Parameter override: #(8) sets WIDTH = 8
  • count is declared as [WIDTH-1:0] = [7:0]
  • Top module cnt is also [7:0], so widths match

📌 Question 16: Enum Assignment

typedef enum {RED, GREEN, BLUE} color_t;
color_t color;
int val;

initial begin
    color = RED;
    val = color;
    $display("val = %0d", val);
    
    color = color_t'(2);
    $display("color = %s", color.name());
end

Question: What will be displayed?

Answer:

  • val = 0
  • color = BLUE

Explanation:

  • Enums have implicit integer values: RED=0, GREEN=1, BLUE=2
  • val = color → val = 0
  • color_t'(2) casts integer 2 to enum → BLUE
  • color.name() returns “BLUE”

📌 Question 17: Bit Slice Assignment

bit [15:0] data = 16'hABCD;

initial begin
    data[7:4] = 4'h5;
    $display("data = %h", data);
    
    {data[15:8], data[3:0]} = 12'h123;
    $display("data = %h", data);
end

Question: What are the outputs?

Answer:

  • First: data = AB5D
  • Second: data = 1253

Explanation:

  • Initial: data = ABCD
  • data[7:4] = 4'h5 → AB5D (middle nibble changed)
  • {data[15:8], data[3:0]} = 12'h123:
    • Upper byte gets 4’h1 → 0x01
    • Lower nibble gets 8’h23[3:0] → 0x3
    • Middle nibble unchanged: 5
    • Result: 1253

Wait, let me recalculate:

  • {data[15:8], data[3:0]} is 12 bits
  • 12'h123 assigns: data[15:8] = 4’h1, data[3:0] = 8’h23
  • But 8’h23 is 8 bits, only 4 bits go to data[3:0]
  • Actually: data[15:8] = 8’h12, data[3:0] = 4’h3
  • Result: 125D (data[7:4] = 5 unchanged)

Correct Answer:

  • First: data = AB5D
  • Second: data = 1253 (8-bit MSB = 0x12, 4-bit LSB = 0x3, middle 4 bits = 5)

📌 Question 18: Virtual Function Call

class Base;
    virtual function void display();
        $display("Base");
    endfunction
endclass

class Extended extends Base;
    function void display();
        $display("Extended");
    endfunction
endclass

Base b = new();
Extended e = new();
Base b_ptr = e;

initial begin
    b.display();
    e.display();
    b_ptr.display();
end

Question: What will be displayed?

Answer:

  • Base
  • Extended
  • Extended

Explanation:

  • b.display() → calls Base::display() → “Base”
  • e.display() → calls Extended::display() → “Extended”
  • b_ptr = e → Base handle pointing to Extended object
  • b_ptr.display() → virtual function, calls Extended::display() → “Extended”

📌 Question 19: Generate Block Scope

module test;
    parameter N = 3;
    
    generate
        for (genvar i = 0; i < N; i++) begin : gen_block
            logic [7:0] data = i * 10;
            initial $display("Block %0d: data = %0d", i, data);
        end
    endgenerate
    
    initial begin
        #1 $display("Access: %0d", gen_block[1].data);
    end
endmodule

Question: What will be displayed?

Answer:

  • Block 0: data = 0
  • Block 1: data = 10
  • Block 2: data = 20
  • Access: 10

Explanation:

  • Generate creates 3 instances: gen_block[0], gen_block[1], gen_block[2]
  • Each has its own data variable
  • Can access via hierarchical name: gen_block[1].data

📌 Question 20: Shallow vs Deep Copy

class Inner;
    int value = 10;
endclass

class Outer;
    Inner inner_obj;
    int data = 5;
    
    function new();
        inner_obj = new();
    endfunction
endclass

Outer o1 = new();
Outer o2 = new();

initial begin
    o2 = o1;  // Shallow copy
    o2.data = 20;
    o2.inner_obj.value = 50;
    
    $display("o1.data = %0d", o1.data);
    $display("o1.inner_obj.value = %0d", o1.inner_obj.value);
end

Question: What are the values in o1?

Answer:

  • o1.data = 5
  • o1.inner_obj.value = 50

Explanation:

  • o2 = o1 is shallow copy (reference copy)
  • Both o1 and o2 point to same object
  • o2.data = 20 changes the shared object
  • Wait, that’s wrong! Let me reconsider…

Actually:

  • o2 = o1 makes o2 handle point to o1’s object
  • o2’s original object is lost
  • Both o2 and o1 point to same object now
  • o2.data = 20 → changes o1.data to 20
  • o2.inner_obj.value = 50 → changes o1.inner_obj.value to 50

Correct Answer:

  • o1.data = 20
  • o1.inner_obj.value = 50

Both are modified because they share the same object!

📌 Question 21: Packed Union

typedef union packed {
    bit [31:0] word;
    bit [3:0][7:0] bytes;
    struct packed {
        bit [15:0] upper;
        bit [15:0] lower;
    } half;
} data_t;

data_t d;

initial begin
    d.word = 32'hDEADBEEF;
    $display("bytes[0] = %h", d.bytes[0]);
    $display("upper = %h", d.half.upper);
end

Question: What will be displayed?

Answer:

  • bytes[0] = EF
  • upper = DEAD

Explanation:

  • Packed union: all members share same memory
  • d.word = 0xDEADBEEF
  • Byte order: [3]=DE, [2]=AD, [1]=BE, [0]=EF
  • d.bytes[0] = EF (rightmost byte)
  • d.half.upper = upper 16 bits = DEAD

📌 Question 22: Constraint with Array

class Packet;
    rand bit [7:0] len;
    rand bit [7:0] data[];
    
    constraint c_len { len inside {[5:10]}; }
    constraint c_data { data.size() == len; }
    constraint c_values { foreach(data[i]) data[i] < 50; }
endclass

Packet p = new();

initial begin
    if (p.randomize())
        $display("len=%0d, size=%0d", p.len, p.data.size());
end

Question: What can be the output?

Answer: Examples:

  • len=5, size=5
  • len=7, size=7
  • len=10, size=10

Explanation:

  • len is randomized to 5-10
  • data array size is constrained to match len
  • All data values will be < 50
  • Size always equals len

📌 Question 23: Always_comb with Latch

logic [3:0] a, b, sel, out;

always_comb begin
    if (sel == 0)
        out = a;
    else if (sel == 1)
        out = b;
end

Question: What happens when sel = 2?

Answer: Tool will give ERROR or WARNING

Explanation:

  • always_comb requires all paths assign all variables
  • When sel = 2 or 3, out is not assigned
  • This implies a latch (unintended memory)
  • Most tools will flag this as error with always_comb
  • Need to add else clause or default assignment

Fix:

always_comb begin
    out = '0;  // Default
    if (sel == 0)
        out = a;
    else if (sel == 1)
        out = b;
end

📌 Question 24: Function with Automatic

function int factorial(int n);
    if (n <= 1)
        return 1;
    else
        return n * factorial(n-1);
endfunction

initial begin
    $display("5! = %0d", factorial(5));
end

Question: Will this work correctly?

Answer: NO! Will likely crash or give wrong result

Explanation:

  • Function is static by default (single copy of variables)
  • Recursive calls will overwrite the same variable storage
  • Need automatic keyword for recursion

Fix:

function automatic int factorial(int n);
    // Now it works!
endfunction

📌 Question 25: X Propagation in Arithmetic

logic [3:0] a = 4'b10x1;
logic [3:0] b = 4'b0010;
logic [3:0] sum, product;

initial begin
    sum = a + b;
    product = a * b;
    $display("sum = %b", sum);
    $display("product = %b", product);
end

Question: What are sum and product?

Answer:

  • sum = xxxx (all X)
  • product = xxxx (all X)

Explanation:

  • Arithmetic with any X propagates X to entire result
  • 10x1 + 0010 → X in any bit position → entire result is X
  • Multiplication same behavior
  • X is pessimistic – contaminates entire result

Summary Statistics

Total Questions: 25

Categories Covered:

  • ✅ Data type overflow/underflow
  • ✅ Signed/unsigned operations
  • ✅ Blocking vs non-blocking
  • ✅ Array operations (dynamic, queue, associative, packed)
  • ✅ X/Z propagation
  • ✅ Object-oriented programming
  • ✅ Randomization and constraints
  • ✅ Generate blocks
  • ✅ Union and struct
  • ✅ Enum operations
  • ✅ Virtual functions
  • ✅ Always_comb behavior
  • ✅ Function recursion
  • ✅ Race conditions

Key Takeaways for Interviews

  1. Know your data types: bit vs logic, signed vs unsigned
  2. Watch for overflow: byte, shortint loop counters
  3. X propagation: Arithmetic with X → result is X
  4. Blocking vs NBA: Understand the difference in always blocks
  5. Array indexing: Packed arrays use big-endian [MSB:LSB]
  6. Shallow copy: Handle assignment copies reference, not object
  7. Virtual functions: Enable runtime polymorphism
  8. Constraints: Can be combined with inline constraints
  9. Always_comb: Must assign all outputs on all paths
  10. Automatic: Required for recursive functions

These questions test deep understanding of SystemVerilog semantics and are commonly asked in advanced RTL/Verification interviews!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top