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.
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.
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.
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);
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.
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.
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
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.
ASYNC_FF: process (CLK,RST)
always @ (posedge CLK or posedge RST)
begin: ASYNC_FF
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.
-- D_REGISTER.VHD
-- May 1997
-- Changing Latch into a D-Register
library IEEE;
use IEEE.std_logic_1164.all;
entity d_register is
port (CLK, DATA: in STD_LOGIC;
Q: out STD_LOGIC);
end d_register;
architecture BEHAV of d_register is
begin
My_D_Reg: process (CLK, DATA)
begin
if (CLK'event and CLK='1') then
Q <= DATA;
end if;
end process; --End My_D_Reg
end BEHAV;
/* Changing Latch into a D-Register
* D_REGISTER.V
* May 1997 */
module d_register (CLK, DATA, Q);
input CLK;
input DATA;
output Q;
reg Q;
always @ (posedge CLK)
begin: My_D_Reg
Q <= DATA;
end
endmodule
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.
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;
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.
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
parameter BUS_SIZE = 8;
output [`BUS_SIZE-1:0] OUT;
input [`BUS_SIZE-1:0] X,Y;
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.
CLK_1: BUFGS port map (I=>CLOCK_IN,CLOCK_OUT);
CLK_1: BUFGS port map (I=>CLOCK_IN,O=>CLOCK_OUT);
BUFGS CLK_1 (.I(CLOCK_IN), CLOCK_OUT);
BUFGS CLK_1 (.I(CLOCK_IN), .O(CLOCK_OUT));
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.
Use the recommendations in this section to create code that is easy to read.
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.
-- D_LATCH.VHD
-- May 1997
library IEEE;
use IEEE.std_logic_1164.all;
entity d_latch is
port (GATE, DATA: in STD_LOGIC;
Q: out STD_LOGIC);
end d_latch;
architecture BEHAV of d_latch is
begin
LATCH: process (GATE, DATA)
begin
if (GATE = '1') then
Q <= DATA;
end if;
end process; -- end LATCH
end BEHAV;
/* Transparent High Latch
* D_LATCH.V
* May 1997 */
module d_latch (GATE, DATA, Q);
input GATE;
input DATA;
output Q;
reg Q;
always @ (GATE or DATA)
begin: LATCH
if (GATE == 1'b1)
Q <= DATA;
end // End Latch
endmodule
Use empty lines to separate top-level constructs, designs, architectures, configurations, processes, subprograms, and packages.
Use spaces to make your code easier to read. You can omit or use spaces between signal names as shown in the following examples.
process (RST,CLOCK,LOAD,CE)
process (RST, CLOCK, LOAD, CE)
module test (A,B,C)
module test (A, B, C)
Use a space after colons as shown in the following examples.
signal QOUT: STD_LOGIC_VECTOR (3 downto 0);
CLK_1: BUFGS port map (I=>CLOCK_IN,O=>CLOCK_OUT);
begin: CPU_DATA
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.
U1: load_reg port map
(INX=>A,LOAD=>LD,CLK=>SCLK,OUTX=>B);
load_reg U1
(.INX(A), .LOAD(LD), .CLK(SCLK), .OUTX(B));
Add comments to your code to improve readability, reduce debugging time, and make it easier to maintain your code.
-- Read Counter (16-bit)
-- Updated 1-25-98 to add Clock Enable, John Doe
-- Updated 1-28-98 to add Terminal Count, Joe Cool
process (RST, CLOCK, CE)
begin
.
.
.
// Read Counter (16-bit)
// Updated 1-25-98 to add Clock Enable, John Doe
// Updated 1-28-98 to add Terminal Count, Joe Cool
always @ (posedge RST or posedge CLOCK)
begin
.
.
.
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.
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.
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;
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.
-- 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;
-- 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;