Common Pitfalls & Lint

Incomplete sensitivity lists, width mismatches and unused signals — bugs simulation hides, and lint catches.

Some Verilog mistakes compile and simulate without a word, then fail in hardware. The worst kind make simulation and the synthesized hardware disagree. A linter such as Verilator (--lint-only -Wall) or the lint checks built into Vivado, Quartus and commercial tools (SpyGlass, Ascent) finds most of them in seconds.

A checklist

always @(a or b) y = a & b & c;

always @(*) y = a & b & c;

A hand-written sensitivity list goes stale as soon as the logic changes; @(*) is always complete.

assign scaled = product; // 16 -> 8 bits assign scaled = product[15:8]; // say which bits you want

Explicit part-selects document the intent and silence a lint warning that would otherwise hide real truncation bugs.

Why is an incomplete sensitivity list dangerous even if simulation looks fine?

Synthesis builds combinational logic from the code regardless of the list, so the hardware reacts to every input while the simulation does not. You verified a model that does not match the chip.

What does a lint tool check that the compiler does not?

Style and intent problems that are legal Verilog: width mismatches, unused or undriven signals, blocking assignments in clocked blocks, latches, multiple drivers, clock and reset misuse, and more.