HDL — Verilog & VHDL — Advanced
Intermediate covered reusable, parameterized structure. This page covers three things that separate code that merely simulates correctly from code that's actually safe to synthesize into real silicon: sensitivity-list mistakes that cause simulation and synthesis to disagree, the real cost tradeoff of how you encode an FSM's state, and the single most common way real chips get corrupted data — a signal crossing between two different clock domains without proper synchronization.
Analogy — A simulation-synthesis mismatch is like a movie script that reads perfectly on paper but is physically impossible to film exactly as written — the simulator ("reading the script") accepts something a real synthesis tool ("actually filming it") either can't build at all or builds differently than the script implied. Clock domain crossing is like passing a note between two people who are each only allowed to read notes at their own randomly-timed glance — if you hand over the note at the exact instant they're mid-glance, they might read a note that's half old, half new, garbled by bad timing rather than corrupted content.
Sensitivity List Mistakes — Why Simulation and Synthesis Can Disagree
always @(*) exists specifically to eliminate this entire category of bug — every modern Verilog style guide (and every synthesis tool's own lint warnings) treats a manually-listed, incomplete sensitivity list on a combinational block as a defect to fix, not a style preference.
FSM State Encoding — Binary vs. One-Hot
RTL Design & Computer Architecture built FSMs using ordinary binary state values (parameter S0 = 2'b00, S1 = 2'b01, ...). At the HDL/synthesis level, how those states are encoded is itself a real design choice with a genuine cost tradeoff:
Neither is universally better: binary is the natural default for a small number of states or when flip-flop count is genuinely scarce; one-hot is common in FPGAs specifically (where flip-flops are relatively cheap and abundant, but combinational logic delay matters more) and in designs with a large number of states, where binary's decoding logic would otherwise become the critical path. Which encoding a synthesis tool actually uses can also be influenced by a synthesis directive/attribute rather than left entirely to the coding style — worth knowing this is a real, adjustable knob, not a fixed property of "how Verilog works."
Clock Domain Crossing (CDC) — The Double-Flop Synchronizer
Every module so far has used a single clock. Real chips commonly have multiple clock domains (a fast core clock, a slower peripheral clock) — and passing a signal directly from one clock domain to another without synchronization is one of the most common sources of real, hard-to-debug silicon bugs.
The double-flop pattern doesn't eliminate metastability's possibility — it makes the probability of metastability propagating into the rest of the design astronomically small, by giving the potentially-metastable signal a full clock period to settle before anything else depends on it. This exact pattern — not a workaround, but the standard, expected way to cross clock domains — is why real designs with multiple clocks are full of double-flop (or deeper) synchronizers at every domain boundary, and why directly reading a signal from one clock domain inside logic clocked by a different domain, without one, is treated as a real defect by any experienced RTL reviewer.
Try It (2 Minutes)
A 6-state FSM needs to be encoded. Using the bit-cost table above:
2^2 = 4 isn't enough, 2^3 = 8 is.)You should land on: binary needs 3 bits (since 2^2 = 4 < 6, but 2^3 = 8 ≥ 6); one-hot needs exactly 6 bits (one per state). Given an FPGA target and next-state logic as the bottleneck, one-hot is the reasonable direction to try — it trades 3 extra flip-flops (cheap on an FPGA) for simpler per-bit next-state logic, which is exactly the kind of tradeoff that can shorten the critical path when combinational delay, not flip-flop count, is the actual constraint.

