top of page

7.1 The  `include Directive: Code Organization and Reusability

What is  `include?

The  `include directive inserts the contents of another file directly into the current file at the point where the directive appears. It's analogous to #include in C/C++.

​

`include "filename.v"

`include "path/to/file.vh"

`include "/absolute/path/to/definitions.svh"

​

Syntax Rules:

​

  • Filename must be in double quotes

  • Can use relative or absolute paths

  • File is inserted textually at directive location

  • Typically used for header files with .vh or .svh extension

  • Can include any valid Verilog code

7.1.1. Common Use Cases

7.1.1.1. Use Case 1: Shared Parameter Definitions

​

File: system_params.vh

 Verilog

// System-wide parameters

`ifndef SYSTEM_PARAMS_VH

`define SYSTEM_PARAMS_VH

// Clock frequencies

`define SYS_CLK_FREQ_MHZ    100

`define UART_CLK_FREQ_MHZ   50

`define DDR_CLK_FREQ_MHZ    800

// Bus widths

`define AXI_DATA_WIDTH      64

`define AXI_ADDR_WIDTH      32

`define AXI_ID_WIDTH        4

// Memory configuration

`define CACHE_LINE_SIZE     64

`define CACHE_NUM_LINES     512

`define ROM_SIZE_BYTES      65536

`endif // SYSTEM_PARAMS_VH

File: axi_master.v

`include "system_params.vh"

module axi_master #(

    parameter DATA_WIDTH = `AXI_DATA_WIDTH,

    parameter ADDR_WIDTH = `AXI_ADDR_WIDTH,

    parameter ID_WIDTH = `AXI_ID_WIDTH

)(

    input wire clk,

    input wire rst_n,

    // AXI interface

    output reg [ID_WIDTH-1:0] awid,

    output reg [ADDR_WIDTH-1:0] awaddr,

    output reg [DATA_WIDTH-1:0] wdata,

    // ... other ports

);

    // Use system-wide definitions

    localparam CLOCK_FREQ = `SYS_CLK_FREQ_MHZ;

    // Implementation

endmodul

7.1.1.2. Use Case 2: Common Package Definitions

​

File: protocol_pkg.vh

 Verilog

`ifndef PROTOCOL_PKG_VH

`define PROTOCOL_PKG_VH

// AXI Protocol Constants

`define AXI_BURST_FIXED     2'b00

`define AXI_BURST_INCR      2'b01

`define AXI_BURST_WRAP      2'b10

`define AXI_SIZE_1_BYTE     3'b000

`define AXI_SIZE_2_BYTES    3'b001

`define AXI_SIZE_4_BYTES    3'b010

`define AXI_SIZE_8_BYTES    3'b011

`define AXI_SIZE_16_BYTES   3'b100

`define AXI_RESP_OKAY       2'b00

`define AXI_RESP_EXOKAY     2'b01

`define AXI_RESP_SLVERR     2'b10

`define AXI_RESP_DECERR     2'b11

// AMBA AHB Constants

`define AHB_TRANS_IDLE      2'b00

`define AHB_TRANS_BUSY      2'b01

`define AHB_TRANS_NONSEQ    2'b10

`define AHB_TRANS_SEQ       2'b11

`define AHB_BURST_SINGLE    3'b000

`define AHB_BURST_INCR      3'b001

`define AHB_BURST_WRAP4     3'b010

`endif // PROTOCOL_PKG_VH

Usage in Design:

 Verilog

`include "protocol_pkg.vh"

module axi_to_ahb_bridge (

    // ports

);

    always @(posedge clk) begin

        case (axi_burst_type)

            `AXI_BURST_FIXED: begin

                ahb_trans <= `AHB_TRANS_NONSEQ;

            end

            `AXI_BURST_INCR: begin

                ahb_burst <= `AHB_BURST_INCR;

            end

        endcase

    end

endmodule

7.1.1.3. Use Case 3: Register Map Definitions

​

File: register_map.vh

 Verilog

`ifndef REGISTER_MAP_VH

`define REGISTER_MAP_VH

// Control and Status Registers

`define REG_CTRL_ADDR           32'h0000_0000

`define REG_STATUS_ADDR         32'h0000_0004

`define REG_INT_ENABLE_ADDR     32'h0000_0008

`define REG_INT_STATUS_ADDR     32'h0000_000C

// Configuration Registers

`define REG_CLK_DIV_ADDR        32'h0000_0010

`define REG_TIMEOUT_ADDR        32'h0000_0014

