0% found this document useful (0 votes)
1 views29 pages

Hardware Interview Guide

Uploaded by

chiungct
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views29 pages

Hardware Interview Guide

Uploaded by

chiungct
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Hardware Engineering

Interview Coding Guide


A from-scratch reference for RTL Design & Verification interviews

SECTION 0

Do I Need to Write 100% Correct Code?

Short answer: No, but you need to be close. You are writing
"pseudocode on a whiteboard that happens to be Verilog." The
interviewer cares that you think like a hardware designer — not that
every semicolon is in place.

W H AT I N T E R V I E W E R S F O R G I V E

Minor syntax typos (missing semicolon, misspelled signal name),


forgetting `timescale , not remembering exact SystemVerilog syntax
if you explain the intent clearly.

W H AT I N T E R V I E W E R S D O N O T F O R G I V E

Using blocking = in sequential logic. Forgetting reset. Creating


unintentional latches (missing else / default ). Not understanding
that Verilog describes parallel hardware. Inability to explain what
physical hardware your code creates.

What Matters Most (Ranked)


1. Correct architecture / logic — did you design the right
hardware?

2. Correct use of = vs <= assignments

3. Correct sensitivity lists / always block structure


4. Correct port declarations and signal widths

5. Handling of edge cases (reset, overflow, simultaneous


read/write)

6. Exact syntax (semicolons, begin / end , etc.) — least important

SECTION 1

Verilog Fundamentals (From Zero)

1.1 — What Is Verilog?

Verilog is not a programming language. It is a Hardware Description


Language (HDL). Every line describes physical wires, gates, or flip-
flops.

THE #1 CONCEPT

So(ware (C / Python): instructions execute one aZer another.


Hardware (Verilog): everything runs at the same time. Every always
block, every assign — they all run simultaneously, like physical
circuits that are always "on."

1.2 — Module: The Basic Building Block

A module is like a chip with pins — inputs, outputs, and internal


logic.
module my_and_gate (
input wire a, // input pin
input wire b, // input pin
output wire y // output pin
);
assign y = a & b; // continuous assignment (combinational)
endmodule

1.3 — Data Types

THINK OF
TYPE MEANING
IT AS…

wire Physical connection, driven by assign or A piece


module output. Cannot store a value. of copper

reg Can hold a value. Used inside always Depends


blocks. Does not always mean a register! on
context

integer 32-bit signed. Used in testbenches / loops. Loop


Not for synthesis. variable

parameter A constant. Makes modules configurable. A #define

1.4 — Number Literals

Format: <bit_width>'<base><value>

LITERAL MEANING

4'b1010 4-bit binary: 1010

8'hFF 8-bit hex: 11111111


8'd255 8-bit decimal: 255

1'b1 Single bit: 1

x Unknown (uninitialized)

z High-impedance (disconnected)

1.5 — Operators

CATEGORY OPERATORS

Bitwise & | ^ ~ (AND, OR, XOR, NOT)

Logical && || ! (for if-conditions)

Relational == != < > <= >=

ShiZ << >> (logical), <<< >>> (arithmetic)

Concatenation {a, b} merges signals

Replication {4{1'b0}} = 4'b0000

Ternary sel ? a : b (like a 2:1 mux)

Reduction &a |a ^a (reduce vector to 1 bit)

I N T E R V I E W T I P — K N OW T H E D I F F E R E N C E

& (bitwise AND): 4'b1100 & 4'b1010 = 4'b1000


&& (logical AND): (4'b1100) && (4'b1010) = 1'b1 (both nonzero)
&a (reduction AND): &4'b1110 = 1'b0 (not all bits are 1)

1.6 — Assign vs Always


Continuous Assignment — for simple combinational logic. LeZ side
must be wire .

assign y = a & b;

Procedural Block — for complex logic. LeZ side must be reg .

// COMBINATIONAL — use blocking (=)


always @(*) begin
y = a & b;
end

// SEQUENTIAL (clocked) — use non-blocking (<=)


always @(posedge clk) begin
q <= d;
end

SECTION 2

Combinational Logic Patterns

2.1 — Multiplexer (MUX)

module mux4to1 (
input wire [1:0] sel,
input wire [7:0] in0, in1, in2, in3,
output reg [7:0] out
);
always @(*) begin
case (sel)
2'b00: out = in0;
2'b01: out = in1;
2'b10: out = in2;
2'b11: out = in3;
default: out = 8'b0; // ← ALWAYS include default!
endcase
end
endmodule

W H Y D E FAU LT M AT T E R S

Without default , if sel takes an unexpected value, the synthesizer


infers a latch. Unintentional latches are the #1 synthesis bug —
interviewers watch for this.

2.2 — Decoder (2-to-4)

module decoder2to4 (
input wire [1:0] in,
input wire en,
output reg [3:0] out
);
always @(*) begin
out = 4'b0000; // default: all low
if (en) begin
case (in)
2'b00: out = 4'b0001;
2'b01: out = 4'b0010;
2'b10: out = 4'b0100;
2'b11: out = 4'b1000;
endcase
end
end
endmodule

2.3 — Priority Encoder


module priority_enc (
input wire [3:0] req,
output reg [1:0] idx,
output reg valid
);
always @(*) begin
valid = 1'b1;
casez (req)
4'b1???: idx = 2'd3; // bit 3 highest priority
4'b01??: idx = 2'd2;
4'b001?: idx = 2'd1;
4'b0001: idx = 2'd0;
default: begin
idx = 2'd0;
valid = 1'b0;
end
endcase
end
endmodule

2.4 — Parameterized Adder

module adder #(parameter N = 8) (


input wire [N-1:0] a, b,
input wire cin,
output wire [N-1:0] sum,
output wire cout
);
assign {cout, sum} = a + b + cin;
endmodule

INTERVIEW NOTE

They may ask about carry-lookahead vs ripple-carry. Ripple-carry is


simple with O(N) delay. Carry-lookahead is faster with O(log N) delay
but uses more area.
SECTION 3

Sequential Logic Patterns

3.1 — D Flip-Flop

// Synchronous Reset
always @(posedge clk) begin
if (rst) q <= 1'b0;
else q <= d;
end

// Asynchronous Reset — rst goes in sensitivity list!


always @(posedge clk or posedge rst) begin
if (rst) q <= 1'b0;
else q <= d;
end

Q: "What's the difference between sync and async reset?"

Synchronous: resets only on clock edge — cleaner timing.


Asynchronous: resets immediately when rst goes high, regardless of
clock — needed for power-on reset. Notice rst is in the sensitivity list.

3.2 — Counter

module counter #(parameter N = 8) (


input wire clk, rst, en,
output reg [N-1:0] count
);
always @(posedge clk) begin
if (rst) count <= {N{1'b0}};
else if (en) count <= count + 1'b1;
end
endmodule

3.3 — Shift Register (Serial-In, Parallel-Out)

always @(posedge clk) begin


if (rst)
parallel_out <= {N{1'b0}};
else
parallel_out <= {parallel_out[N-2:0], serial_in};
// ↑ shift left by 1 ↑ new bit at LSB
end

3.4 — Clock Divider

module clk_div #(parameter N = 4) (


input wire clk, rst,
output reg clk_out
);
reg [$clog2(N)-1:0] count;

always @(posedge clk) begin


if (rst) begin
count <= 0;
clk_out <= 1'b0;
end else if (count == N/2 - 1) begin
count <= 0;
clk_out <= ~clk_out;
end else begin
count <= count + 1'b1;
end
end
endmodule

CLASSIC TRICK QUESTION

"Design a divide-by-3 clock with 50% duty cycle." This requires using
both posedge and negedge of the clock and OR-ing the outputs.

SECTION 4

The "Big 5" Classic Interview Problems

These 5 designs appear in over 80% of hardware interviews.


Memorize the patterns.

4.1 — Synchronous FIFO MOST ASKED

A FIFO is a queue for hardware. Data enters one side and exits the
other in order. Key concepts: memory array, write/read pointers,
full/empty flags, circular buffer.

module sync_fifo #(
parameter DATA_W = 8,
parameter DEPTH = 8,
parameter PTR_W = $clog2(DEPTH)
)(
input wire clk, rst,
// Write interface
input wire wr_en,
input wire [DATA_W-1:0] wr_data,
output wire full,
// Read interface
input wire rd_en,
output reg [DATA_W-1:0] rd_data,
output wire empty
);
reg [DATA_W-1:0] mem [0:DEPTH-1];
reg [PTR_W:0] wr_ptr, rd_ptr; // 1 extra bit!

// Full & Empty detection


assign full = (wr_ptr[PTR_W] != rd_ptr[PTR_W]) &&
(wr_ptr[PTR_W-1:0] == rd_ptr[PTR_W-1:0]);
assign empty = (wr_ptr == rd_ptr);

// Write logic
always @(posedge clk) begin
if (rst)
wr_ptr <= 0;
else if (wr_en && !full) begin
mem[wr_ptr[PTR_W-1:0]] <= wr_data;
wr_ptr <= wr_ptr + 1'b1;
end
end

// Read logic
always @(posedge clk) begin
if (rst) begin
rd_ptr <= 0;
rd_data <= 0;
end else if (rd_en && !empty) begin
rd_data <= mem[rd_ptr[PTR_W-1:0]];
rd_ptr <= rd_ptr + 1'b1;
end
end
endmodule

Q: "What happens if we read and write simultaneously when full?"

The write is blocked ( wr_en && !full fails). The read proceeds,
making space. Next cycle, the write can proceed. Some designs add a
special case for simultaneous read+write when full.
Q: "Why is the pointer one bit wider than needed?"

The extra MSB distinguishes full from empty. When pointers are equal →
empty. When they differ only in the MSB → full.

Q: "How many flip-flops does this use?"

DEPTH × DATA_W for memory + 2 × (PTR_W+1) for pointers. For


DEPTH=8, DATA_W=8: 64 + 8 = 72 flip-flops.

4.2 — Arbiter (Fixed Priority)

module fixed_arb_v2 (
input wire [3:0] req,
output reg [3:0] grant
);
always @(*) begin
casez (req)
4'b???1: grant = 4'b0001;
4'b??10: grant = 4'b0010;
4'b?100: grant = 4'b0100;
4'b1000: grant = 4'b1000;
default: grant = 4'b0000;
endcase
end
endmodule

4.3 — Register Swap

// WITH temp register (blocking assignments):


always @(posedge clk) begin
temp = b; // b's value captured immediately
b = a;
a = temp;
end

// WITHOUT temp register (non-blocking assignments):


always @(posedge clk) begin
a <= b; // both RHS evaluated FIRST
b <= a; // then all LHS updated at end of time step
end

W H Y T H I S WO R K S

Non-blocking <= captures all right-hand-side values at the beginning


of the time step, then updates all leZ-hand-sides at the end. So a gets
the old value of b , and b gets the old value of a . Simultaneously.
This is hardware — two wires crossing.

4.4 — Edge Detector

module edge_detect (
input wire clk, rst, sig,
output wire rise, fall
);
reg sig_d; // delayed version

always @(posedge clk) begin


if (rst) sig_d <= 1'b0;
else sig_d <= sig;
end

assign rise = sig & ~sig_d; // was 0, now 1


assign fall = ~sig & sig_d; // was 1, now 0
endmodule
SECTION 5

Blocking vs Non-Blocking

This is tested in every hardware interview. Get this wrong = instant


reject.

THE GOLDEN RULE — MEMORIZE THIS

Combinational always @(*) → use =


logic

Sequential logic always @(posedge → use <=


clk)

Continuous assign assign y = ... → always


=

Why It Matters

B LO C K I N G ( = ) I N C LO C K E D LO G I C — B R O K E N P I P E L I N E

always @(posedge clk) begin


b = a; // b gets a's value RIGHT NOW
c = b; // c gets b's NEW value = a's value
end
// Result: b = a, c = a → SINGLE flip-flop, pipeline broken

N O N - B LO C K I N G ( < = ) I N C LO C K E D LO G I C — C O R R E C T P I P E L I N E
always @(posedge clk) begin
b <= a; // schedule: b will get a's CURRENT value
c <= b; // schedule: c will get b's CURRENT (old) value
end
// Result: b = old_a, c = old_b → TWO flip-flops in series ✓

SECTION 6

Finite State Machines (FSMs)

Moore: output depends only on current state. Mealy: output depends


on current state and current inputs (reacts faster, but can create
combinational paths).

Recommended: 3-Always-Block Style

// Sequence Detector — detects "101" on input


module seq_detect (
input wire clk, rst, din,
output reg detected
);
localparam S_IDLE = 2'b00,
S_1 = 2'b01,
S_10 = 2'b10,
S_101 = 2'b11;

reg [1:0] state, next_state;

// Block 1: State register (sequential)


always @(posedge clk) begin
if (rst) state <= S_IDLE;
else state <= next_state;
end

// Block 2: Next-state logic (combinational)


always @(*) begin
next_state = state; // default: stay
case (state)
S_IDLE: next_state = din ? S_1 : S_IDLE;
S_1: next_state = din ? S_1 : S_10;
S_10: next_state = din ? S_101 : S_IDLE;
S_101: next_state = din ? S_1 : S_10;
default: next_state = S_IDLE;
endcase
end

// Block 3: Output logic (Moore style)


always @(*) begin
detected = (state == S_101);
end
endmodule

FSM INTERVIEW TIPS

Always draw the state diagram first. Always include a default case and
reset. Assign a default value to next_state at the top. Know one-hot
(more FFs, faster decode) vs binary encoding (fewer FFs, more logic).

SECTION 7

Clock Domain Crossing (CDC)

Metastability: A flip-flop captures a signal changing right at the


clock edge (violating setup/hold time). The output oscillates
unpredictably before settling.
Solution: Two-Flop Synchronizer (single-bit signals)

module synchronizer (
input wire clk_b, rst,
input wire async_in, // from clock domain A
output wire sync_out // synchronized in domain B
);
reg sync_ff1, sync_ff2;

always @(posedge clk_b or posedge rst) begin


if (rst) begin
sync_ff1 <= 1'b0;
sync_ff2 <= 1'b0;
end else begin
sync_ff1 <= async_in; // may be metastable
sync_ff2 <= sync_ff1; // resolves metastability
end
end

assign sync_out = sync_ff2;


endmodule

M U LT I - B I T S I G N A LS → A SY N C F I F O W I T H G R AY C O D E

Gray code ensures only one bit changes per increment, so even if the
synchronizer catches it mid-transition, the error is at most off-by-one
(safe for full/empty detection).

gray = binary ^ (binary >> 1)

SECTION 8

Timing Diagrams
Interviewers will ask you to draw timing diagrams alongside your
code.

Rules for Drawing

1. Draw the clock waveform first (square wave)

2. Flip-flop outputs change aBer the active clock edge (small


delay)

3. Combinational outputs change immediately when inputs


change

4. Mark setup time (data stable before clock edge)

5. Mark hold time (data stable aBer clock edge)

Key Timing Parameters

PARAMETER SYMBOL MEANING

Setup Time Tsu How long before the clock edge data must be
stable

Hold Time Th How long aZer the clock edge data must stay
stable

Clock-to-Q Tcq Delay from clock edge to output change

If setup/hold are violated → metastability → undefined output.

SECTION 9

Synthesis Awareness
"What hardware does your code create?" — You must be able to
answer this.

CODE CONSTRUCT → HARDWARE

assign y = a & b; AND gate

assign y = sel ? a : b; 2:1 MUX

always @(posedge clk) q <= d; D Flip-Flop

case statement MUX tree or decoder

if-else chain Priority MUX

for loop (unrolled) Replicated hardware

always @(*) without full coverage LATCH (unintentional!)

Latch Inference — The Trap

B A D — C R E AT E S A L AT C H

always @(*) begin


if (sel)
y = a;
// no else! y holds old value when sel=0 → latch
end

G O O D — N O L AT C H ( T WO A P P R OAC H E S )

// Approach 1: Full if-else


always @(*) begin
if (sel) y = a;
else y = b;
end

// Approach 2: Default assignment


always @(*) begin
y = 1'b0; // default value
if (sel) y = a;
end

SECTION 10

SystemVerilog & UVM

Key SystemVerilog Additions

FEATURE WHAT IT DOES

logic Replaces both wire and reg — less confusion

always_comb Replaces always @(*) — compiler checks it's


combinational

always_ff Replaces always @(posedge clk) — compiler


checks it's sequential

always_latch Explicitly declares latch intent

Interfaces Bundle signals for cleaner port connections

Classes OOP for testbenches


Assertions assert property (...) for formal/sim checks

Constraints rand variables with constraint blocks

UVM Architecture (High Level)

UVM is a framework for building reusable, layered testbenches. The


flow:

sequence → sequencer → driver → DUT → monitor → scoreboard

COMPONENT ROLE

uvm_driver Drives stimulus to the DUT

uvm_monitor Observes DUT inputs/outputs

uvm_scoreboard Checks correctness (expected vs actual)

uvm_sequence Generates a stream of transactions

uvm_agent Groups driver + monitor + sequencer

uvm_env Top-level container for agents

SECTION 11

Python Scripting (DV/CAD Roles)

Common task: "Parse this log file and extract error information."

import re
from collections import Counter
error_counts = Counter()

with open("[Link]", "r") as f:


for line in f:
match = [Link](r"ERROR:\s*\[(\w+)\]", line)
if match:
error_counts[[Link](1)] += 1

for err_type, count in error_counts.most_common():


print(f"{err_type}: {count}")

Bit manipulation in Python:

value = 0xDEADBEEF
# Extract bits [15:8]
field = (value >> 8) & 0xFF # → 0xBE

SECTION 12

C/C++ for Firmware & Embedded

#include <stdint.h>

// Set bit n
uint32_t set_bit(uint32_t reg, int n) {
return reg | (1U << n);
}

// Clear bit n
uint32_t clear_bit(uint32_t reg, int n) {
return reg & ~(1U << n);
}
// Toggle bit n
uint32_t toggle_bit(uint32_t reg, int n) {
return reg ^ (1U << n);
}

// Extract bit field [high:low]


uint32_t extract_field(uint32_t reg, int high, int low) {
uint32_t mask = ((1U << (high - low + 1)) - 1) << low;
return (reg & mask) >> low;
}

Q: "Why volatile ?"

Tells the compiler the value can change at any time (hardware can
update it), so don't optimize away reads/writes to this address.

Q: "Is x a power of 2?"

(x != 0) && ((x & (x - 1)) == 0) — Classic trick. x-1 flips all


bits below the single set bit.

SECTION 13

Real Interview Questions from Industry

Reported from Intel, AMD, NVIDIA, Qualcomm, Broadcom, Cadence,


Synopsys, Apple, Google, and Amazon (Annapurna Labs).

RTL Design Questions

1. Design a synchronous FIFO with depth 8 and data width 8.


Follow-up: What happens on simultaneous read+write when full?
2. Design a parameterized N-bit counter with enable and reset.

3. Implement a priority encoder for 8 inputs.

4. Design a round-robin arbiter for 4 requestors.

5. Implement a sequence detector FSM for "1011" (overlapping).


6. Swap two registers without a temp register. Explain why it
works.

7. Write a 4:1 mux using (a) case, (b) ternary, (c) if-else.

8. Design a divide-by-3 clock with 50% duty cycle.


9. Sync vs async reset — write Verilog for both.

10. Write code that infers a latch. Now fix it.

11. Given b <= a; c <= b; — draw the timing diagram.

12. Design an asynchronous FIFO. Explain Gray code pointers.

13. What is metastability? How do you solve it?


14. Implement a dual-port RAM.

15. Design a CDC circuit for a single-bit signal.

16. Write a Moore FSM with 4 states.

17. Mealy vs Moore — what's the difference?

18. What does casez do differently from case ?


19. How do you avoid latch inference?

20. Design a serial-to-parallel converter.

Verification Questions

21. Explain the UVM testbench architecture.

22. Task vs function in SystemVerilog?

23. Write a constrained random class for valid Ethernet frames.

24. Functional coverage vs code coverage?


25. Write an assertion: "req must be followed by ack within 5
cycles."

26. What is a virtual function? Why use it in UVM?

Digital Logic & Concept Questions

27. Setup time and hold time?

28. Critical path? How to fix timing violations?


29. Explain pipelining and its trade-offs.

30. Clock skew vs clock jitter?

31. How does an async FIFO handle CDC?

32. What is DFT? What is scan chain?

33. Power gating vs clock gating?


34. FPGA vs ASIC flows?

SECTION 14

Interview Format & Strategy

Typical Structure

ROUND FORMAT CONTENT

Phone 45–60 Resume + technical Q&A (concepts, maybe


Screen min simple coding)

On-site 1 45–60 RTL Coding — spec → module → edge cases →


min synthesis

On-site 2 45–60 Digital Logic / Architecture — timing


min diagrams, pipelines

On-site 3 45–60 Verification (DV) or Scripting, or system


min design

On-site 4 45–60 Behavioral — past projects, debugging,


min teamwork

How to Approach the Coding Question

1. Clarify the spec — ask questions! Data width? Depth? Sync or


async? Overflow behavior?

2. Draw the block diagram first — show you can visualize


hardware before writing code. This alone can save you if your
code has bugs.

3. Write the module header — get the interface (ports) right


before any logic.

4. Write the logic — start with reset, then normal operation,


always add default/else.
5. Trace edge cases — reset, boundary conditions (full/empty),
simultaneous operations.

6. Discuss synthesis — how many flip-flops? Critical path? Any


latches?

SECTION 15

Resources & Links

Online Resources
RESOURCE BEST FOR

HDLBits ([Link]) Interactive Verilog exercises — best


for practice

ChipVerify ([Link]) Free Verilog/SV tutorials &


interview questions

FPGA4Student ([Link]) Complete Verilog projects with


code

Nandland ([Link]) Beginner-friendly Verilog & FPGA


tutorials

ASIC World ([Link]) Comprehensive Verilog reference

GitHub: RTL interview problems with


pengwubj/hw_interview_questions solutions

Books

BOOK BEST FOR

"Digital Design and Computer Architecture" Best intro to digital


— Harris & Harris design + Verilog

"Verilog HDL" — Samir Palnitkar The classic Verilog


reference

"SystemVerilog for Verification" — Chris Essential for DV roles


Spear

"CMOS VLSI Design" — Weste & Harris Transistor-level &


synthesis
Practice Strategy

1. Do all exercises on HDLBits (free, interactive, auto-graded)

2. Code the Big 5 from memory until you can write each in 15
minutes

3. For each design, practice: block diagram → code → timing


diagram → "what hardware?"

4. Review 5 interview questions per day from ChipVerify

5. If targeting DV roles, also study UVM architecture

QUICK REFERENCE

Cheat Sheet

TOPIC RULE

Combinational always @(*) + =

Sequential always @(posedge clk) + <=

Avoid Latches Always assign default values or cover all cases

FIFO Extra MSB on pointers. Empty: wr==rd . Full: MSBs


Full/Empty differ, rest equal.

CDC (1-bit) Two-flop synchronizer

CDC (multi- Async FIFO with Gray code pointers


bit)

FSM Style 3-block: state reg, next-state logic, output logic

Power of 2? (x != 0) && ((x & (x-1)) == 0)


Gray Code gray = bin ^ (bin >> 1)

Good luck with your interviews.

You might also like