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:

example waveform

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:

example

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:

Example waveform

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:

example waveform

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:

example code waveform

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:

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:

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.