ADI HDL coding guidelines

1. Introduction

This document contains coding and documentation guidelines which must be followed by all HDL projects. The purpose of this document is to establish a set of rules that specify the layout, naming conventions and some general coding practices for the HDL modules implementation. Specific HDL coding practices meant to obtain maximum performance from a FPGA design are described by external documents such as [1] and [2] and are not included in this document.

There are two types of rules: should and must rules
  • Should rules are advisory rules. They suggest the recommended way of doing things.

  • Must rules are mandatory requirements.

The coding rules are intended to be applied to HDL modules written using VHDL or Verilog.

When an external IP is used, the naming conventions practiced by the IP should be kept, even if they do not match the rules specified in this document.

2. Coding style

A. Layout

A1

Spaces must be used instead of tabs.

This allows the code to be properly visualized by any editor. Do not leave spaces at the end of a line. The following editor settings must be used: Tab Size: 2, Indent Size: 2.

A2

One white space must be inserted around operators, such as =, ==, &&, ||, &, |, ^, etc.

Incorrect:

if((my_signal1==1'b0)&&(my_bus[3:0]==4'd5))

Correct:

if ((my_signal == 1'b0) && (my_bus[3:0] == 4'd5))

A3

The always block should have a space before **@** symbol.

Incorrect:

always@(posedge clk) begin
  ...
end

Correct:

always @(posedge clk) begin
  ...
end

A4

The Verilog begin/end block must always be used, even if there is only one statement. This makes adding lines of code much easier and with fewer errors.

A5

Indentation levels must be used to show code nesting. Blank lines may be used as desired to improve code readability, but not in all cases.

