rtl coding guidelines
**RTL Coding for Synthesis** is the **discipline of writing Register Transfer Level hardware descriptions (Verilog/SystemVerilog/VHDL) that are both functionally correct and optimally synthesizable — where coding style directly determines the quality of the synthesized gate-level netlist in terms of area, timing, and power, because the synthesis tool's interpretation of RTL constructs follows strict inference rules that reward certain coding patterns and penalize others**.
**Synthesis-Friendly Coding Principles**
- **Fully Specified Combinational Logic**: Every if/else and case statement must cover all conditions. Missing else or incomplete case creates latches (inferred memory elements) — almost never intended and a common synthesis bug.
- **Synchronous Design**: All state elements clocked by a single clock edge. Avoid multiple clock edges, gated clocks in RTL (use synthesis-inserted clock gating), and asynchronous logic except for reset.
- **Blocking vs. Non-Blocking Assignment**: Use non-blocking (<=) for sequential logic (flip-flop outputs), blocking (=) for combinational logic. Mixing them causes simulation-synthesis mismatch.
- **FSM Coding Style**: One-hot encoding for small FSMs (low fan-in, fast), binary encoding for large FSMs (small area). Explicit enumeration of states with a default case that goes to a safe/reset state.
**SDC Timing Constraints**
Synopsys Design Constraints (SDC) is the industry-standard format for communicating timing requirements to synthesis and place-and-route tools:
- **create_clock**: Defines clock period (e.g., 1 GHz = 1 ns period). All timing analysis is relative to this.
- **set_input_delay / set_output_delay**: Models external interface timing. Tells the tool how much of the clock period is consumed by external logic.
- **set_max_delay / set_min_delay**: Constrains specific paths (e.g., multi-cycle paths, false paths).
- **set_false_path**: Excludes paths that never functionally occur from timing analysis (e.g., static configuration registers in a different clock domain).
- **set_multicycle_path**: Allows paths more than one clock cycle for setup check (e.g., a multiply that takes 3 cycles by design).
**Synthesis Optimization Strategies**
- **Resource Sharing**: Synthesis tools automatically share arithmetic operators (adders, multipliers) across mutually exclusive conditions. Coding with explicit muxing of operands helps the tool infer sharing.
- **Pipeline Register Insertion**: Adding pipeline stages (registers) breaks long combinational paths, increasing achievable clock frequency. RTL should be written with pipeline stages at logical computation boundaries.
- **Clock Gating Inference**: Writing `if (enable) q <= d;` infers clock gating — the synthesis tool inserts integrated clock gating (ICG) cells that stop the clock to the register when enable is deasserted, saving dynamic power.
**Common Pitfalls**
- **Multiply by Constant**: `a * 7` synthesizes better than `a * b` — the tool optimizes to shifts and adds.
- **Priority vs. Parallel Logic**: Nested if-else creates a priority chain (MUX cascade). case/casez creates parallel mux. Choose based on whether priority is functionally needed.
- **Register Duplication**: The synthesis tool may duplicate registers to reduce fan-out and improve timing. Excessive duplication wastes area — use dont_touch or max_fanout constraints to control.
RTL Coding for Synthesis is **the interface between the designer's functional intent and the physical gates that implement it** — where disciplined coding practices and precise timing constraints enable the synthesis tool to produce netlists that meet area, timing, and power targets on the first attempt.