Configuring

VSG can use a configuration file to alter it’s behavior and/or include a list of files to analyze. This is accomplished by passing JSON and/or YAML file(s) through the –configuration command line argument. This is the basic form of a configuration file in JSON:

{
    "file_list":[
      "fifo.vhd",
      "$PATH_TO_FILE/spi_master.vhd",
      "$OTHER_PATH/src/*.vhd",
      "source/spi.vhd": {
        "rule": {
          "ruleId_ruleNumber":"blah"
      }
    ],
    "local_rules":"$DIRECTORY_PATH",
    "rule":{
        "global":{
            "attributeName":"AttributeValue"
        },
        "ruleId_ruleNumber":{
            "attributeName":"AttributeValue"
        }
    }
}

This is the basic form of a configuration file in YAML:

---
file_list:
  - fifo.vhd
  - source/spi.vhd:
      rule:
        ruleId_ruleNumber:
          attributeName: AttributeValue
  - $PATH_TO_FILE/spi_master.vhd
  - $OTHER_PATH/src/*.vhd
local_rules: $DIRECTORY_PATH
rule:
  global:
    attributeName: AttributeValue
  ruleId_ruleNumber:
    attributeName: AttributeValue
...

It is not required to have file_list, local_rules, and rule defined in the configuration file. Any combination can be defined, and the order does not matter.

Note

All examples of configurations in this documentation use JSON. However, YAML can be used instead.

file_list

The file_list is a list of files that will be analyzed. Environment variables will expanded. File globbing is also supported. The Environment variables will be expanded before globbing occurs. This option can be useful when running VSG over multiple files.

Rule configurations can be specified for each file by following the format of the rule configuration.

local_rules

Local rules can be defined on the command line or in a configuration file. If they are defined in both locations, the configuration will take precedence.

rule

Any attribute of any rule can be configured. Using global will set the attribute for every rule. Each rule is addressable by using it’s unique ruleId and ruleNumber combination. For example, whitespace_006 or port_010.

Note

If global and unique attributes are set at the same time, the unique attribute will take precedence.

Here are a list of attributes that can be altered for each rule:

Attribute Values Description
indentSize Integer Sets the number of spaces for each indent level.
phase Integer Sets the phase the rule will run in.
disable Boolean If set to True, the rule will not run.
fixable Boolean If set to False, the violation will not be fixed

Reporting Single Rule Configuration

The configuration for a single rule can be reported using the -rc option:

$ vsg -rc entity_001
{
  "rule": {
    "entity_001": {
      "indentSize": 2,
      "phase": 4,
      "disable": false,
      "fixable": true
    }
  }
}

VSG will print the configuration for the rule given in a JSON format. This configuration can be altered and added to a configuration file.

Reporting Configuration for All Rules

Every rule configuration can be report and saved to a file using the -oc option:

$ vsg -oc configuration.json

The output file will be in JSON format and can be modified and passed back to VSG using the -c option.

Rule Configuration Priorities

There are three ways to configure a rule. From least to highest priority are:

  • [rule][global]
  • [rule][<identifier>]
  • [file_list][<filename>][rule][<identifier>].

If the same rule is defined in all three locations as in the example below, then the final setting will be equal to the highest priority.

{
  "file_list":[
    "entity.vhd":{
      "rule":{
        "length_001":{
          "disable": true
        }
      }
   },
   "architecture.vhd",
   "package.vhd"
  ],
  "rule":{
    "global":{
      "disable": true
    },
    "rule": {
      "length_001":{
        "disable": false
    }
  }
}

In this example configuration, all rules are disabled by the global configuration. Then rule length_001 is enabled for the files architecture.vhd, package.vhd and entity.vhd by the rule configuration. Then rule length_001 is disabled for the file entity.vhd.

Example: Disabling a rule

Below is an example of a JSON file which disables the rule entity_004

{
    "rule":{
        "entity_004":{
            "disable":true
        }
    }
}

Use the configuration with the –configuration command line argument:

$ vsg -f RAM.vhd --configuration entity_004_disable.json

Example: Setting the indent increment size for a single rule

The indent increment size is the number of spaces an indent level takes. It can be configured on an per rule basis…

{
    "rule":{
        "entity_004":{
            "indentSize":4
        }
    }
}

Example: Setting the indent increment size for all rules

Configure the indent size for all rules by setting the global attribute.

{
    "rule":{
        "global":{
            "indentSize":4
        }
    }
}

Multiple configurations

More than one configuration can be passed using the –configuration option. This can be useful in two situations:

  1. Block level configurations
  2. Multilevel rule configurations

The priority of the configurations is from right to left. The last configuration has the highest priority. This is true for all configuration parameters except file_list.

Block level configurations

Many code bases are large enough to be broken into multiple sub blocks. A single configuration can be created and maintained for each subblock. This allows each subblock to be analyzed independently.

When the entire code base needs be analyzed, all the subblock configurations can be passed to VSG. This reduces the amount of external scripting required.

config_1.json

{
    "file_list":[
      "fifo.vhd",
      "source/spi.vhd",
      "$PATH_TO_FILE/spi_master.vhd",
      "$OTHER_PATH/src/*.vhd"
    ]
}

config_2.json

{
    "file_list":[
      "dual_port_fifo.vhd",
      "flash_interface.vhd",
      "$PATH_TO_FILE/ddr.vhd"
    ]
}

Both configuration files can be processed by vsg with the following command:

$ vsg --configuration config_1.json config_2.json

Multilevel rule configurations

Some code bases may require rule adjustments that apply to all the files along with rule adjustments against individual files. Use multiple configurations to accomplish this. One configuration can handle code base wide adjustments. A second configuration can target individual files. VSG will combine any number of configurations to provide a unique set of rules for any file.

config_1.json

{
    "rule":{
        "entity_004":{
            "disable":true
        },
        "entity_005":{
            "disable":true
        },
        "global":{
            "indentSize":2
        }
    }
}

config_2.json

{
    "rule":{
        "entity_004":{
            "disable":false,
            "indentSize":4
        }
    }
}

Both configuration files can be processed by VSG with the following command:

$ vsg --configuration config_1.json config_2.json -f fifo.vhd

VSG will combine the two configurations into this equivalent configuration…

{
    "rule":{
        "entity_004":{
            "disable":false,
            "indentSize":4
        },
        "entity_005":{
            "disable":true
        },
        "global":{
            "indentSize":2
        }
    }
}

…and run on the file fifo.vhd.

Configuring Disabled Rules

Each rule is either enabled (actively checked) or disabled (not checked). Each rule can be enabled or disabled by user configuration.

Most rules are enabled by default while some are disabled by default. Rules disabled by default are marked by disabled and are typically naming convention rules. They can be enabled by setting the disable option to False in a configuration.

rule :
  <rule_id>:
      disable: False

Configuring Uppercase and Lowercase Rules

There are several rules that enforce either uppercase or lowercase. The default for all such rules is lowercase. The decision was motivated by the fact, that the VHDL language is case insensitive. Having the same default for all case rules also results in less documentation and code to maintain. The default value for each of these case rules can be overridden using a configuration.

Overriding Default Lowercase Enforcement

The default lowercase setting can be changed using a configuration.

For example the rule constant_002 can be changed to enforce uppercase using the following configuration:

---

rule :
  constant_002 :
     case : 'upper'

Changing Multiple Case Rules

If there are a lot of case rules you want to change, you can use the global option to reduce the size of the configuration. For example, if you want to uppercase everything except the entity name, you could write the following configuration:

---

rule :
  global :
    case : 'upper'
  entity_008 :
    case : 'lower'

Rules Enforcing Case

Configuring Prefix and Suffix Rules

There are several rules that enforce specific prefixes or suffixes in different name identifiers. It is noted in the documentation, what the default prefixes and suffixes are for each such rule.

All prefix and suffix rules are disabled by default. The defaults for each of these rules can be overridden using a configuration.

Note

Some elements have both prefix and suffix rules. Depending on the desired style, either or both can be enabled.

Overriding Default Prefix Enforcement

The default setting can be changed using a configuration. The rule variable_012 defaults to following prefix: [‘v_’]. We can use the following configuration to change allowed prefix:

---

 rule :
     variable_012:
         # Each prefix rule needs to be enabled explicitly.
         disable: false
         prefixes: ['var_']

Overriding Default Suffix Enforcement

The default setting can be changed using a configuration. For example, the rule port_025 defaults to following suffixes: [‘_I’, ‘_O’, ‘_IO’]. We can use the following configuration to change allowed suffixes:

---

 rule :
     port_025:
         # Each suffix rule needs to be enabled explicitly.
         disable: false
         suffixes: ['_i', '_o']

Rules Enforcing Prefixes and Suffixes

Element Prefix Rule Suffix Rule
Block Label block_601 block_600
Constant Identifier constant_015 constant_600
Generate Label generate_017 generate_600
Generic Identifier generic_020 generic_600
Package Identifier package_017 package_016
Package Body Identifier package_body_601 package_body_600
Port Identifier port_011 port_025
Process Label process_036 process_600
Signal Identifier signal_008 signal_600
Subtype Identifier subtype_004 subtype_600
Type Identifier type_definition_015 type_definition_600
Variable Identifier variable_012 variable_600

Configuring Number of Signals in Signal Declaration

VHDL allows of any number of signals to be declared within a single signal declaration. While this may be allowed, in practice there are limits impossed by the designers. Limiting the number of signals declared improves the readability of VHDL code.

The default number of signals allowed, 2, can be set by configuring rule signal_015.

Overriding Number of Signals

The default setting can be changed using a configuration. We can use the following configuration to change the number of signals allowed to 1.

---

rule :
  signal_015 :
     consecutive : 1

Rules Enforcing Number of Signals

Configuring Length Rules

VSG includes several rules enforcing maximum lengths of code structures. These rules are set as warnings.

Overriding Line Length

Limiting the line length of the VHDL code can improve readability. Code that exceeds the editor window is more difficult to read. The default line length is 120, and can be changed by configuring rule length_001.

Use the following configuration to change the line length to 180.

rule :
  length_001 :
     length : 180

Overridding File Line Length

Limiting the length of a VHDL file can improve readability. Excessively long files can indicate the file can be broken into smaller modules. The default line length is 2000, and can be changed by configuring rule length_002.

Use the following configuration to change the file length to 5000.

rule :
  length_002 :
     length : 5000

Overridding Process Line Length

Limiting the length of a VHDL processes can improve readability. Processes should perform a limited number of functions. Smaller processes are easier to understand.

The default length is 500 lines, and can be changed by configuring rule length_003.

Use the following configuration to change the process length to 1000.

rule :
  length_003 :
     length : 1000

Rules Enforcing Lengths

Configuring Keyword Alignment Rules

There are several rules that enforce alignment for a group of lines based on the keywords such as ‘after’, ‘<=’ etc. Some of the configurations are available in all keyword alignment rules, while others are rule specific.

Common Keyword Alignment Configuration

Following configuration options can be independently changed for each of the keyword alignment rules.

  1. compact_alignment - if set to True it enforces single space before alignment keyword in the line with the longest part before the keyword. Otherwise the alignment occurs to the keyword maximum column. By default set to True.

    Violation

    signal sig_short   : std_logic;
    signal sig_very_long      : std_logic;
    

    Fix (compact_alignment = True)

    signal sig_short     : std_logic;
    signal sig_very_long : std_logic;
    

    Fix (compact_alignment = False)

    signal sig_short          : std_logic;
    signal sig_very_long      : std_logic;
    
  2. blank_line_ends_group - if set to True any blank line encountered in the VHDL file ends the group of lines that should be aligned and starts new group. By default set to True.

    Violation

    signal wr_en : std_logic;
    signal rd_en   : std_logic;
    
    constant c_short_period : time;
    constant c_long_period : time;
    

    Fix (blank_line_ends_group = True)

    signal wr_en   : std_logic;
    signal rd_en   : std_logic;
    
    constant c_short_period : time;
    constant c_long_period  : time;
    

    Fix (blank_line_ends_group = False)

    signal wr_en            : std_logic;
    signal rd_en            : std_logic;
    
    constant c_short_period : time;
    constant c_long_period  : time;
    
  3. comment_line_ends_group - if set to True any purely comment line in the VHDL file ends the group of lines that should be aligned and starts new group. By default set to True.

    Violation

    port (
        sclk_i : in std_logic;
        pclk_i : in std_logic;
        rst_i : in std_logic;
        ---- serial interface ----
        spi_ssel_o : out std_logic;
        spi_sck_o : out std_logic;
        spi_mosi_o : out std_logic;
        spi_miso_i : in std_logic
    );
    

    Fix (comment_line_ends_group = True)

    port (
        sclk_i : in std_logic;
        pclk_i : in std_logic;
        rst_i  : in std_logic;
        ---- serial interface ----
        spi_ssel_o : out std_logic;
        spi_sck_o  : out std_logic;
        spi_mosi_o : out std_logic;
        spi_miso_i : in std_logic
    );
    

    Fix (comment_line_ends_group = False)

    port (
        sclk_i     : in std_logic;
        pclk_i     : in std_logic;
        rst_i      : in std_logic;
        ---- serial interface ----
        spi_ssel_o : out std_logic;
        spi_sck_o  : out std_logic;
        spi_mosi_o : out std_logic;
        spi_miso_i : in std_logic
    );
    

Note

As all keyword alignment rules have above configurations they are not mentioned in the documentation for each rule.

Rule Specific Keyword Alignment Configuration

  1. separate_generic_port_alignment - if set to True alignment within the generic declarative/mapping part is separated from alignment within the port declarative/mapping part. By default set to True.

    Violation

    generic (
        g_width : positive;
        g_output_delay : positive
    );
    port (
        clk_i : in std_logic;
        data_i : in std_logic;
        data_o : in std_logic
    );
    

    Fix (separate_generic_port_alignment = True)

    generic (
        g_width        : positive;
        g_output_delay : positive
    );
    port (
        clk_i  : in std_logic;
        data_i : in std_logic;
        data_o : in std_logic
    );
    

    Fix (separate_generic_port_alignment = False)

    generic (
        g_width        : positive;
        g_output_delay : positive
    );
    port (
        clk_i          : in std_logic;
        data_i         : in std_logic;
        data_o         : in std_logic
    );
    
  2. if_control_statements_ends_group - if set to True any line with if control statement ends the group of lines that should be aligned and starts new group. By default set to True.

    Violation

    if condition = '1' then
        data_valid <= '1';
        data <= '1';
    else
        data_valid <= '0';
        hold_transmission <= '1';
    end if;
    

    Fix (if_control_statements_ends_group = True)

    if condition = '1' then
        data_valid <= '1';
        data       <= '1';
    else
        data_valid        <= '0';
        hold_transmission <= '1';
    end if;
    

    Fix (if_control_statements_ends_group = False)

    if condition = '1' then
        data_valid        <= '1';
        data              <= '1';
    else
        data_valid        <= '0';
        hold_transmission <= '1';
    end if;
    
  3. case_control_statements_ends_group - if set to True, any line with case control statements (case, when or end case) ends the group of lines that should be aligned and starts new group. If set to False, no line with case control statements ends the group of lines that should be aligned and starts a group. If set to break_on_case_or_end_case, any line with case or end case ends the group of lines that should be aligned and starts new group. By default set to True.

    Violation

    data_valid_before    <= '1';
    case A is
        when A =>
            X <= F;
            XY <= G;
            XYZ <= H;
        when B =>
            a <= I;
            ab <= h;
            c <= a;
        when others =>
          null;
    end case
    data_valid_after       <= '1';
    

    Fix (case_control_statements_ends_group = True)

    data_valid_before <= '1';
    case A is
        when A =>
            X   <= F;
            XY  <= G;
            XYZ <= H;
        when B =>
            a  <= I;
            ab <= h;
            c  <= a;
        when others =>
            null;
    end case
    data_valid_after <= '1';
    

    Fix (case_control_statements_ends_group = False)

    data_valid_before <= '1';
    case A is
        when A =>
            X         <= F;
            XY        <= G;
            XYZ       <= H;
        when B =>
            a         <= I;
            ab        <= h;
            c         <= a;
        when others =>
            null;
    end case
    data_valid_after  <= '1';
    

    Fix (case_control_statements_ends_group = break_on_case_or_end_case)

    data_valid_before <= '1';
    case A is
        when A =>
            X   <= F;
            XY  <= G;
            XYZ <= H;
        when B =>
            a   <= I;
            ab  <= h;
            c   <= a;
        when others =>
            null;
    end case
    data_valid_after <= '1';
    
  4. loop_control_statements_ends_group - if set to True any line with loop control statement (including for and while loops) ends the group of lines that should be aligned and starts new group. By default set to False.

    Violation

    data_valid_before    <= '1';
    for index in 4 to 23 loop
        data_valid <= '0';
        hold_transmission <= '1';
    end loop;
    data_valid_after       <= '1';
    

    Fix (loop_control_statements_ends_group = True)

    data_valid_before <= '1';
    for index in 4 to 23 loop
        data_valid        <= '0';
        hold_transmission <= '1';
    end loop;
    data_valid_after <= '1';
    

    Fix (loop_control_statements_ends_group = False)

    data_valid_before     <= '1';
    for index in 4 to 23 loop
        data_valid        <= '0';
        hold_transmission <= '1';
    end loop;
    data_valid_after      <= '1';
    

Note

If given keyword alignment rule has any of the above keyword alignment specific configuration, then it is explicitly noted in the documentation of this rule.

The default value for each of these case rules can be overridden using a configuration.

Configuring Identifier Alignment Rules

There are several rules that enforce alignment of identifiers in group of lines. Some of the configurations are available in all keyword alignment rules, while others are rule specific.

Common Identifier Alignment Configuration

Following configuration options can be independently changed for each of the identifier alignment rules.

  1. blank_line_ends_group - if set to True any blank line encountered in the VHDL file ends the group of lines that should be aligned and starts new group. By default set to True.

    Violation

    signal wr_en   : std_logic;
    file results :
    
    signal rd_en   : std_logic;
    constant c_short_period : time;
    

    Fix (blank_line_ends_group = True)

    signal wr_en   : std_logic;
    file   results :
    
    signal   rd_en   : std_logic;
    constant c_short_period : time;
    

    Fix (blank_line_ends_group = False)

    signal   wr_en   : std_logic;
    file     results :
    
    signal   rd_en   : std_logic;
    constant c_short_period : time;
    
  2. comment_line_ends_group - if set to True any purely comment line in the VHDL file ends the group of lines that should be aligned and starts new group. By default set to True.

    Violation

    signal wr_en   : std_logic;
    file results :
    -- some comment
    signal rd_en   : std_logic;
    constant c_short_period : time;
    

    Fix (comment_line_ends_group = True)

    signal wr_en   : std_logic;
    file   results :
    -- some comment
    signal   rd_en   : std_logic;
    constant c_short_period : time;
    

    Fix (comment_line_ends_group = False)

    signal   wr_en   : std_logic;
    file     results :
    -- some comment
    signal   rd_en   : std_logic;
    constant c_short_period : time;
    

Note

As all identifier alignment rules have above configurations they are not mentioned in the documentation for each rule.

Configuring Blank Lines

There are rules which will check for blank lines either above or below a line. These rules are designed to improve readability by separating code using blank lines.

There are a couple of options to these rules, which can be selected by using the style option:

Style Description
no_blank_line Removes blank lines on the line above or below.
require_blank_line Requires a blank line on the line above or below.
rule :
  architecture_015:
     style : require_blank_line

Warning

It is important to be aware these rules may conflict with rules that enforce rules on previous lines. This can occur when a below rule is applied and then on the next line a previous rule applies. Resolve any conflicts by changing the configuration of either rule.

Example: require_blank_line

The following code would fail with this option:

architecture rtl of fifo is
  -- Comment

architecture rtl of fifo is
  signal s_sig1 : std_logic;

The following code would pass with this option:

architecture rtl of fifo is

  -- Comment

architecture rtl of fifo is

  signal s_sig1 : std_logic;

Example: no_blank_line

The following code would fail with this option:

architecture rtl of fifo is

  -- Comment

architecture rtl of fifo is

  signal s_sig1 : std_logic;

The following code would pass with this option:

architecture rtl of fifo is
  -- Comment

architecture rtl of fifo is
  signal s_sig1 : std_logic;

Configuring Previous Line Rules

There are rules which will check the contents on lines above code structures. These rules allow enforcement of comments and blank lines.

There are several options to these rules, which can be selected by using the style option:

Style Description
no_blank_line Removes blank lines on the line above.
require_blank_line Requires a blank line on the line above.
no_code Either a blank line; or comment(s) on the line(s) above.
allow_comment Either a blank line; or comment(s) on the line(s) above and a blank line above the comment(s).
require_comment Comment(s) required on the line(s) above and a blank line above the comment(s).

Note

Unless stated in the rule description, the default style is require_blank_line.

Warning

It is important to be aware these rules may conflict with rules that enforce blank lines below keywords. This can occur when a below rule is applied and then on the next line a previous rule applies. Resolve any conflicts by changing the configuration of either rule.

This is an example of how to configure these options.

rule :
  entity_003:
     style : require_blank_line

Note

All examples below are using the rule entity_004.

Example: no_blank

The following code would fail with this option:

library fifo_dsn;
-- Define entity

entity fifo is

The following code would pass with this option:

library fifo_dsn;
-- Define entity
entity fifo is

Example: require_blank_line

The following code would fail with this option:

library fifo_dsn;
-- Define entity
entity fifo is

The following code would pass with this option:

library fifo_dsn;
-- Define entity

entity fifo is

Example: no_code

The following code would fail with this option:

library fifo_dsn;
entity fifo is

The following code would pass with this option:

library fifo_dsn;

entity fifo is

library fifo_dsn;
-- Comment

entity fifo is

library fifo_dsn;
-- Comment
entity fifo is

Example: allow_comment

The following code would fail with this option:

library fifo_dsn;
entity fifo is

library fifo_dsn;
-- Comment
entity fifo is

The following code would pass with this option:

library fifo_dsn;

entity fifo is

library fifo_dsn;
-- Comment

entity fifo is

library fifo_dsn;

-- Comment
entity fifo is

Example: require_comment

The following code would fail these options:

library fifo_dsn;
entity fifo is

library fifo_dsn;
-- Comment
entity fifo is

The following code would pass these options:

library fifo_dsn;

-- Comment
entity fifo is

Configuring Type of Instantiations

There are two methods to instantiate components: component or entity.

VSG can check which method is being used and throw a violation if the incorrect method is detected.

Overriding Type of Instantiation

The default setting is component instantiation. We can use the following configuration to change it to entity instantiation.

---

rule :
  instantiation_034:
     method: 'entity'

Rules Enforcing Type of Instantiations

Configuring Optional Items

There are optional language items in VHDL. In the Language Reference Manual (LRM) they are denoted with square brackets []. Using many of these optional items improves the readability of VHDL code.

However, it may not fit the current style of existing code bases. The rules checking the optional items can be configured to add or remove them.

Adding Optional Items

This is the default behavior for these rules.

The configuration format to add the optional items is shown below:

rule :
  <rule_id>:
     action: 'add'

Removing Optional Items

The configuration format to remove the optional items is shown below:

rule :
  <rule_id>:
     action: 'remove'

Configuring Block Comments

Block comments are sequential comment lines with a header and footer. Below are several examples of a block comments:

----------------------------------
-- Comment
-- Comment
----------------------------------

--================================
-- Comment
-- Comment
--================================

--+-------------------------------
--| Comment
--| Comment
--+-------------------------------

--+---------< header >------------
--| Comment
--| Comment
--+---------< footer >------------

Block Comment Structure

The above examples can be generalized into the following:

--<header_left><header_left_repeat><header_string><header_right_repeat>
--<comment_left>
--<footer_left><footer_left_repeat><footer_string><footer_right_repeat>

Where:

Attribute Values Default Description
header_left String None None The string to place to the right of the –
header_left_repeat String - A character to repeat between header_left and header_string
header_string String None None A string to place in the header.
header_right_repeat String None None A character to repeat after the header-string
comment_left String None None A string which should exist to the right of the –
footer_left String None None The string to place to the right of the –
footer_left_repeat String - A character to repeat between footer_left and footer_string
footer_string String None None A string to place in the footer.
footer_right_repeat String None None A character to repeat after the footer_string

There are additional options for configuring block comments:

Attribute Values Default Description
min_height Integer 3 Sets minimum number of consecutive comment lines before being considered a block comment.
header_alignment “left” “center” “right” “center” Sets horizontal position of header string.
max_header_column Integer 120 Sets the maximum length of the combined header.
footer_alignment “left” “center” “right” “center” Sets horizontal position of footer string.
max_footer_column Integer 120 Sets the maximum length of the combined footer.
allow_indenting Boolean True Allows indented block comments. Setting this to False will only detect block comments starting at column 0.

With these options, a block comment can be validated by VSG.

Examples

It is important to note the rules are disabled by default. They must enabled using a configuration.

Simple Block Comment

To configure the following example…

----------------------------------
-- Comment
-- Comment
----------------------------------

…the configuration would be:

rule:
  block_comment_001:
    disable : False
    header_left : None
    header_left_repeat : '-'
    header_string : None
    header_right_repeat : None
  block_comment_002:
    disable : False
    comment_left : None
  block_comment_003:
    disable : False
    footer_left : None
    footer_left_repeat : '-'
    footer_string : None
    footer_right_repeat : None

Complex Block Comment

To configure the following example…

--+-<Header>==============================
--| Purpose:
--| Author:
--+------------------------------<Footer>=

…the configuration would be:

rule:
  block_comment_001:
    disable : False
    header_left : '+'
    header_left_repeat : '-'
    header_string : '<Header>'
    header_right_repeat : '='
    header_alignment : 'left'
  block_comment_002:
    disable : False
    comment_left : '|'
  block_comment_003:
    disable : False
    footer_left : '+'
    footer_left_repeat : '-'
    footer_string : '<Footer>'
    footer_right_repeat : '='
    footer_alignment : 'right'

Doxygen Block Comment

Doxygen comments use an exclamation mark. To configure a block comment for Doxygen…

----------------------------------
--! Comment
--! Comment
----------------------------------

…the configuration would be:

rule:
  block_comment_001:
    disable : False
    header_left : '-'
    header_left_repeat : '-'
    header_string : None
    header_right_repeat : None
  block_comment_002:
    disable : False
    comment_left : '!'
  block_comment_003:
    disable : False
    footer_left : '-'
    footer_left_repeat : '-'
    footer_string : None
    footer_right_repeat : None

Configuring Indentation

VSG follows a predefined set of rules when indenting VHDL code. The indenting alogrithm is driven by a YAML file.

The indent values feeding the algorithm can be obtained by using the -oc command line argument. There will be a section starting with indent.

Understanding the Indent Configuration Data Structure

The indent configuration file follows this basic format:

indent:
    tokens:
        group_name:
            token_name:
                token : value
                after : value

where:

Attribute Values Description
indent NA Indicates the following information defines indent behavior.
tokens NA Indicates the following information defines token level behavior.
group_name <string> The group a token belongs to.
token_name <string> The name of the token which has indent behavior.
token NA Indicates the value to apply to the token.
after NA Indicates the value to apply after the token.
value
<integer>
current

“+<integer>” “-<integer>”

The type of behavior to apply to the token or after the token.

The group_name and token_name keys provide unique identifier which can be matched to types of tokens after the file has been parsed. There are more tokens than are currently defined in the indent configuration, as not all tokens require indenting rules.

The token key informs VSG how to apply indents when it encounters the token.

The after key informs VSG how to apply indents to successive tokens it encounters.

The value defines the behavior for each token and after key, and are defined as:

Value Type Description
[0-9][0-9]* <integer> Sets the indent level to the specified value.
current <string> Uses the existing indent level.
“+[0-9][0-9]*” <string> Increase the indent relative to the current indent level.
“-[0-9][0-9]*” <string> Decrease the indent relative to the current indent level.

Using the group_name and token_name to identify types of VHDL tokens and then the token and after defines the behavior of the indenting algorithm.

Example

VSG assumes the closing parenthesis will match with the port keyword.

entity some_block is
  port (
    I_CLK   : std_logic;
    I_RST   : std_logic;
    I_WR_EN : std_logic;
    O_DATA  : std_logic_vector(7 downto 0);
  );
end entity some_block;

If we use the following configuration…

indent:
    tokens:
        port_clause:
            close_parenthesis:
                token : current
                after : '-2'

…then VSG will enforce the following format:

entity some_block is
  port (
    I_CLK   : std_logic;
    I_RST   : std_logic;
    I_WR_EN : std_logic;
    O_DATA  : std_logic_vector(7 downto 0);
    );
end entity some_block;

How does this work?

VSG is setting the indent levels as it goes. The port definitions in the above example are set to an indent of 2. When the closing parenthesis is encountered, VSG checks the port_clause.close_parenthesis.token key to determine what to do. In this case the key is set to current. This tells VSG to keep the indent of 2 for the closing parenthesis token. VSG then looks at the port_clause.close_parenthesis.after key and finds a ‘-2’. This tells VSG to subtract two from the current indent value of 2. Which will set the indent to 0. The next token in the indent configuration with a token key value of current would then get 0.

The Challenge With Adjusting Indent Values

The most difficult part of changing the indent values is knowing which group_name and token_name to use.

For the group_name use the VHDL LRM as a reference. All group names match a left-hand side of a production.

For the token_name, refer to the output configuration using the -oc. This will give the complete indent configuration. The desired adjustment can be pulled out into a smaller file. This file can then be applied with the -c option.

Configuring Multiline Indent Rules

There are rules which will check indent of multiline expressions and conditions.

There are several options to these rules:

Method Type Default Description
align_left boolean True True = New lines will be aligned left. False = Align to left of assignment operator.
align_paren boolean True True = Use open parenthesis for alignment. False = Do not use open parenthesis for alignment.

This is an example of how to configure the option.

rule :
  constant_012:
     align_left : False
     align_paren : True

Note

All examples below are using the rule constant_012.

Example: align_left True, align_paren False

The following code would fail with this option:

constant c_const : t_type :=
                             (
                               (
                                 a => 0,
                                 b => 1
                               ),
                               (
                                 c => 0,
                                 d => 1
                               )
                             );

constant c_const : t_type :=
(
 (
  a => 0,
  b => 1
 ),
 (
  c => 0,
  d => 1
 )
);

The following code would pass with this option:

constant c_const : t_type :=
(
  (
    a => 0,
    b => 1
  ),
  (
    c => 0,
    d => 1
  )
);

constant c_const : t_type :=
(
  (
    a => 0,
    b => 1
  ),
  (
    c => 0,
    d => 1
  )
);

Example: align_left False, align_paren False

The following code would fail with this option:

constant c_const : t_type :=
(
  (
    a => 0,
    b => 1
  ),
  (
    c => 0,
    d => 1
  )
);

The following code would pass with this option:

constant c_const : t_type :=
                             (
                               (
                                 a => 0,
                                 b => 1
                               ),
                               (
                                 c => 0,
                                 d => 1
                               )
                             );

Example: align_left True, align_paren True

The following code would fail with this option:

constant c_const : t_type := (
  1 => func1(
    G_GENERIC1, G_GENERIC2)
);

The following code would pass with this option:

constant c_const : t_type := (
  1 => func1(
               G_GENERIC1, G_GENERIC2)
);

Configuring Multiline Structure Rules

There are rules which will check indent and formatting of multiline expressions and conditions.

The alignment of multiline rules is handled by a corresponding rule. Both rules are required to ensure proper formatting of multiline expressions and conditions. The corresponding rule will be noted in the rule documentation.

There are several options to these rules:

Method Type Default Description
first_paren_new_line string yes First opening parenthesis on it’s own line.
last_paren_new_line string yes Last closing parenthesis on it’s own line.
open_paren_new_line string yes Insert new line after open parenthesis.
close_paren_new_line string yes Insert new line before close parenthesis.
new_line_after_comma string yes Insert new line after the commas.
assign_on_single_line string yes Keep assignments on a single line.
ignore_single_line string yes Do not apply rules if expression/condition is contained on a single line.
move_last_comment string ignore If last_paren_new_line is ‘yes’, then move any trailing comments to the previous line.

The options can be combined to format the output.

Each option except new_line_after_comma and assign_on_single_line allows one of three values: yes, no and ignore.

Option Value Action
yes Option will be enforced.
no The inverse of the Option will be enforced.
ignore The option will be ignored.

The new_line_after_comma option allows one of four values: yes, no, ignore and ignore_positional.

Option Value Action
yes Insert new line after commas.
no Remove new line after commas.
ignore Ignore commas.
ignore_positional Insert new line after commas unless elements are positional.

The assign_on_single_line option allows one of two values: yes and ignore.

Option Value Action
yes Force assignments to a single line.
ignore Allow assignments to span multiple lines.

This is an example of how to configure these options.

rule :
  constant_012:
     first_paren_new_line : 'yes'
     last_paren_new_line : 'yes'
     open_paren_new_line : 'yes'
     close_paren_new_line : 'yes'
     new_line_after_comma : 'ignore'
     ignore_single_line : 'no'

Note

All examples below are using the rule constant_016 and the option ignore_single_line is False.

Example: first_paren_new_line

The following code would fail with this option:

constant c_const : t_type := (a => 0, b => 1);

The following code would pass with this option:

constant c_const : t_type :=
(a => 0, b => 1);

Example: last_paren_new_line

The following code would fail with this option:

constant c_const : t_type := (a => 0, b => 1);

The following code would pass with this option:

constant c_const : t_type := (a => 0, b => 1
);

Example: first_paren_new_line and last_paren_new_line

The following code would fail with this option:

constant c_const : t_type := (a => 0, b => 1);

The following code would pass with this option:

constant c_const : t_type :=
(
  a => 0, b => 1
);

Example: new_line_after_comma

The following code would fail with this option:

constant c_const : t_type := (a => 0, b => 1);

The following code would pass with this option:

constant c_const : t_type := (a => 0,
b => 1);

Example: new_line_after_comma and first_paren_new_line and last_paren_new_line

The following code would fail with this option:

constant c_const : t_type := (a => 0, b => 1);

The following code would pass with this option:

constant c_const : t_type :=
(a => 0,
 b => 1);

Example: open_paren_new_line

The following code would fail with this option:

constant c_const : t_type := ((a => 0, b => 1), (c => 0, d => 1));

The following code would pass with this option:

constant c_const : t_type := (
(
  a => 0, b => 1), (
c => 0, d => 1));

Example: close_paren_new_line

The following code would fail with this option:

constant c_const : t_type := ((a => 0, b => 1), (c => 0, d => 1));

The following code would pass with this option:

constant c_const : t_type := ((a => 0, b => 1
                              ), (c => 0, d => 1
                              ));

Example: open_paren_new_line and close_paren_new_line

The following code would fail with this option:

constant c_const : t_type := ((a => 0, b => 1), (c => 0, d => 1));

The following code would pass with this option:

constant c_const : t_type := (
(
  a => 0, b => 1
), (
  c => 0, d => 1
));

Example: all options yes

The following code would fail with this option:

constant c_const : t_type := ((a => 0, b => 1), (c => 0, d => 1));

The following code would pass with this option:

constant c_const : t_type :=
(
  (
    a => 0,
    b => 1
  ),
  (
    c => 0,
    d => 1
  )
);

Example: all options no

The following code would pass with this option:

constant c_const : t_type :=
(
  (
    a => 0,
    b => 1
  ),
  (
    c => 0,
    d => 1
  )
);

The following code would fail with this option:

constant c_const : t_type := ((a => 0, b => 1), (c => 0, d => 1));

Example: assign_on_single_line

The following code would pass with this option set to True:

constant c_const : t_type :=
(
  1 => func1(std_logic_vector(G_GEN), G_GEN2),
  2 => func1(std_logic_vector(G_GEN), G_GEN2)
);

The following code would fail with this option set to True:

constant c_const : t_type :=
(
  1 => func1(std_logic_vector(G_GEN), G_GEN2),
  2 => func1(
             std_logic_vector(G_GEN), G_GEN2)
);

Example: last_paren_new_line and move_last_comment

The following code would fail with this option:

constant c_const : t_type :=
(
  a => 0,
  b => 1); -- Comment

The following code would pass with this option:

constant c_const : t_type :=
(
  a => 0,
  b => 1 -- Comment
);

Rules Enforcing Multiline Structure Rules

Configuring Concurrent Alignment Rules

There are rules which will check indent and alignment of multiline conditional expressions and conditional waveforms.

Conditional expressions and conditional waveforms are defined as:

conditional_expressions ::=
  expression **when** condition
  { **else** expression **when** condition }
  [ **else** expression ]

conditional_waveforms ::=
  waveform **when** condition
  { **else** waveform **when** condition }
  [ **else** waveform ]

Below is an example of a conditional waveform:

architecture rtl of fifo is

begin

  output <= '1' when input = "00" else
            sig_a or sig_b when input = "01" else
            sig_c and sig_d when input = "10" else
            '0';

end architecture rtl;

The alignment of multiline rules is handled by a corresponding rule. Both rules are required to ensure proper formatting of multiline expressions and conditions. The corresponding rule will be noted in the rule documentation.

There are several options to these rules:

Option Type Default Description
align_left string ‘no’ Align multilines to the left.
align_paren string ‘yes’ Indent lines based on parenthesis.
align_when_keywords string ‘no’ Each when keyword will be aligned.
wrap_at_when string ‘yes’ Indent multiline condition at ‘when’ keyword.
align_else_keywords string ‘no’ Each else keyword will be aligned.

The options can be combined to format the conditional expression or conditional waveform.

Each option allows one of two values: ‘yes’ and ‘no’.

Option Value Action
‘yes’ Option will be enforced.
‘no’ The inverse of the Option will be enforced.

This is an example of how to configure these options.

rule :
  concurrent_009:
     wrap_at_when : 'yes'
     align_when_keywords : 'yes'
     align_else_keywords : 'yes'
     align_left : 'no'

Note

All examples below are using the rule concurrent_009.

Example: indent_condition_at_when

The following code would fail with this option:

output <= '1' when input = "0000" or
    input = "1111" else
  sig_a or sig_b when input = "0001" and
    input = "1001" else
  sig_c and sig_d when input = "0010" or
    input = "1010" else
  '0';

The following code would pass with this option:

output <= '1' when input = "0000" or
                   input = "1111" else
  sig_a or sig_b when input = "0001" and
                      input = "1001" else
  sig_c and sig_d when input = "0010" or
                       input = "1010" else
  '0';

Example: align_when_keywords

The following code would fail with this option:

output <= '1' when input = "00" else
          sig_a or sig_b when input = "01" else
          sig_c and sig_d when input = "10" else
          '0';

The following code would pass with this option:

output <= '1'             when input = "00" else
          sig_a or sig_b  when input = "01" else
          sig_c and sig_d when input = "10" else
          '0';

Example: align_when_keywords and align_else_keywords

The following code would fail with this option:

output <= '1' when input = "0000" else
          sig_a or sig_b when input = "0100" and input = "1100" else
          sig_c when input = "10" else
          '0';

The following code would pass with this option:

output <= '1'            when input = "0000"                    else
          sig_a or sig_b when input = "0100" and input = "1100" else
          sig_c          when input = "10"                      else
          '0';

Example: align_left ‘yes’

The following code would fail with this option:

output <= '1' when input = "0000" else
          sig_a or sig_b when input = "0100" and input = "1100" else
          sig_c when input = "10" else
          '0';

The following code would pass with this option:

output <= '1' when input = "0000" else
  sig_a or sig_b when input = "0100" and input = "1100" else
  sig_c when input = "10" else
  '0';

Example: align_left ‘no’

The following code would fail with this option:

output <= '1' when input = "0000" else
  sig_a or sig_b when input = "0100" and input = "1100" else
  sig_c when input = "10" else
  '0';

The following code would pass with this option:

output <= '1' when input = "0000" else
          sig_a or sig_b when input = "0100" and input = "1100" else
          sig_c when input = "10" else
          '0';

Example: align_paren ‘yes’ and align_left ‘no’

The following code would fail with this option:

output <= '1' when func1(func2(G_VALUE1,
                     G_VALUE2), func3(
                     G_VALUE3)
                     ) else
          '0';

The following code would pass with this option:

output <= '1' when func1(func2(G_VALUE1,
                                G_VALUE2), func3(
                                                  G_VALUE3)
                        ) else
          '0';

Rules Enforcing Conditional Expression

Configuring Concurrent Structure Rules

There are rules which will check the structure of conditional expressions and waveforms.

The alignment of multiline rules is handled by a corresponding rule. Both rules are required to ensure proper formatting of multiline conditional expressions and waveforms. The corresponding rule will be noted in the rule documentation.

There are several options to these rules:

Method Type Default Description
new_line_after_assign string no First opening parenthesis on it’s own line.
ignore_single_line string yes Do not apply rules if expression/condition is contained on a single line.

The options can be combined to format the output.

Each option except ignore_single_line allows one of three values: yes, no and ignore.

Option Value Action
yes Option will be enforced.
no The inverse of the Option will be enforced.
ignore The option will be ignored.

The ignore_single_line option allows one of two values: yes and ignore.

Option Value Action
yes Force assignments to a single line.
ignore Allow assignments to span multiple lines.

This is an example of how to configure these options.

rule :
  concurrent_011:
     ignore_single_line : 'no'

Note

All examples below are using the rule concurrent_011 and the option ignore_single_line is ‘no’.

Example: new_line_after_assign

The following code would fail with this option:

write_en <= '1' when sig1 = "00" else '0';

The following code would pass with this option:

write_en <=
  '1' when sig1 = "00" else '0';

Rules Enforcing Conditional Expression Structure