Incorrect:

 1if (my_signal == 1'b0) begin
 2  if (my_bus[3:0]==4'd5) begin
 3  statement1;
 4  statement2;
 5  end
 6statement3;
 7statement4;
 8end
 9else
10statement5;

Correct:

 1if (my_signal == 1'b0) begin
 2  if (my_bus[3:0] == 4'd5) begin
 3    statement1;
 4    statement2;
 5  end
 6  statement3;
 7  statement4;
 8end else begin
 9  statement5;
10end

A6

In a case definition, indentation levels must be used to offset the statements that are encapsulated, but the use of blank lines can be used or omitted to best show the statement groupings (if really necessary). end should be indented as in the correct example.

Incorrect:

 1case ( my_bus[3:0] )
 2  4'b0000 : my_signal1 = TRUE;
 3  4'b0001 : my_signal1 = FALSE;
 4  4'b0010 :
 5  begin
 6  my_signal1 = TRUE;
 7  my_signal2 = FALSE;
 8  end
 9  4'b0100 : my_signal2 = FALSE;
10  default : my_signal1 = TRUE;
11endcase

Correct:

 1case (my_bus[3:0])
 2  4'b0000: begin
 3    my_signal1 = TRUE;
 4    end
 5  4'b0001: begin
 6    my_signal1 = FALSE;
 7    end
 8  4'b0010: begin
 9    my_signal1 = TRUE;
10    my_signal2 = FALSE;
11    end
12  4'b0100: begin
13    my_signal2 = FALSE;
14    end
15  default: begin
16    my_signal1 = TRUE;
17    end
18endcase

A7

Alignment should be used in declarations, assignments, multi-line statements, and end of line comments. The code must be written in a tabular format.

Incorrect:

1reg[3:0] my_signal1; // description
2reg[31:0] my_decoded_signal1; // description
3reg[4:0] my_signal2, my_signal3; // description
4wire[2:0] my_select; // description

Correct:

1reg  [ 3:0]  my_signal1;         // description
2reg  [31:0]  my_decoded_signal1; // description
3reg  [ 4:0]  my_signal2;         // description
4reg          my_signal3;         // description
5
6wire [ 2:0]  my_select;          // description

A8

Parentheses must be used around all boolean statements and in complex equations, in order to force the order of operations and avoid confusion. Complex boolean expressions should be expressed as multi-line aligned statements.

Incorrect:

1if ((my_signal1 && your_signal1) || (my_signal2 && your_signal2) || (my_signal3 && your_signal3)) begin
2  my_signal1 = TRUE;
3  my_delayed_signal1 = !your_signal;
4end

Correct:

1if ((my_signal1 && your_signal1) ||
2    (my_signal2 && your_signal2) ||
3    (my_signal3 && your_signal3)) begin
4  my_signal1 = TRUE;
5  my_delayed_signal1 = !your_signal;
6end

A9

A line must not contain more than one statement. Do not concatenate multiple statements on the same line.

Incorrect:

upper_en = (p5type && xadr1[0]); lower_en = (p5type && !xadr1[0]);

Correct:

upper_en = (p5type && xadr1[0]);
lower_en = (p5type && !xadr1[0]);

A10

In module instances:

A10.1

All parameters and ports, must be written on a separate line, even if there are few of them or their names are short.

Incorrect:

my_module #(.PARAMETER1 (PARAMETER1)) i_my_module (.clk (clk));

Correct:

1my_module #(
2  .PARAMETER1 (PARAMETER1)
3) i_my_module (
4  .clk (clk));

A10.2

When instantiating a module, the label of the module instance must be on a separate line, with the closing parenthesis of the parameters list (if that’s the case) and the opening parenthesis of the ports list. The closing parenthesis of the ports list must be right next to the last parenthesis of the last port.

1my_module #(
2  .PARAMETER1 (PARAMETER1),
3  .PARAMETER2 (PARAMETER2)
4) i_my_module (
5  .clk (clk),
6  .rst (rst),
7  .data_in (data_in),
8  .en (en),
9  .response_out (response_out));

A10.3

Commented parts of code must not be added to the main branch (i.e if, case, module instances, etc).

A11

In module declarations:

A11.1

Verilog modules must use Verilog-2001 style parameter declarations. This increases legibility and consistency.

 1module my_module #(
 2  parameter PARAMETER1 = 0
 3) (
 4  input         clk,
 5  input         rst,
 6  input  [7:0]  data_0,
 7  input  [7:0]  data_1,
 8  input         enable,
 9  input         valid,
10
11  // interface 1
12  input         interf1_clk,
13  inout         interf1_some_signal,
14  output [15:0] interf1_data_i,
15  output [15:0] interf1_data_q,
16
17  // interface 2
18  input         interf2_some_signal,
19  output        interf2_data_out
20);

A11.2

Comments are allowed inside a module declaration only for separating the interfaces by specifying the name and giving supplementary explanations.

A11.3

When declaring a module, the closing parenthesis of the parameters list must be on the same line with the last parameter and with the opening parenthesis of the ports list (as shown in the correct examples).

A11.4

After endmodule there must be only one newline, and nothing else after.

A12

Ports must be indicated individually; that is, one port per line must be declared, using the direction indication and data type with each port.

A13

Signals and variables must be declared individually; that is, one signal/variable per line must be declared.

A14

All ports and signals must be grouped by interface. Group ports declaration by direction starting with input, inout and output ports.

A15

The clock and reset ports must be declared first.

A16

Verilog wires and registers declarations must be grouped in separate sections. Firstly register types and then wire types.

A17

The source files should have the format shown in Annex 1 for Verilog code and Annex 2 for VHDL code.

A18

Local parameters must be declared first, before declaring wires or registers.

 1localparam   LOCAL_PARAM1;
 2localparam   NEXT_LOCAL_PARAM;
 3localparam   LOCAL_PARAM2;
 4
 5reg  [ 3:0]  my_signal1;
 6reg  [ 4:0]  my_signal2;
 7reg          my_signal3;
 8
 9wire [ 2:0]  my_wire1;
10wire         my_wire2;

B. Naming Conventions

B1

All the names in the source code must be written in English.

B2

Names must start with a letter, be composed of alphanumeric characters or underscores [A-Z, a-z, 0-9,_].

B3

All modules, signal and register names must be lower case, delimited by underscores _.

1module my_module (
2  input           ena_fft,
3  input           ena_mdi,
4  input           fft_in,
5  output          mdi_out,
6  output [15:0]   my_signal1
7);

B4

A file must contain a single module. File name must be the same as the module name. For sub-modules the name must be composed in the following way:

<top_module_name>_<sub_module_description>.

B5

All parameter names must be upper case with underscore delimiters.

B6

Signals names should be composed in the following way:

[interface|clock domain]_<signal_name>[_ns][_l][_p][_n][_m1][_m2][_s]

The suffix component may be used as described below and, in the case of multiple suffixes being used in the same signal name, must only be used in the order specified in the signal name descriptions above.

*_ns - State machine next state.

*_l - Latch output. Optional for signals leaving top-level module or sub-module, required for signals internal to a module

*_p - Positive side of differential signal.

*_n - Negative side of differential signal. - Active low signal. Can also be used for negative side of differential signal.

*_m1/\_m2 - Used to describe registers synchronizers (e.g. up_ack_m1, up_ack_m2)

*_s - Used to qualify wires/signals (e.g. up_ack_s)

This rule is useful for complex modules where it is possible to incorrectly use a signal if its name does not contain a suffix to specify its purpose. Generally this rule can lead to an unnecessary naming complexity and thus can be overlooked unless it is absolutely necessary.

B7

Ports names should be composed in the following way:

<interface_name>_<port_name>[_clk][_rst][_p][_n]

*_clk - Clock signal. Exception: Signals whose names obviously indicate clocks (e.g. system_clock or clk32m), or when specifying a clock with a certain frequency (in this case clk should be used as a prefix: e.g. clk_625mhz)

*_rst / \_rstn - Reset signal (e.g. module_rst). Exception: Signals whose names obviously indicate resets.

*_p - Positive side of differential signal.

*_n - Active low signal. Can also be used for negative side of differential signal.

B8

Global text macros specified by the `define directive must be preceded with the top-level module name, as in:

<top_level_module_name>_<text macro name>

B9

Consistent usage in the spelling and naming style of nets and variables must be used throughout the design.

B10

Abbreviations used in a module must be documented and uncommon abbreviations should be avoided.

B11

Reset and clock names must remain the same across hierarchy.

C. Comments

C1

Comments must be used to describe the functionality of the HDL code. Liberal use of comments is strongly encouraged. Adding obvious comments is discouraged. Basically, extensive comments that proceed blocks of code, coupled with sparse back references, guide the reader through the code.

C2

Each functional section of the code should be preceded by comments describing the code’s intent and function.

C3

Unusual or non-obvious implementations must be explained and their limitations documented with a comment.

C4

Each port declaration should have a descriptive comment, only on the preceding line.

C5

Other declarations, such as regs, wires, local parameters, should have a descriptive comment. Either on the same line (discouraged), or on the preceding line. This rule is optional for auto-generated code.

C6

All synthesis-specific directives must be documented where used, identifying the reason they are used, the tool and the directive used.

C7

The comments inserted in the code must comply with the format shown in Annex 1 for Verilog code and Annex 2 for VHDL code.

D. General

D1

A file must contain a single module.

D2

A file must contain either: digital-only Verilog code (files with .v extension); analog-only Verilog code (files with .va or .vams extension); or mixed-signal Verilog code (files with .vams extension).

D3

Symbolic constants (local parameter) should be used for register field values rather than fixed numerical constants. The fields may be one or more bits or the entire register.

D4

Port connection width must match. In module instantiations, nets connected to ports must have the same width as the respective port declaration.

D5

The ranges in both the vector port declaration and the net/variable declaration must be equal.

D6

Operands sizes must match. No expression may have its size implicitly extended or reduced. In a case statement, all the case item expressions and the case expression must have the same size.

D7

Combinational logic must be specified completely (i.e., a value must be assigned to the logic outputs for all input combinations). In a construct derived from either a case or an if statement, the outputs may be assigned default values before the case or if statement, and then the logic is completely specified.

D8

The sensitivity list of Verilog always and VHDL process constructs must be completely specified.

D9

Modules must be instantiated with all I/O: port names and signal connections must be listed on all module instantiations. Do not leave any input ports open (even if they are unused), always tie them to 0 or 1. Leave unused outputs open but do list them.

D10

A `timescale directive that is best for simulation should be used in Verilog modules.

D11

Compile warnings must be treated as potential errors and should always try to be resolved. In case a warning is not resolved its cause and effects must be fully understood.

D12

Critical warnings must be treated and fixed.

D13

Each file must contain a license header, and when changes are made to a file, when making a PR, the year should be updated to the current year.

3. Annexes

Annex 1 Verilog file format

 1// ***************************************************************************
 2// ***************************************************************************
 3// Copyright (C) year-year Analog Devices, Inc. All rights reserved.
 4//
 5// In this HDL repository, there are many different and unique modules, consisting
 6// of various HDL (Verilog or VHDL) components. The individual modules are
 7// developed independently, and may be accompanied by separate and unique license
 8// terms.
 9//
10// The user should read each of these license terms, and understand the
11// freedoms and responsabilities that he or she has by using this source/core.
12//
13// This core is distributed in the hope that it will be useful, but WITHOUT ANY
14// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15// A PARTICULAR PURPOSE.
16//
17// Redistribution and use of source or resulting binaries, with or without modification
18// of this file, are permitted under one of the following two license terms:
19//
20//   1. The GNU General Public License version 2 as published by the
21//      Free Software Foundation, which can be found in the top level directory
22//      of this repository (LICENSE_GPL2), and also online at:
23//      <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
24//
25// OR
26//
27//   2. An ADI specific BSD license, which can be found in the top level directory
28//      of this repository (LICENSE_ADIBSD), and also on-line at:
29//      https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD
30//      This will allow to generate bit files and not release the source code,
31//      as long as it attaches to an ADI device.
32//
33// ***************************************************************************
34// ***************************************************************************
35
36`timescale 1ns/100ps
37
38module prescaler #(
39  // range = 1-16
40  parameter FIRST_PARAMETER = 8,
41  // range = N/A
42  parameter SECOND_PARAMETER = 12
43) (
44  input           core_32m_clk,         // 32 MHz clock
45  input           system_clk,           // system clock
46  input           scan_mode_test,       // scan mode clock
47  input           reset_n,              // active low hard reset, synch w/
48                                        // system_clk
49  output  reg     div16_clk,            // input clock divided by 16
50  output  reg     div16_clk_n           // input clock divided by 16 and inverted
51);
52  // local parameters
53
54  // registers declarations
55
56  reg     [3:0]   count;          // 4-bit counter to make clock divider
57  reg     [3:0]   count1;         // 4-bit counter to make clock divider
58
59  // wires declarations
60
61  wire    [3:0]   count1_ns;      // clock divider next state input
62
63  // functions definitions
64
65  // this block updates the internal counter
66  always @(posedge core_32m_clk or negedge reset_n) begin
67    if (!reset_n) begin
68      count <= 4'b0000;
69    end else begin
70      // update counter
71      count <= count + 4'b0001;
72    end
73  end
74
75  // this block updates the output clock signals
76  always @(scan_mode_test or system_clk or count) begin
77    if (!scan_mode_test) begin
78      // normal operation clock assign
79      div16_clk = count[3];
80      div16_clk_n = ~count[3];
81    end else begin
82      // scan mode clock assign
83      div16_clk = system_clk;
84      div16_clk_n = system_clk;
85    end
86  end
87
88  // Modules Instantiations
89
90endmodule

Annex 2 VHDL file format

 1-- ***************************************************************************
 2-- ***************************************************************************
 3-- Copyright (C) year-year Analog Devices, Inc. All rights reserved.
 4--
 5-- In this HDL repository, there are many different and unique modules, consisting
 6-- of various HDL (Verilog or VHDL) components. The individual modules are
 7-- developed independently, and may be accompanied by separate and unique license
 8-- terms.
 9--
10-- The user should read each of these license terms, and understand the
11-- freedoms and responsabilities that he or she has by using this source/core.
12--
13-- This core is distributed in the hope that it will be useful, but WITHOUT ANY
14-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15-- A PARTICULAR PURPOSE.
16--
17-- Redistribution and use of source or resulting binaries, with or without modification
18-- of this file, are permitted under one of the following two license terms:
19--
20--   1. The GNU General Public License version 2 as published by the
21--      Free Software Foundation, which can be found in the top level directory
22--      of this repository (LICENSE_GPL2), and also online at:
23--      <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
24--
25-- OR
26--
27--   2. An ADI specific BSD license, which can be found in the top level directory
28--      of this repository (LICENSE_ADIBSD), and also on-line at:
29--      https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD
30--      This will allow to generate bit files and not release the source code,
31--      as long as it attaches to an ADI device.
32--
33-- ***************************************************************************
34-- ***************************************************************************
35
36entity prescaler is
37  Port (
38    core_32m_clk      : in  std_logic,    -- 32 MHz clock
39    system_clk        : in  std_logic,    -- system clock
40    scan_mode_test    : in  std_logic,    -- scan mode clock
41    reset_n           : in  std_logic,    -- active low hard reset, synch
42    -- w/ system_clock
43    div16_clk         : out std_logic,    -- input clock divided by 16
44    div16_clk_n       : out std_logic     -- input clock divided by 16
45     -- and inverted
46  );
47end prescaler;
48
49architecture Behavioral of  prescaler is
50
51-- Components Declarations
52
53-- Local Types Declarations
54
55--  Constants Declarations
56
57-- Signals Declarations
58  signal count        : std_logic_vector(3 downto 0); -- 4-bit counter to
59  -- make clock divider
60  signal count_ns     : std_logic_vector(3 downto 0); -- clock divider next
61  -- state input
62
63-- Module Implementation
64begin
65
66  -- This process updates the internal counter
67  process(core_32m_clk)
68  begin
69    if (rising_edge(core_32m_clk)) then
70      if (reset_n = '0') then
71        -- reset counter
72        count <= "0000";
73      else
74        -- update counter
75        count <= count + "0001";
76      end if;
77    end if;
78  end process;
79
80  -- This process updates the output clock signals
81  process(scan_mode_test, system_clk, count)
82  begin
83    if (scan_mode_test = '0') then
84      -- normal operation clock assign
85      div16_clk <= count(3);
86      div16_clk_n <= not count(3);
87    else
88      -- scan mode clock assign
89      div16_clk <= system_clk;
90      div16_clk_n <= system_clk;
91    end if;
92  end process;
93
94end Behavioral;

4. References

[1] Philippe Garrault, Brian Philofsky, “HDL Coding Practices to Accelerate Design Performance”, Xilinx, 2006

[2] Peter Chambers, “The Ten Commandments of Excellent Design”, VLSI Technology, 1997

[3] “Verilog Coding Techniques, v3.2”, Freescale Semiconductor, 2005

[4] Jane Smith, “Verilog Coding Guidelines, Rev. B”, Cisco Systems 2000