Back to Interview Prep

Verilog Interview Questions - Part 2: FSM & Race Conditions

May 17, 2026 HDL2Chips Team Verilog

This part covers FSM design, race conditions, and common pitfalls in Verilog. These questions are frequently asked in mid-to-senior level digital design interviews.

Q11 Explain Mealy vs Moore state machines.

In a Moore machine, the outputs depend only on the current state, not on the inputs directly. This makes the outputs stable for a full clock cycle but may require more states. In a Mealy machine, the outputs depend on both the current state and the inputs, which can produce output changes as soon as inputs change, often resulting in fewer states. Mealy machines can respond faster but may have glitches in the output if the input is not synchronized. Both styles are synthesizable, and the choice depends on design requirements.

Q12 What are race conditions in Verilog? How can they be avoided?

A race condition occurs when the output of a simulation depends on the order of execution of concurrent statements that are scheduled in the same time slot. This happens when multiple always blocks or assignments read and write the same variable in an unpredictable order. Race conditions are avoided by using non-blocking assignments (<=) for sequential logic, using blocking assignments (=) for combinational logic inside the same always block, and not mixing both for the same variable. Proper use of the Verilog event scheduler and always blocks with well-defined sensitivity lists also helps.

Q13 How does latch inference occur in Verilog?

A latch is inferred when a combinational always @(*) block does not assign a value to a variable in all possible paths. For example, if a case or if-else statement omits an else or default clause, the synthesis tool creates a latch to hold the previous value. To avoid latches in combinational logic, always assign every output in every branch, provide a default assignment at the top of the block, and include a default in case statements.

// Latch inferred (missing default)
always @(*) begin
  if (sel) q = a;
end

// No latch (full case)
always @(*) begin
  if (sel) q = a;
  else q = b;
end
Q14 What is the difference between case, casex, and casez?

All three are used for multi-way branching. case performs exact bit-wise comparison, including x and z values. casez treats z values (and ? in the case item) as don't-care bits. casex treats both x and z as don't-care bits. casez is commonly used for priority encoders where unused bits are masked with ?. casex should be used cautiously as it may hide X-propagation bugs during simulation.

Q15 What are the differences between tasks and functions in Verilog?

Functions execute in zero simulation time, cannot contain timing controls (#delay, @, wait), must return a single value (or declared as void in SystemVerilog), and cannot call tasks. Tasks can consume simulation time, can have input, output, and inout ports, do not return a value, and can call both tasks and functions. Functions are more resource-efficient and are always synthesizable. Tasks can be synthesizable if they do not use timing controls.

Q16 Explain "full case" and "parallel case" synthesis directives.

"Full case" means all possible values of the case expression are covered, either explicitly or through a default clause. Without a full case, latches may be inferred. "Parallel case" means each case item is mutually exclusive (no overlap). If case items overlap, a priority encoder is synthesized instead of a parallel multiplexer. Synthesis tools like Synopsys support // synopsys full_case parallel_case directives, but overusing them can cause simulation-synthesis mismatches — it is better to write fully covered, non-overlapping case statements.

Q17 Write a 4:1 multiplexer using a case statement.
module mux4to1 (
  input [3:0] a,
  input [1:0] sel,
  output reg y
);
  always @(*) begin
    case (sel)
      2'b00: y = a[0];
      2'b01: y = a[1];
      2'b10: y = a[2];
      2'b11: y = a[3];
      default: y = 1'bx;
    endcase
  end
endmodule
Q18 How do you code a D flip-flop with asynchronous reset in Verilog?
module dff_async_reset (
  input clk, rst_n, d,
  output reg q
);
  always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
      q <= 1'b0;
    else
      q <= d;
  end
endmodule
Q19 Compare synchronous and asynchronous resets.

Synchronous reset is only applied at the active clock edge, making the design immune to glitches on the reset signal. However, it requires the reset to be present for at least one clock cycle and adds logic to the data path. Asynchronous reset takes effect immediately regardless of the clock, which is useful for ensuring a known state at power-up but can cause metastability if released near a clock edge. A common practice is to use an asynchronous reset with synchronous de-assertion (reset synchronizer) to combine the benefits of both.

Q20 Write an N-bit shift register in Verilog.
module shift_reg #(parameter N = 8) (
  input clk, rst_n, sin,
  output reg [N-1:0] q
);
  always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
      q <= {N{1'b0}};
    else
      q <= {q[N-2:0], sin};
  end
endmodule

Understanding FSMs, race conditions, and proper coding styles is essential for writing reliable, synthesizable Verilog. Continue to Part 3 for synthesis and testbench questions.