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

  • Start Here6
  • SystemVerilog Language Foundations35
  • Object-Oriented SystemVerilog for Verification35
  • Constraint Randomization — Interview-Critical Deep Dive66
  • SystemVerilog Assertions — Interview-Critical Deep Dive63
  • Functional Coverage in SystemVerilog28
  • Testbench Architecture in SystemVerilog38
  • Advanced Language & Integration30
    • DPI-C: Calling C from SystemVerilog
    • bind: Attaching Verification to RTL
    • Macros, Defines & Compilation
      • `define & Text Macros
      • `ifdef & Conditional Compilation
      • `include & Guard Discipline
      • Debugging Macro Problems
      • Compilation, Elaboration & Optimization Flow
    • Plusargs, Files & Runtime Configuration
    • Simulation Performance & TB Memory
    • RTL/TB Boundaries, Races & Timing
  • Senior & Interview Preparation34
  • Principal-Level Verification28
Loading lesson

‹Macros, Defines & Compilation
  1. Topics
  2. SystemVerilog
  3. Advanced Language & Integration
  4. Macros, Defines & Compilation
  5. `ifdef & Conditional Compilation

Part 7 · Advanced & Integration · Intermediate

`ifdef & Conditional Compilation

Selecting code at compile time with ifdef, command-line defines, and configuration discipline.

On this page

    Defined means present, not true

    ` ifdef` includes a region only if a macro is defined. The macro value is irrelevant: define MODE 0` still makes ifdef MODE`` true.

    Code in the false branch is never compiled. It can reference signals that do not exist, which is fundamentally different from a run-time if that compiles both branches.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // snippet
    `define FPGA_TARGET   // value-less define: existence is the flag
    
    `ifdef FPGA_TARGET
      // FPGA clock buffer primitive (tool cell, shown as a fragment)
      // bufg clk_buf (.I(clk_in), .O(clk));
    `elsif ASIC_TARGET
      // ASIC standard-cell buffer (tool cell, shown as a fragment)
      // CLKBUF_X4 clk_buf (.A(clk_in), .Z(clk));
    `else
      assign clk = clk_in;   // plain sim model
    `endif
    
    `ifndef SYNTHESIS     // include when NOT defined
      initial $display("Simulation-only banner");
    `endif
    
    // `undef removes a definition from this point onward
    `undef FPGA_TARGET

    An unguarded use of a build macro is a compile error when the flag is absent. Guard it or give it a default.

    design.sv
    1
    2
    3
    4
    5
    // snippet
    `ifndef BUILD_TAG
      `define BUILD_TAG "dev"
    `endif
    // initial $display("Simulation-only banner: build %s", `BUILD_TAG);

    One tree, many builds

    Most defines come from the build script, not the source. One tree compiles into RTL sim, gate-level sim and synthesis without editing a file.

    Diagram
    iverilog -g2012 -DUSE_FAST_TICK -o simv tick_gen.sv tb_tick.sv && vvp simv
    iverilog -g2012 -DRTL_SIM -DASSERT_ON -o simv design.sv tb_top.sv && vvp simv
    verilator --binary --timing +define+USE_FAST_TICK --top-module tb_tick tb_tick.sv

    The sim-versus-synthesis guard below is standard. Synthesis tools predefine SYNTHESIS, so sim-only checks vanish from the netlist build.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // snippet
    `ifndef SYNTHESIS
      always @(posedge clk)
        if (fifo_full && wr_en)
          $error("Write to full FIFO");  // sim-only check, stripped by synthesis
    `endif
    
    `ifdef GATE_SIM
      // SDF annotation hardcodes the testbench hierarchy: a fragment, not reusable.
      // initial $sdf_annotate("netlist.sdf", tb_top.dut);
      `define CLK_PERIOD 12   // slower clock for annotated timing
    `else
      `define CLK_PERIOD 10
    `endif
    
    `ifdef ASSERT_ON
      // assert_no_overflow: assert property (@(posedge clk) !(full && wr_en));
      // Concurrent assertion: needs a tool with SVA support, shown as a fragment.
    `endif

    Configuration discipline

    Conditional compilation does not compose. Two flags make four configurations and five make thirty-two, most never compiled and quietly broken, which is the ifdef-explosion smell.

    • Keep one central defines file listing every legal flag. Never scatter ` define`` statements across random files.

    • Prefer run-time plusargs for verbosity, test selection and iteration counts. They need no recompilation.

    • Prefer parameters and generate blocks for structural variants. They are type-checked in every branch.

    • Reserve ` ifdef`` for true compile-time concerns: tool and target differences, synthesis guards, restricted code.

    • Document the legal flag combinations when two flags interact.

    Testbench

    A tick generator whose period is selected at compile time. The testbench derives its expectation from the same flag, so it passes with and without -D.

    tick_gen.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
    36
    37
    timeunit 1ns; timeprecision 1ps;
    
    `ifdef USE_FAST_TICK
      `define TICK_MAX 4
    `else
      `define TICK_MAX 8
    `endif
    
    module tick_gen (
      input  logic clk,
      output logic tick
    );
      int count = 0;
      always @(posedge clk) begin
        if (count == `TICK_MAX - 1) begin count = 0; tick = 1; end
        else begin count = count + 1; tick = 0; end
      end
    endmodule
    
    module tb_tick;
      logic clk = 0;
      logic tick;
      tick_gen dut (.clk(clk), .tick(tick));
      int ticks = 0;
      always #5 clk = ~clk;
      initial begin
        repeat (80) begin @(posedge clk); #1; if (tick) ticks++; end
        `ifdef USE_FAST_TICK
          if (ticks == 20) $display("PASS: fast config ticks every 4 cycles: 20 ticks in 80 cycles");
          else $fatal(1, "FAIL: fast config tick count is wrong");
        `else
          if (ticks == 10) $display("PASS: default config ticks every 8 cycles: 10 ticks in 80 cycles");
          else $fatal(1, "FAIL: default config tick count is wrong");
        `endif
        $finish;
      end
    endmodule

    Common pitfall

    A misspelled name in ` ifdef` is silently false and the guarded code vanishes with no warning. A forgotten endif` usually reports at end of file, far from the omission. Testing a valued define with ifdef` expecting value semantics always surprises: define MODE 0`` is still defined.

    Interview

    Likely question: refuse the next ` ifdef``.

    • Compile-time ` ifdef` excludes text; run-time if` simulates a branch.

    • One TB serves RTL and gate-level sim through defines that select SDF annotation and the clock period.

    • Refuse another ` ifdef`` when a plusarg or a parameter can do the job more cheaply.

    Check yourself ` define MODE 0` is in force. Is ifdef MODE`` true or false, and why?

    True. ` ifdef` tests existence, never value. Use ifndef`` for default-on behavior and a real comparison for values.

    Check yourself The fast build ticks every 4 cycles and the testbench counts 20 ticks in 80 cycles. What does the default build count, and which line decides it?

    10 ticks. The ` else` branch defines TICK_MAX 8, so exactly every eighth edge raises tick`.

    Related topics

    • Text macros

    • Debugging macros

    Previous

    283 / 363

    Next: `include & Guard Discipline

    Up next

    Up next`include & Guard Discipline

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Debugging Macro Problems
    • Compilation, Elaboration & Optimization Flow