Return to previous page Advance to next page
Synthesis and Simulation Design Guide
Chapter 2: HDL Coding Hints

Selecting HDL Formatting Styles

Because HDL designs are often created by design teams, Xilinx recommends that you agree on a style for your code at the beginning of your project. An established coding style allows you to read and understand code written by your fellow team members. Also, inefficient coding styles can adversely impact synthesis and simulation, which can result in slow circuits. Additionally, because portions of existing HDL designs are often used in new designs, you should follow coding standards that are understood by the majority of HDL designers. This section of the manual provides a list of suggested coding styles that you should establish before you begin your designs.

Selecting a Capitalization Style

Select a capitalization style for your code. Xilinx recommends using a consistent style (lower or upper case) for entity or module names in FPGA designs.

Verilog

For Verilog, the following style is recommended.

Note: Cell names must be upper case to use the UniSim simulation library and certain synthesis libraries. Check with your synthesis vendor.

VHDL

Note: VHDL is case-insensitive.

For VHDL, use lower case for all language constructs from the IEEE-STD 1076. Any inputs defined by you should be upper case. For example, use upper case for the names of signals, instances, components, architectures, processes, entities, variables, configurations, libraries, functions, packages, data types, and sub-types. For the names of standard or vendor packages, the style used by the vendor or uppercase letters are used, as shown for IEEE in the following example:

library IEEE;
use IEEE.std_logic_1164.all;
signal SIG: UNSIGNED (5 downto 0);

Using Xilinx Naming Conventions

Use the Xilinx naming conventions listed in this section for naming signals, variables, and instances that are translated into nets, buses, and symbols.

Note: Most synthesis tools convert illegal characters to legal ones.

The following FPGA resource names are reserved and should not be used to name nets or components.

Refer to the language reference manual for Verilog or VHDL for language-specific naming restrictions. Xilinx does not recommend using escape sequences for illegal characters. Also, if you plan on importing schematics into your design, use the most restrictive character set.

Matching File Names to Entity and Module Names

The VHDL or Verilog source code file name should match the designated name of the entity (VHDL) or module (Verilog) specified in your design file. This is less confusing and generally makes it easier to create a script file for the compilation of your design. Xilinx also recommends that if your design contains more than one entity or module, each should be contained in a separate file with the appropriate file name. It is also a good idea to use the same name as your top-level design file for your synthesis script file with either a .do, .scr, .script, or the appropriate default script file extension for your synthesis tool.

Naming Identifiers, Types, and Packages

You can use long (256 characters maximum) identifier names with underscores and embedded punctuation in your code. Use meaningful names for signals and variables, such as CONTROL_REGISTER. Use meaningful names when defining VHDL types and packages as shown in the following examples.

type LOCATION_TYPE is ...;
package STRING_IO_PKG is

Using Labels

Use labels to group logic. Label all processes, functions, and procedures as shown in the following examples. Labeling makes it easier to debug your code.

Labeling Flow Control Constructs

You can use optional labels on flow control constructs to make the code structure more obvious, as shown in the following VHDL and Verilog examples. However, you should note that these labels are not translated to gate or register names in your implemented design. Flow control constructs can slow down simulations in some Verilog simulators.

Using Variables for Constants (VHDL Only)

Do not use variables for constants in your code. Define constant numeric values in your code as constants and use them by name. This coding convention allows you to easily determine if several occurrences of the same literal value have the same meaning. In some simulators, using constants allows greater optimization. In the following code example, the OPCODE values are declared as constants, and the constant names refer to their function. This method produces readable code that may be easier to modify.

Using Constants to Specify OPCODE Functions (VHDL)

constant ZERO   : STD_LOGIC_VECTOR (1 downto 0):=“00”;
constant A_AND_B: STD_LOGIC_VECTOR (1 downto 0):=“01”;
constant A_OR_B : STD_LOGIC_VECTOR (1 downto 0):=“10”;
constant ONE : STD_LOGIC_VECTOR (1 downto 0):=“11”;

process (OPCODE, A, B)
begin
if (OPCODE = A_AND_B)then OP_OUT <= A and B;
elsif (OPCODE = A_OR_B) then OP_OUT <= A or B;
elsif (OPCODE = ONE) then OP_OUT <= `1';
else OP_OUT <= `0';
end if;
end process;

Using Parameters for Constants (Verilog Only)

You can specify a constant value in Verilog using the parameter special data type, as shown in the following examples. The first example includes a definition of OPCODE constants as shown in the previous VHDL example. The second example shows how to use a parameter statement to define module bus widths.

Using Parameters to Specify OPCODE Functions (Verilog)

parameter ZERO = 2'b00;
parameter A_AND_B = 2'b01;
parameter A_OR_B = 2'b10;
parameter ONE = 2'b11;

