Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations57
  • Combinational Design58
  • Sequential Design61
  • FSM & Control66
  • Timing & Clocking64
  • Reset & CDC58
  • Memory & Buses94
  • Advanced RTL60
    • Parameterization and Generate Hub
    • Top-Level Integration Hub
    • Synthesis Intent Hub
    • Style and Static Checks Hub
      • Style conventions that reduce review friction
      • Lint, RDC, and waiver policy
      • Waiver rules that scale
      • Key takeaways
      • Common pitfalls
      • Worked Examples and Waveforms
      • Corner Cases and Stress Tests
      • Integration and Sign-off Notes
    • Assertions in RTL Hub
    • Formal Verification Basics Hub
    • Reusable SystemVerilog for RTL
  • Senior & Interview175
  • Glossary and Notation
Loading lesson

‹Style and Static Checks Hub
  1. Topics
  2. RTL Design
  3. Advanced RTL
  4. Style and Static Checks Hub
  5. Style conventions that reduce review friction

Part 8 · Advanced · Advanced

Style conventions that reduce review friction

Naming, reset, and process rules that make RTL read the same on every review.

On this page

    Why this matters

    A reviewer who has to guess direction, polarity or domain from a bare name misses bugs. A consistent suffix and a split between next-state decode and the state register make a diff readable.

    After this lesson you can: apply the suffix convention, keep one always_ff per clock and reset domain, and write decode with a default for every output.

    Names carry meaning

    A reviewer should learn the signal from its name. Direction, polarity, and role belong in the suffix.

    Suffix

    Meaning

    Example

    _i, _o

    Input or output port

    req_i, grant_o

    _ni

    Active-low input: n before the direction suffix

    rst_ni

    _q, _d

    Registered state, next-state decode

    state_q, state_d

    clk_i

    Clock and reset take the same _i suffix

    clk_i, rst_ni

    These are the port suffixes from the port-list lesson. In a block with two clocks, put the domain before the suffix (for example clk_fast_i), because a bare clk forces every reader to guess.

    One process per state group

    Each state element group gets one always_ff per clock and reset domain. Merging two domains into one process hides which edge updates what.

    For this FSM, the house style keeps reset/register updates in the sequential process and decisions in combinational decode. A small counter can be clearer in one process, as in the inference lesson. Neither process count alone changes the intended hardware; reset priority, enable/hold behavior and complete combinational assignments determine the function.

    Separate decode from update

    The always_comb block computes next state and outputs from current state and inputs. The always_ff block moves next state to current state on the edge.

    Every output gets a default value before the case. Then no input combination can leave an output unassigned.

    Before and after: the same FSM, two styles

    The two versions below have the same function: a request in IDLE is granted in the same cycle and the machine spends one cycle in BUSY. The first is legal and short, but a reviewer has to decode it.

    fsm_hard.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Legal, same function, hard to review
    module fsm_hard (
      input  logic clk, rst, r,
      output logic g, b
    );
      logic s;
      always_ff @(posedge clk or negedge rst)
        if (!rst) s <= 1'b0;
        else      s <= s ? 1'b0 : r;
      assign g = !s & r;
      assign b = s;
    endmodule
    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // snippet: the house-style core of style_fsm (complete module under Testbench)
    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) state_q <= IDLE;
      else         state_q <= state_d;
    end
    
    always_comb begin
      state_d = state_q;               // defaults first: no latch, no missing path
      grant_o = 1'b0;
      busy_o  = 1'b0;
      case (state_q)
        IDLE: if (req_i) begin state_d = BUSY; grant_o = 1'b1; end
        BUSY: begin state_d = IDLE; busy_o = 1'b1; end
        default: state_d = IDLE;
      endcase
    end

    Each question a reviewer asks of the first version is answered by a name or a line in the second.

    Reviewer question

    fsm_hard

    style_fsm

    Is reset active low?

    Only the negedge says so

    rst_ni: n means active low

    Which signal is state, which is input?

    s and r give no hint

    state_q is registered, req_i is an input

    What does state 1 mean?

    A bare 1'b0 / 1'b1

    Named IDLE and BUSY

    Where is the next state decided?

    Inside a ternary in the clocked block

    In always_comb, one branch per state

    Common pitfall

    A case without a default that skips a selector value infers a latch: the output must hold its old value. Assign defaults first, or add the missing branch.

    Interview

    Likely question: why split next-state decode from the state register. The answer is review: one process says what happens next, the other says when it is stored.

    Check yourself Must two state groups on one clock use separate processes?

    No. Compatible clock/reset event controls can share a process. Grouping by reset and enable intent often makes review easier, but a split FSM and a one-process counter are contextual style choices, not different hardware solely because of process count.

    Check yourself The combinational block assigns every output before its case. Which bug class disappears?

    Inferred latches. Every path assigns every output, so no output ever needs to hold state.

    Testbench

    The full FSM in the house style, plus the self-checking testbench that steps a reference model alongside it.

    style_fsm.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    module style_fsm (
      input  logic clk_i,
      input  logic rst_ni,
      input  logic req_i,
      output logic grant_o,
      output logic busy_o
    );
      localparam logic IDLE = 1'b0;
      localparam logic BUSY = 1'b1;
      logic state_q, state_d;
    
      always_ff @(posedge clk_i or negedge rst_ni) begin
        if (!rst_ni)
          state_q <= IDLE;
        else
          state_q <= state_d;
      end
    
      always_comb begin
        state_d = state_q;
        grant_o = 1'b0;
        busy_o = 1'b0;
        case (state_q)
          IDLE: if (req_i) begin
            state_d = BUSY;
            grant_o = 1'b1;
          end
          BUSY: begin
            state_d = IDLE;
            busy_o = 1'b1;
          end
          default: state_d = IDLE;
        endcase
      end
    endmodule
    

    Remember

    • Direction, polarity and role live in the suffix: req_i, grant_o, rst_ni, state_q, state_d.

    • Use one always_ff per clock and reset domain.

    • In the always_comb block, give every output a default before the case so no input combination leaves one unassigned.

    Rule of thumb: one process says what happens next, the other says when it is stored.

    How this was checked

    Testbench run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It steps a reference model alongside the FSM. The benches in this topic are finite digital checks, not lint or RDC results.

    Keep going

    • Interview: run a mock interview on this topic

    Related topics

    • Lint, RDC, and waiver policy

    • Waiver rules that scale

    Previous

    485 / 694

    Next: Lint, RDC, and waiver policy

    Up next

    Up nextLint, RDC, and waiver policy

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Waiver rules that scale
    • Key takeaways
    • Common pitfalls