VHDL naming convention

Overview

The preferred coding style within the MSK firmware group is described below. Having a unified style should make it easier to discover coding errors during code review (ideally preventing bugs before they show up), and helps at long-term maintenance of the code base.

There is a tool to check VHDL files for compliance with these specific rules:

It is recommended to use it when writing new code.

Code Formating

  • Code style: lowercase_separated_by_underscores

  • Capital letters for CONSTANTS, GENERICS and enumeration states (ST_IDLE, ST_RUN)

No TABs - only spaces (in editors set TAB by 2 spaces).

Indention width 2 spaces

Keep long line marker location at 80, try to fit but never exceed 120 characters.

Long lines should be broken with indentation of 2 spaces

Names in VHDL code:

The naming scheme is <prefix><object_name><suffix/es>

Prefix

pi_

in port

po_

out port

pio_

inout port

G_

generic

l_

local signal (within a block or generate)

ll_, lll_, …​

local signal in a nested block or generate

v_

variable

par_

parameter

idx_

index

ST_

state

C_

constant

t_

type, subtype

blk_

block

gen_

generate

f_

function

prd_

procedure

prs_

process

ins_

instance

lp_

loop

Name

Meaningful minimum 4 characters.

fixed names for signals
  • clock - for clock

  • reset - for reset

Postfixes

_clk

clock

_rst

reset

_n

active low

_en

enable

_ce

clock enable

_we

write enable

_re

read enable

_ie

input enable

_oe

output enable

_vld

valid

_rdy

ready, data ready

_trg

trigger

_str

strobe

_fsm

state machine

_cnt

counter

_ctl

control

_sts

status

_stt

state

_addr

address

_data

data

_q

register stage

_qq

register stage

Register stage; if longer then 2 use std_logic_vector

Examples:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

--==============================================================================
-- decoder entity
--==============================================================================
entity data_decoder is
  generic(
    G_DATA_WIDTH      : natural := 0
  );
  port (
    pi_clock : in  std_logic;
    pi_reset : in  std_logic;

    pi_data  : in  std_logic_vector(G_DATA_WIDTH-1 downto 0);
    pi_valid : in  std_logic;

    po_data  : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
    po_valid : out std_logic
  );
end entity data_decoder;

--==============================================================================
architecture arch of data_decoder is

  signal data_in   : std_logic_vector(G_DATA_WIDTH-1 downto 0);
  signal valid_in  : std_logic;
  signal data_out  : std_logic_vector(G_DATA_WIDTH-1 downto 0);
  signal valid_out : std_logic;

begin

  po_data  <= data_out ;
  po_valid <= valid_out;

  ------------------------------------------------------------------------------
  --! core decoder instance
  ------------------------------------------------------------------------------
  ins_decoder_core : entity work.data_decoder_core
  generic map (
    G_DATA_WIDTH => G_DATA_WIDTH
  )
  port map (
    pi_clock => pi_clock,
    pi_reset => pi_reset,

    pi_data  => data_in,
    pi_valid => valid_in,

    po_data  => data_out,
    po_valid => valid_out
  );

  ------------------------------------------------------------------------------
  --! pre-decoder data manipulation
  ------------------------------------------------------------------------------
  prs_data_predec:
  process(pi_clock)
  begin
    if rising_edge(pi_clock) then
      valid_in <= pi_valid ;

      if pi_valid = '1' then
        data_in <= std_logic_vector(unsigned(pi_data) + 10000 );
      end if;

    end if;
  end process;

end architecture arch;

AXI Naming Scheme

Types are defined in the desy.common_axi and desy.common_bsp_if libraries. Port names should follow a similar scheme, but it must be clear if the entity acts as a master or as a subordinate on that port. An m or s is inserted for this purpose.

Port Naming Syntax

p<direction>_<m/s>_axi4_<module_name>  => for AXI4 Full
p<direction>_<m/s>_axi4l_<module_name> => for AXI4 Lite
p<direction>_<m/s>_axi4s_<module_name> => for AXI4 Stream

Example:

Module which has AXI4 Master Port

po_m_axi4_daq : out t_axi4_m2s;
pi_m_axi4_daq : in  t_axi4_s2m;

po_m_axi4l_lll : out t_axi4l_m2s;
pi_m_axi4l_lll : in  t_axi4l_s2m;

po_m_axi4s_lll : out t_axi4s_m;
pi_m_axi4s_lll : in  t_axi4s_s;

Signal Naming Syntax

A VHDL signal is connected to both the master and the subordinate. It must be clear whether it contains the master-to-suboprdinate (m2s) or subordinate-to-master (s2m) signals.

axi4_<module_name1>_<module_name2>_m2s
axi4_<module_name1>_<module_name2>_s2m

Example: (2 IP-cores are connected via these two signals)

axi4_ip1_ip2_m2s : t_axi4_m2s;
axi4_ip1_ip2_s2m : t_axi4_s2m;