`define REG_MODE_ADDR           32'h0000_0018

// Data Registers

`define REG_TX_DATA_ADDR        32'h0000_0020

`define REG_RX_DATA_ADDR        32'h0000_0024

// Control Register Bit Fields

`define CTRL_ENABLE_BIT         0

`define CTRL_RESET_BIT          1

`define CTRL_INT_EN_BIT         2

`define CTRL_MODE_BIT_START     4

`define CTRL_MODE_BIT_END       6

// Status Register Bit Fields

`define STATUS_BUSY_BIT         0

`define STATUS_ERROR_BIT        1

`define STATUS_READY_BIT        2

`define STATUS_OVERFLOW_BIT     3

`endif // REGISTER_MAP_VH

Usage in Register Block:

`include "register_map.vh"

module register_block (

    input wire [31:0] addr,

    input wire [31:0] wdata,

    input wire write_en,

    output reg [31:0] rdata

);

    reg [31:0] ctrl_reg;

    reg [31:0] status_reg;

    reg [31:0] config_reg; 

    // Write logic

    always @(posedge clk) begin

        if (write_en) begin

            case (addr)

                `REG_CTRL_ADDR: begin

                    ctrl_reg <= wdata;

                end

                `REG_CLK_DIV_ADDR: begin

                    config_reg <= wdata;

                end

                // ... other registers

            endcase

        end

    end

    // Read logic

    always @(*) begin

        case (addr)

            `REG_CTRL_ADDR:   rdata = ctrl_reg;

            `REG_STATUS_ADDR: rdata = status_reg;

            `REG_CLK_DIV_ADDR: rdata = config_reg;

            default:          rdata = 32'h0;

        endcase

    end

    // Extract control fields

    wire enable = ctrl_reg[`CTRL_ENABLE_BIT];

    wire reset_req = ctrl_reg[`CTRL_RESET_BIT];

    wire [2:0] mode = ctrl_reg[`CTRL_MODE_BIT_END:`CTRL_MODE_BIT_START];

endmodule

7.1.2. Best Practices for  `include

7.1.2.1. Use Include Guards

​

Always protect header files with include guards to prevent multiple inclusion:

 Verilog

// Good practice - with include guard

`ifndef MY_HEADER_VH

`define MY_HEADER_VH

// Header content here

`endif // MY_HEADER_VH

​

Why? Without guards, including the same file twice causes redefinition errors:

​

// File: defs.vh (without guard)

`define BUS_WIDTH 32

// File: top.v

`include "defs.vh"

`include "defs.vh"  // ERROR: BUS_WIDTH already defined!

7.1.2.2. Organize include Files by Purpose

include.png

7.1.2.3. Use Relative Paths When Possible

 Verilog

// Good - relative path

`include "../includes/system_params.vh"

// Avoid - absolute path (not portable)

`include "/home/user/project/includes/system_params.vh"

7.1.2.4. Document Dependencies

 Verilog

/**

 * Module: axi_master

 * Dependencies:

 *   - system_params.vh : System-wide parameters

 *   - axi_defs.vh      : AXI protocol constants

 */

`include "system_params.vh"

`include "axi_defs.vh"

module axi_master (...);

7.1.2.5. Minimize Include Depth

 Verilog

// Avoid - deep nesting

// file_a.vh includes file_b.vh

// file_b.vh includes file_c.vh

// file_c.vh includes file_d.vh

// Hard to track dependencies!

// Better - flat structure

// Each file includes only what it needs directly

7.1.3. Hidden Challenges with `include

7.1.3.1. Circular Dependencies

 Verilog

// File: module_a.vh

`include "module_b.vh"

`define A_CONSTANT 10

// File: module_b.vh

`include "module_a.vh"  // ERROR: Circular dependency!

`define B_CONSTANT 20

Solution: Use include guards and restructure dependencies.

​

7.1.3.2. Search Path Issues

 Verilog

// If compiler can't find file

`include "my_header.vh"  // ERROR: File not found

Solution: Configure compiler include paths:

# For Vivado

vlog +incdir+./includes module.v

# For ModelSim

vlog -incdir ./includes module.v

# For VCS

vcs +incdir+./includes module.v

7.1.3.3. Including Modules

 Verilog

// Bad practice - don't include modules

`include "uart.v"  // Avoid this!

// Good practice - compile separately and link

// Compile: uart.v

// Compile: top.v (instantiates uart)

Compiler Directives

define

© Copyright 2025 VLSI Mentor. All Rights Reserved.©

Connect with us

  • Instagram
  • Facebook
  • Twitter
  • LinkedIn
  • YouTube
bottom of page