VHDL Coding Style Guidelines

(Adapted from Xilinx's Coding Style Guidelines)


Table of Contents




Section 1 - Top-Down Design


Behavioural and Structural Code

"When creating synthesizable code (RTL), you should write two types of code: behavioral RTL (leaf-level logic inference, sub-blocks) and structural code (blocks) -- each exclusively in its own architecture." - Xilinx

Essentially, this means that, rather than mixing behavioural and structural VHDL in one descriptive file, you should separate your VHDL code. Ideally, in creating a formal design that would be iterated over and updated repeatedly, there should be no signal assignments. In our environment, it is not a large problem to invert a signal or merge two signals into a bus, but major behavioural code such as processes and case statements should be contained within their own behavioural descriptions and not in a structural file.

Always keep in mind that your VHDL code is not just a random assortment of files, but rather a hierarchy of structural elements specifically placed to create a well defined design.

Behavioural

architecture <arch-name> of <entity-name> is
begin

output <= input_1 or input_2;
end <arch-name>;

Structural

architecture <arch-name> of <entity-name> is
component or_entity
port(
output: out std_logic;
input_1: in std_logic;
input_2: in std_logic
);
end component;
begin
or_1: or_entity
port map(
output => o,
input_1 => i_1,
input_2 => i_2
);
end <arch-name>;


Declarations, Instantiations, and Mappings

"It is important to use a consistent, universal style for such things as entity declarations, component declarations, port mappings, functions, and procedures." - Xilinx

Comments

"Liberal comments are mandatory to maintain reusable code. Although VHDL is sometimes considered to be self-documenting code, it requires liberal comments to clarify intent, as any VHDL user can verify." - Xilinx

When people describe VHDL as 'self documenting', generally they are talking about understanding that a signal assignment has occurred, not understanding the idea behind the assignment. As far as understanding reasoning for signal assignments, VHDL alone cannot possibly fully describe what is going on without comments. This is why there are three general rules for commenting:

Indentation

"Proper indentation ensures readability and reuse. Therefore, a consistent style is warranted. Many text editors are VHDL-aware, automatically indenting for 'blocks' of code, providing consistent indentation. Emacs and CodeWright are two of the most common editors that have this capability. Figure 13-7 shows an example of proper indentation. Proper indentation greatly simplifies reading the code. If it is easier to read, it is less likely that there will be coding mistakes by the designer." - Xilinx

Indentation is an important aspect of VHDL. Knowing where sections of code begin and end is very important in creating readable updateable code. Both the Foundation and the Sonata editors have the abilities to indent code, so this should not be too much of a problem. As for when to indent, the simple rule of thumb is that any section of code that is marked by an end (and, optionally, a begin) keyword should have its body indented. This includes component declarations, process statements, if statements, case statements, entity declarations and architectures.

Naming Conventions

"Naming conventions maintain a consistent style, which facilitates design reuse. If all designers use the same conventions, designer A can easily understand and use designer B's VHDL code." - Xilinx

These are, once again, general rules, but they are designed to make your code easier to read, understand, and debug. By following these rules, it also makes it easier for others to understand your code.


Section 2 - Signals and Variables


Casting

"The most common problem [with signals] is that signals can be various data types. The problem in VHDL is "casting" from one data type to another. Unfortunately, no single function can automatically cast one signal type to another. Therefore, the use of a standard set of casting functions is important to maintain consistency between designers" - Xilinx

Because VHDL is a strongly typed language, casting from one type to another is a requirement and can, at times, be difficult. There are a number of packages available with functions used for casting. In this lab, we have chosen to use the ieee.numeric_std package. It comes with all the functions that you will need and is a standardly available package. The table below shows pertinent castings that you may need for this lab:

From To Function
std_logic_vector unsigned unsigned(std_logic_vector)
unsigned integer to_integer(unsigned)
integer unsigned to_unsigned(integer, no_of_bits)
unsigned std_logic_vector std_logic_vector(unsigned)

Rules for Signals

"The rules for signals are not complex" - Xilinx

There are very few rules for signals:

Rules for Variables

"Variables are commonly not understood and are therefore not used. Variables are also commonly used and not understood. Variables can be very powerful when used correctly. This warrants an explanation of how to properly use variables" - Xilinx

When combinatorial signals are to be used within a process, most often a designer will use variables. Variables, however, are treated quite differently than signals during synthesis and implementation.

Variables are not synthesized necessarily as physical wires (whereas signals are). As such, their assignments are not purely combinatorial. Assignment to a variable depends on its order in a sequence of statements. The following is two uses of variables:

Correct Variable Assignment Incorrect Variable Assignment
variable := a and b;
c <= variable or e;
d <= variable or f;
c <= variable or e;
d <= variable or f;
variable := a and b;


The assignment on the left writes to the variable before reading from it. As a result, the variable simply becomes a wire connecting the output of an andgate to the inputs of two or gates. The assignment on the right, however, reads the variable before writing to it. This tells the synthesis tool that the value being read is the previous value of the variable. As a result, the value is stored sequentially and this leads to a 'latch inferred' warning.


Section 3 - Synchronous Design


Clocking

"In a synchronous design, only one clock and one edge of the clock should be used..." - Xilinx

An important technique in design is the synchronization of designs with a clock. A regularly alternating signal, the clock provides a time during which signals can be checked and memory units (registers, flip-flops, etc.) can be updated. There are a number of considerations that must be made when using the clock, however.

Finite State Machines

"Coding for Finite State Machines (FSM) includes analyzing several tradeoffs." - Xilinx

FSMs are extremely useful tools in digital design. They used in many different applications so there are some standard rules regarding their implementation:

Section 4 - Logic Level Reduction


Conditional Statements

"If-then-else and case statements can cause unwanted effects in a design. Specifically, nested if-the-else and case statements may cause extra levels of logic inference. This occurs because if-then-else statements generally infer priority-encoded logic. However, one level of an if-then-else will not necessarily create priority-encoded logic. For that matter, synthesis tools generally handle if-then-else or case statements very well and create parallel logic rather than priority-encoded logic." - Xilinx

Conditions in if-then-else statements very often are synthesized as combinatorial logic (and gates, or gates, etc.). As a result, nested statements will create deeper combinatorial logic causing complications in timing, gate delays and could create a priority encoding situation that is undesired by the designer. Therefore, there are a few simple guidelines to follow when using conditional statements:

[Return to CMPUT 329 Lab Home Page]
Created by Paras Mehta, 2003