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

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
    • Parameterization and Generate Hub
    • Top-Level Integration Hub
    • Synthesis Intent Hub
      • Inference-focused coding style
      • Inferring flip-flops and RAM
      • Latch avoidance and case semantics
      • Reading a synthesis report
    • Style and Static Checks Hub
    • Assertions in RTL Hub
    • Formal Verification Basics Hub
    • Reusable SystemVerilog for RTL
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

←Synthesis Intent Hub
  1. Topics
  2. RTL Design
  3. Advanced RTL
  4. Synthesis Intent Hub
  5. Inference-focused coding style
On this page

    Part 8 of 9, lesson 7 of 28Part 8 of 9/Advanced/Lesson 7 of 28Advanced

    Inference-focused coding style

    One counter written two ways, with the template that keeps synthesis predictable.

    Two counters with the same function can map to different netlists, and the cause is usually reset, enable or a cell the tool did not recognise, not the number of processes. Blaming the style wastes the investigation.

    After this lesson you can: write reset, enable and memory logic in the canonical templates, and investigate a netlist difference by comparing function, supported cells and constraints.

    Write what the tool recognises

    Synthesis recognises reset, enable and memory intent from a small set of supported patterns. Write each storage element in its canonical template, then read the mapping report to see what was built.

    Pattern

    Semantic intent

    What to check in the report

    always_ff with reset first, then enable

    Reset-priority storage with hold when disabled

    Enable cell versus feedback mux in the mapped netlist

    Array with clocked write and registered read

    Synchronous memory with explicit collision behaviour

    Selected RAM resource, supported ports and collision mode

    always_comb assigning every output first

    Combinational function

    No unintended storage; exact gates are target-dependent

    One counter, two codings

    Both counters below describe the same hardware: an 8-bit register with asynchronous reset, an enable, and an incrementer. The first splits next-state logic into its own combinational block; the second uses the single-block template. The comments mark the three things that decide the netlist.

    cnt_before.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
    module cnt_before (
      input logic clk, rst_n, en,
      output logic [7:0] q
    );
      logic [7:0] next;
      always_comb begin
        next = q;                      // hold path: en low keeps q (an enable, not a latch)
        if (en) next = q + 8'd1;       // incrementer: 8 bits, wraps from ff to 00
      end
      always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) q <= '0;           // reset first: wins over en
        else q <= next;
      end
    endmodule
    
    module cnt_after (
      input logic clk, rst_n, en,
      output logic [7:0] q
    );
      always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) q <= '0;           // reset first: wins over en
        else if (en) q <= q + 8'd1;    // no else: the register holds, which is the enable
      end
    endmodule

    Read the two side by side: reset priority, the hold path when en is low, and the increment width are the same in both. Those three facts, not the number of processes, set the hardware. On an iCE40 target both counters map to the same 23 cells: 8 flip-flops with enable and asynchronous reset (SB_DFFER), 9 LUTs and 6 carry cells. In both, synthesis found the hold path and folded it into the flops' enable pin.

    Try it: save both modules as cnt.sv and map each one separately with identical options, using the two commands below. Look for SB_DFFER (a flop with an enable pin) rather than a plain flop plus a LUT mux per bit.

    Diagram
    yosys -p "read_verilog -sv cnt.sv; synth_ice40 -top cnt_before; stat"
    yosys -p "read_verilog -sv cnt.sv; synth_ice40 -top cnt_after; stat"

    The testbench under Testbench drives both counters with the same reset and enable sequence and flags any cycle where they disagree.

    Common mistakes

    Process count alone does not change the intended hardware. Both counters describe the same reset, enable and increment function. One process is compact for this small counter; separate decode and update is useful for an FSM. In either style, keep reset priority and the disabled hold path.

    Likely question: “Two identical functions gave different netlists. Why?” First check that they really are identical: reset priority, hold behaviour, widths and initial state. Then compare the supported cells, constraints and optimisation logs under the same tool version and options. Process count is not the cause, and neither netlist is better until a mapped and timed comparison says so.

    Check yourself Two counters share reset and enable, yet their outputs disagree. Where is the first place to look?

    Check initial or reset state, reset priority, disabled hold behaviour, arithmetic width and observation timing. Splitting the processes is not itself a functional difference. The bench compares settled outputs after each sampled edge.

    Check yourself What makes a coding style inference-friendly?

    Each element uses its canonical template: a clocked process for flops, an array with synchronous ports for RAM, and full assignment for combinational logic.

    Testbench

    A directed regression over selected reset, hold, count and wraparound histories.

    cnt_before.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
    module cnt_before (
      input logic clk, rst_n, en,
      output logic [7:0] q
    );
      logic [7:0] next;
      always_comb begin
        next = q;
        if (en) next = q + 8'd1;
      end
      always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) q <= '0;
        else q <= next;
      end
    endmodule
    
    module cnt_after (
      input logic clk, rst_n, en,
      output logic [7:0] q
    );
      always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) q <= '0;
        else if (en) q <= q + 8'd1;
      end
    endmodule
    
    • Reset priority, the hold path and the arithmetic width set the hardware; the number of processes does not.

    • Both counters map to the same 23 iCE40 cells: 8 enable flops, 9 LUTs and 6 carry cells.

    • Compare reports under the same tool version, target and options before drawing a PPA conclusion.

    Rule of thumb: write the template the tool recognises, then check the report.

    How this was checked

    Testbench run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It is a directed regression over selected reset, hold, count and wraparound histories. It is not an equivalence proof.

    Cell counts from Yosys 0.69 (2026-10-17), synth_ice40 with default options, each counter as its own top: 6 SB_CARRY, 8 SB_DFFER and 9 SB_LUT4 for both. This is a mapping count only: no place and route, timing or power was run.

    • Interview: run a mock interview on this topic

    Related topics

    • Inferring flip-flops and RAM

    • Contextual FSM process style

    Previous

    252 / 350

    Next: Inferring flip-flops and RAM

    Up next

    Up nextInferring flip-flops and RAM

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Latch avoidance and case semantics
    • Reading a synthesis report