Best Practices & Coding Style
36.1 Coding guidelines
Use ieee.numeric_std; never std_logic_arith/std_logic_unsigned.
Use VHDL-2008 where tools allow (process(all), readable out ports).
One entity per file; file name = entity name.
Consistent naming:
clk, clk_100m rst (active high), rst_n (active low) _r, _reg suffix (optional) u_ or i_ prefix label every process (p_counter:)
Use named association in port and generic maps.
Keep clocked processes simple and uniform (same reset style across the design).
Avoid latches, combinational loops, gated clocks, and asynchronous logic tricks.
Parameterize with generics; compute widths with functions (log2ceil).
Synchronize all asynchronous inputs; handle every clock-domain crossing explicitly.
Register outputs of major blocks; document latency.
Comment intent (protocols, timing assumptions), not syntax.
Lint and format automatically: VSG (VHDL Style Guide), TerosHDL, Sigasi.
Version control everything, including constraints and IP configurations (store .xci/Tcl scripts, not generated outputs).
Script your builds (Tcl for Vivado/Quartus, FuseSoC, hdlmake, Edalize, Bender) for reproducibility.
Verify every block with a self-checking testbench before integration; maintain regression suites.
36.2 Common mistakes
incomplete sensitivity list sim/synth mismatch missing else/default in combinational process using a signal immediately after assigning it in a process reading the old value use variables or account for the delay driving a signal from two processes multiple drivers / 'X' one process per signal + without resize lost carry/overflow comparing vectors of different lengths with = match widths / numeric types integer without range integer range 0 to N using clk'event on non-clock signals / derived clocks asynchronous input used directly multi-bit CDC bit-by-bit async FIFO / handshake design fails in hardware create_clock for every clock relying on 'X' propagation in synthesis wait for in synthesizable code counters / ticks