Loading header...

Verilog Style for Synthesis

Good Verilog style is not decoration. It prevents latch bugs, width bugs, reset confusion, clock-domain mistakes, and simulation/synthesis mismatches.

Learning Objectives

By the end of this lesson, you should be able to:

  • separate combinational and sequential logic;
  • use blocking and nonblocking assignments deliberately;
  • write reviewable reset and enable logic;
  • create small modules that synthesize predictably.

Two-Block Habit

For control logic, a useful pattern is:

  1. one combinational block for next-state/output decisions;
  2. one clocked block for registers.
always @* begin
    next_state = state;
    done = 1'b0;

    case (state)
        IDLE: if (start) next_state = BUSY;
        BUSY: begin
            done = 1'b1;
            next_state = IDLE;
        end
    endcase
end

always @(posedge clk) begin
    if (rst)
        state <= IDLE;
    else
        state <= next_state;
end

Assignment Rule of Thumb

Context Assignment Why
Combinational always @* blocking = describes immediate combinational calculation
Clocked always @(posedge clk) nonblocking <= models flip-flops updating together
Continuous logic assign simple wires/LUT logic

Do not mix these randomly. When you intentionally break the rule, leave a comment explaining why.

Reset Style

Prefer clear synchronous resets unless the board or primitive requires asynchronous reset.

always @(posedge clk) begin
    if (rst) begin
        count <= 8'd0;
    end else if (en) begin
        count <= count + 8'd1;
    end
end

Reset control state. Avoid resetting huge datapaths unless the design needs a known startup value.

Review Checklist

  • Does every combinational output get a default value?
  • Are all registers assigned only in clocked blocks?
  • Are widths explicit for counters, constants, and concatenations?
  • Is every clock-domain crossing named and synchronized?
  • Are testbench-only constructs kept out of RTL?
  • Are vendor-specific primitives isolated in wrapper modules?

Exercise

Take this buggy code and rewrite it safely:

always @* begin
    if (sel)
        y = a;
end

Then explain which hardware the original code might infer and why your rewrite avoids it.

Common Mistakes

  • Missing default assignments in combinational blocks.
  • Using #delay in RTL.
  • Creating derived clocks with ordinary LUT logic.
  • Leaving width warnings unresolved.
  • Copying simulation-only code into design files.

Summary

Synthesizable Verilog should make hardware intent obvious. Keep combinational and clocked logic separate, use assignment types consistently, make widths explicit, and treat warnings as design feedback.

Next: Simulation and Testbenches.

Further Reading

  • Verilator warnings guide
  • Yosys Verilog support notes
  • Vendor FPGA HDL coding guidelines

Mind Map

mindmap root((Synthesis Style)) Core concept Write predictable RTL One clock per block Avoid inferred latches Applications Applications Portable FPGA design Code review Checks Design checks Lint warnings Resource report Common mistakes Delay statements in RTL Common mistakes Unsized constants