always @ (OPCODE or A or B)
begin
if (OPCODE==`ZERO) OP_OUT=1'b0;
else if(OPCODE==`A_AND_B) OP_OUT=A&B;
else if(OPCODE==`A_OR_B) OP_OUT=A|B;
else OP_OUT=1'b1;
end

Using Parameters to Specify Bus Size (Verilog)

parameter BUS_SIZE = 8;

output [`BUS_SIZE-1:0] OUT;
input [`BUS_SIZE-1:0] X,Y;

Using Named and Positional Association

Use positional association in function and procedure calls, and in port lists only when you assign all items in the list. Use named association when you assign only some of the items in the list. Also, Xilinx suggests that you use named association to prevent incorrect connections for the ports of instantiated components. Do not combine positional and named association in the same statement as illustrated in the following examples.

Managing Your Design

As part of your coding specifications, you should include rules for naming, organizing, and distributing your files. In VHDL designs, use explicit configurations to control the selection of components and architectures that you want to compile, simulate, or synthesize. In some synthesis tools, configuration information is ignored. In this case, you only need to compile the architecture that you want to synthesize.

Creating Readable Code

Use the recommendations in this section to create code that is easy to read.

Indenting Your Code

Indent blocks of code to align related statements. You should define the number of spaces for each indentation level and specify whether the Begin statement is placed on a line by itself. In the examples in this manual, each level of indentation is four spaces and the Begin statement is on a separate line that is not indented from the previous line of code. The examples below illustrate the indentation style used in this manual.

Using Empty Lines

Use empty lines to separate top-level constructs, designs, architectures, configurations, processes, subprograms, and packages.

Using Spaces

Use spaces to make your code easier to read. You can omit or use spaces between signal names as shown in the following examples.

Use a space after colons as shown in the following examples.

Breaking Long Lines of Code

Break long lines of code at an appropriate point, such as at a comma, a colon, or a parenthesis to make your code easier to read, as illustrated in the following code fragments.

Adding Comments

Add comments to your code to improve readability, reduce debugging time, and make it easier to maintain your code.

Using Std_logic Data Type (VHDL only)

The Std_logic (IEEE 1164) type is recommended for hardware descriptions for the following reasons.

The back-annotated netlist from Xilinx implementation is in Std_logic. If you do not use Std_logic type to drive your top-level entity in the testbench, you cannot reuse your functional testbench for timing simulation. Some synthesis tools can create a wrapper for type conversion between the two top-level entities; however, this is not recommended by Xilinx.

Declaring Ports

Xilinx recommends that you use the Std_logic package for all entity port declarations. This package makes it easier to integrate the synthesized netlist back into the design hierarchy without requiring conversion functions for the ports. A VHDL example using the Std_logic package for port declarations is shown below.

Entity alu is
port( A : in STD_LOGIC_VECTOR(3 downto 0);
B : in STD_LOGIC_VECTOR(3 downto 0);
CLK : in STD_LOGIC;
C : out STD_LOGIC_VECTOR(3 downto 0) );
end alu;

Since the downto convention for vectors is supported in a back-annotated netlist, the RTL and synthesized netlists should use the same convention if you are using the same test bench. This is necessary because of the loss of directionality when your design is synthesized to an EDIF or XNF netlist.

Minimizing the Use of Ports Declared as Buffers

Do not use buffers when a signal is used internally and as an output port. In the following VHDL example, signal C is used internally and as an output port.

Entity alu is
port( A : in STD_LOGIC_VECTOR(3 downto 0);
B : in STD_LOGIC_VECTOR(3 downto 0);
CLK : in STD_LOGIC;
C : buffer STD_LOGIC_VECTOR(3 downto 0) );
end alu;

architecture BEHAVIORAL of alu is
begin
process begin
if (CLK'event and CLK='1') then
C <= UNSIGNED(A) + UNSIGNED(B) + UNSIGNED(C);
end if;
end process;
end BEHAVIORAL;

Because signal C is used both internally and as an output port, every level of hierarchy in your design that connects to port C must be declared as a buffer. However, buffer types are not commonly used in VHDL designs because they can cause problems during synthesis. To reduce the amount of buffer coding in hierarchical designs, you can insert a dummy signal and declare port C as an output, as shown in the following VHDL example.

Entity alu is
port( A : in STD_LOGIC_VECTOR(3 downto 0);
B : in STD_LOGIC_VECTOR(3 downto 0);
CLK : in STD_LOGIC;
C : out STD_LOGIC_VECTOR(3 downto 0));
end alu;

architecture BEHAVIORAL of alu is
-- dummy signal
signal C_INT : STD_LOGIC_VECTOR(3 downto 0);
begin
C <= C_INT;
process begin
if (CLK'event and CLK='1') then
C_INT < =UNSIGNED(A) + UNSIGNED(B) +
UNSIGNED(C_INT);

      end if;
end process;
end BEHAVIORAL;

Comparing Signals and Variables (VHDL only)

You can use signals and variables in your designs. Signals are similar to hardware and are not updated until the end of a process. Variables are immediately updated and, as a result, can effect the functioning of your design. Xilinx recommends using signals for hardware descriptions; however, variables allow quick simulation.

The following VHDL examples show a synthesized design that uses signals and variables, respectively. These examples are shown implemented with gates in the “Gate implementation of XOR_SIG” figure and the “Gate Implementation of XOR_VAR” figure.

Note: If you assign several values to a signal in one process, only the final value is used. When you assign a value to a variable, the assignment takes place immediately. A variable maintains its value until you specify a new value.

Using Signals (VHDL)

-- XOR_SIG.VHD
-- May 1997
Library IEEE;
use IEEE.std_logic_1164.all;

entity xor_sig is
port (A, B, C: in STD_LOGIC;
X, Y: out STD_LOGIC);
end xor_sig;

architecture SIG_ARCH of xor_sig is
signal D: STD_LOGIC;
begin
SIG:process (A,B,C)
begin
D <= A; -- ignored !!
X <= C xor D;
D <= B; -- overrides !!
Y <= C xor D;
end process;
end SIG_ARCH;

Figure 2.1 Gate implementation of XOR_SIG

Using Variables (VHDL)

-- XOR_VAR.VHD
-- May 1997

Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity xor_var is
port (A, B, C: in STD_LOGIC;
X, Y: out STD_LOGIC);
end xor_var;

architecture VAR_ARCH of xor_var is
begin

VAR:process (A,B,C)
variable D: STD_LOGIC;
begin
D := A;
X <= C xor D;
D := B;
Y <= C xor D;
end process;
end VAR_ARCH;

Figure 2.2 Gate Implementation of XOR_VAR