Most common RTL Bugs and How they are Fixed
You’ve written the code. Simulations passed. Timing looks clean. But the chip still misbehaves. You might be wondering what the issue is! Well it could be a blocking condition mis written with non - blocking condition or a missed default case statement.
In this article, we’ll walk through seven common RTL issues, each illustrated with code and its fix.
Incomplete Sensitivity:
Potential Issue: In combinational always blocks, missing signals in the sensitivity list can result in synthesis-simulation mismatches and unintended latches.
Example code:
Notice how the output ‘latch_out’ is still 0 after c is turned HIGH at 10ns. This is because the synthesis infers a latch as simulation is incorrect because ‘c’ isn’t in the sensitivity list.
Try it out: link to playground
Unused Signals, Ports:
Potential Issue: Defining signals or ports that are never used leads to extra logic or inferred latches that confuse formal tools and verification.
Example code:
Try it out: link to playground
Poor Clock Gating:
Potential Issue: Using combinational logic to gate clocks directly leads to glitches. This is dangerous because even tiny glitches can toggle flip-flops unexpectedly, breaking state machines or corrupting data paths.
Example code:
Try it out: link to playground
Non-Full case statement:
Potential Issue: Case missing a default statement and not covering all input values leads to implied latches
Example code:
Try it out: link to playground
Missing Else
Potential Issue: Missing final else in multi-branch if-else-if leads to incomplete assignments and latches.
Example code:
Try it out: link to playground
Blocking vs Non‑Blocking in Sequential Blocks
Potential Issue: Using blocking assignments (=) in sequential always @(posedge clk) blocks can lead to order-sensitive bugs that are difficult to spot.
Example code:
Width Mismatch in Assignments
Potential Issue: Assigning a wider signal to a narrower one leads to silent truncation. No error or warning by default. In control or address buses, this could be catastrophic.
Example code:
Unlike software bugs that can be patched post-release, RTL bugs get etched into silicon, often at the cost of millions. Yet, many of these issues like incomplete assignments, silent truncations, or misuse of blocking assignments are entirely preventable with the right practices.
By learning from these mistakes, not just in code but in cultural habits and review practices, you future proof your designs and contribute to robust, reliable hardware that just works.