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:
- Block level configurations
- 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 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
Rules Disabled by Default¶
- after_001
- after_002
- after_003
- architecture_025
- block_600
- block_601
- block_comment_001
- block_comment_002
- block_comment_003
- comment_011
- constant_015
- generate_017
- generic_020
- instantiation_600
- instantiation_601
- package_016
- package_017
- package_body_600
- package_body_601
- port_011
- port_025
- process_036
- signal_008
- subtype_004
- type_015
- variable_012
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¶
- architecture_004
- architecture_009
- architecture_011
- architecture_013
- architecture_014
- architecture_019
- architecture_020
- architecture_021
- architecture_028
- attribute_declaration_500
- attribute_declaration_501
- attribute_declaration_502
- attribute_specification_500
- attribute_specification_501
- attribute_specification_502
- attribute_specification_503
- block_500
- block_501
- block_502
- block_503
- block_504
- block_505
- block_506
- case_014
- case_015
- case_016
- case_017
- case_018
- component_004
- component_006
- component_008
- component_010
- component_012
- component_014
- constant_002
- constant_004
- constant_011
- constant_013
- context_004
- context_012
- context_013
- context_014
- context_015
- context_016
- context_ref_003
- context_ref_004
- entity_004
- entity_006
- entity_008
- entity_010
- entity_012
- entity_014
- entity_specification_500
- entity_specification_501
- entity_specification_502
- entity_specification_503
- file_statement_002
- for_loop_003
- function_004
- function_005
- function_010
- function_013
- function_014
- function_017
- generate_005
- generate_009
- generate_010
- generate_012
- generic_007
- generic_009
- generic_017
- generic_map_001
- generic_map_002
- if_statement_025
- if_statement_026
- if_statement_027
- if_statement_028
- if_statement_029
- if_statement_034
- instantiation_008
- instantiation_009
- instantiation_027
- instantiation_031
- library_004
- library_005
- package_004
- package_006
- package_008
- package_010
- package_013
- package_018
- package_body_500
- package_body_501
- package_body_502
- package_body_503
- package_body_504
- package_body_505
- package_body_506
- package_body_507
- port_010
- port_017
- port_018
- port_019
- port_map_001
- port_map_002
- procedure_007
- procedure_008
- procedure_009
- process_004
- process_005
- process_008
- process_009
- process_013
- process_017
- process_019
- range_001
- range_002
- signal_002
- signal_004
- signal_010
- signal_011
- signal_014
- subtype_002
- type_definition_002
- type_definition_004
- type_definition_013
- type_definition_014
- variable_002
- variable_004
- variable_010
- variable_011
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.
compact_alignment
- if set toTrue
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 toTrue
.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;
blank_line_ends_group
- if set toTrue
any blank line encountered in the VHDL file ends the group of lines that should be aligned and starts new group. By default set toTrue
.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;
comment_line_ends_group
- if set toTrue
any purely comment line in the VHDL file ends the group of lines that should be aligned and starts new group. By default set toTrue
.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¶
separate_generic_port_alignment
- if set toTrue
alignment within the generic declarative/mapping part is separated from alignment within the port declarative/mapping part. By default set toTrue
.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 );
if_control_statements_end_group
- if set toTrue
any line with if control statement ends the group of lines that should be aligned and starts new group. By default set toTrue
.Violation
if condition = '1' then data_valid <= '1'; data <= '1'; else data_valid <= '0'; hold_transmission <= '1'; end if;
Fix (if_control_statements_end_group = True)
if condition = '1' then data_valid <= '1'; data <= '1'; else data_valid <= '0'; hold_transmission <= '1'; end if;
Fix (if_control_statements_end_group = False)
if condition = '1' then data_valid <= '1'; data <= '1'; else data_valid <= '0'; hold_transmission <= '1'; end if;
case_control_statements_end_group
- if set toTrue
any line with case control statement ends the group of lines that should be aligned and starts new group. By default set toTrue
.Violation
case A is when A => X <= F; XY <= G; XYZ <= H; when B => a <= I; ab <= h; c <= a; when others => null; end case
Fix (case_control_statements_end_group = True)
case A is when A => X <= F; XY <= G; XYZ <= H; when B => a <= I; ab <= h; c <= a; when others => null; end case
Fix (case_control_statements_end_group = False)
case A is when A => X <= F; XY <= G; XYZ <= H; when B => a <= I; ab <= h; c <= a; when others => null; end case
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.
Rules Enforcing Keyword Alignment¶
- after_002
- architecture_026
- architecture_027
- block_401
- component_017
- component_020
- concurrent_006
- concurrent_008
- context_028
- entity_017
- entity_018
- entity_020
- function_012
- generate_401
- generate_403
- generate_405
- instantiation_010
- instantiation_029
- process_033
- process_034
- process_035
- sequential_005
- type_400
- variable_assignment_005
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.
blank_line_ends_group
- if set toTrue
any blank line encountered in the VHDL file ends the group of lines that should be aligned and starts new group. By default set toTrue
.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;
comment_line_ends_group
- if set toTrue
any purely comment line in the VHDL file ends the group of lines that should be aligned and starts new group. By default set toTrue
.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.
Rules Enforcing Identifier Alignment¶
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;
Rules Enforcing Blank Lines¶
- architecture_015
- architecture_016
- architecture_017
- architecture_018
- architecture_200
- block_201
- block_202
- block_203
- block_204
- block_205
- case_008
- case_009
- case_010
- component_018
- context_023
- context_024
- context_025
- function_007
- generate_003
- if_030
- instantiation_019
- package_011
- package_012
- package_body_201
- package_body_202
- package_body_203
- process_011
- process_021
- process_022
- process_023
- process_026
- process_027
- type_011
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
Rules Enforcing Previous Lines¶
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
Rules Enforcing Block Comments¶
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>” “-<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)
);
Rules Enforcing Multiline Indent Rules¶
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';