VHDL Conventions

VHDL conventions are essential guidelines that improve the clarity, consistency, and quality of hardware description code. By following these best practices, developers can write code that is easier to read, maintain, and scale. 

At EmLogic, we emphasize robust architecture and solid methodologies to ensure efficient and reliable hardware design. Adopting these conventions helps us maintain high standards, streamline development processes, and enhance collaboration across projects.

General rules

lowercase / UPPERCASE

Code layout

Naming

Entity and Instance naming

Note: Direct instantiation is to be used as default. Components should be avoided unless specific reasons to use this.

Module entity
Stand-alone function

uart

FPGA top level entity

<the FPGA design name>

Submodule entity
Either functional name or use module-name as prefix


baudrate_ctrl, uart_rx

Instance
Use functional name as suffix as default.
May also prefix by i[#]_ as an alternative.
(Exception for generate)


i_uart, i3_uart, i_uart_host_if, i_fifo_addresses
i_cmd_queue

Testbenches and harness
a) TB for uart
b) TB for uart_rx
c) TB for testing RX in uart
d) TB with special purpose
e) Test harness for the same as above


a) uart_tb
b) uart_rx_tb (uart_<func inside uart>_tb
c) uart_tb_rx (uart_tb_<funct to test in full uart>)
d) uvvm_tb_demo
e) same as above but ‘th’ rather than ‘tb’

VIP variants

uart_vvc, uart_tx_vvc

Architecture naming

Functional / RTL (including hierarchical):
Multiple architectures:

rtl
rtl_<func>

Behavioural

bhv – or other functional name (not RTL)

Testbench architecture or harness

Functional name: e.g. func, corner, tx, rx_test

Special purpose
(e.g. netlist, low power, device specific)

Any meaningful name
(rtl_<func>) for RTL

Package naming

Module or entity specific

uart_pkg
uart_pif_pkg
uart_pif_priv_pkg
(Use ‘priv’ if private. Default is public)

General packages

<name>_pkg (e.g. common_methods_pkg)

VIP variants

uart_bfm_pkg
vvc_methods_pkg

FiIe naming

Default

<most primary unit in file>.vhd (see Entity name)
uart.vhd, uart_rx.vhd, uart_tb.vhd

If additional architectures

Entity: <entity-name>_ent.vhd
Arch: <entity-name>_<arch-name>.vhd
e.g. uart_ent, uart_bhv.vhd, uart_rtl_low_power.vhd

Packages

uart_pkg.vhd e.g. common_methods_pkg.vhd

Library naming

Company dedicated library

emlogic_support_comps
emlogic_space_wire
emlogic_vip_space_wire

Project dedicated library

<module/funjctionmality-name> or
[<project-name>_]<module/funjctionmality-name>

Vendor dedicated_library

<vendor-name>_name, unless already given a library name

Restrictions

Type range restrictions

Including vectors and arrays – and naming

Vector (Any kind)

Range N downto M, (M=0 or justify other)

Single dimensional array

Same as vector, so also name <element>_vector, always range N downto M. Exception for ‘string’, which is normally range 1 to N.
Other exceptions using range N to M should be named <element>_array

Multi dimenaional array

Use good explanatory names.
Dimension 2 is often range N to M, but a word-array (of SLV) would often be N downto M

Number (any kind)

Must define range

 

Type usage restrictions

std_logic_vector

Never use if object is always representing a number

unsigned

Use for ALL objects representing an unsigned number (unless natural is better)

signed

Use for ALL objects representing a signed number (unless integer is better)

Integer, natural, positive

Typically use for indexes and pointers ONLY use when really well understood. Always restrict range. Never use for primary I/O (for synthesis).
Use strictest possible type (i.e. positive if only postives if using unconstrained)

Enumerated, Boolean, Records

Use anywhere, but Never use for FPGA primary I/O (for synthesis)

Prefixes

Prefixes (and not) - For Signal, Var., Const., etc.

Normally a single char preceeding an underscore. Used to say something about the object type.

Signal

<name> (no prefix)

 

Global signal
def. in pkg

global_<name>
(May skip ‘global_’ for very well known names, like VVC signals in UVVM)

Variable
def. in process. NOT a register

v_<name>

Variable
def. in process. Intended register

vr_<name>

Variable
formal parameter in subroutine

<name>

Variable
def. inside protected type

v_<name>

Shared variable (of protected type)
Unprotected is no longer allowed

shared_<name>

Constant
normal constants

C_<NAME>

Constant 
formal param. subroutine

<name>

Constant 
defined in subroutine

C_<NAME>

Generic constant

GC_<NAME>

Enumeration literals

[<TYPE>_]<NAME> (TYPE= User type name)or S_<NAME>
(recommended for FSM, but not mandatory. Typically very useful when referring to states from outside the FSM, but less useful for plain and simple FSMs)

Alias

a_<name>

Alias
Hierarchical reference

ha_<name>

Register address constants
locally

C_ADDR_<reg-name>
e.g. C_ADDR_ERROR_FLAGS

Register address constants
lcentrally/top-level

C_ADDR_<module-name>_<reg-name>
e.g. C_ADDR_UART1_ERROR_FLAGS

Address offset

C_ADDR_OFFSET_<module-name>
e.g. C_ADDR_OFFSET_UART1

Prefixes – for other language element

Process

p_<name>

Procedure

<name>

Function

<name>(min 1 param otherwise use ‘VOID’)

Type

t_<name>

Generate

g_<name>

Loop label
optional

l_<name>

Suffixes

Suffixes

Intended purely as extra info for signals/variables/const. If multiple suffixes apply, add them in alphabetical order
(e.g. <name>_a_n) Note a number is mandatory for their given # below

Active low
avoid

_n

Asynchronous

_a

Synchronized

_s# (1..N)

Delayed
i.e. all in same clock domain

_d# (1..N)
(May also sometimes use sr for shift reg.)

pipeline stage _p#

_p# (1..N)
(May also sometimes use sr for shift reg.)

Differential pair

_dp & _dn

Toggle-signal
to indicate valid on toggle, i.e. not a boolean signal

_tgl

Abbrevations

Fixed names and abbreviations

clk
clk_<funct-name>

‘clk’ may only be used for signals going to flop or memory clock inputs. E.g. a clock just going out of the FPGA to for instance an external DAC should NOT use ‘clk’ in the name, but rather for instance ‘clock’

 

clock_<funct-name>
<funct-name>_clock

Never use this for a signal going to flop or memory clock inputs
(see clk above)

rst, arst
rst<_clk-name>, rst_30, rst_uart
<interface prefix_rst

Reset (rst: synchronous, i.e. not immediate) (arst: asynchronous reset, i.e. immediate)

See ‘Compound Functional names’ under ‘General rules’ at the beginning

Allowed abbreviations

ack

acknowledge

addr 

address

c2p, p2c

Signals from core to pif, or pif to core respectively (e.g. inside a module with records between PIF and core).

clr

clear

cmd

command

cnt

count(er) (Actual count value. cd idx)

ctrl

control(ler)

dest

destination

din, dout

data in, data out

ena

enable

err

error

idx, idx1

index (Use idx when first element 0, otherwise idx1 when first element is 1)

irq

interrupt / interrupt request

lsb, lsw

least significant bit/word (for byte use lsbyte)

msb, msw

most significant bit/word (for byte use lsbyte)

num

number (of), (do not use ‘no’)

pif

processor interface

ptr

pointer

rd, wr
rena, wena

read, write
(Either set may be used, depending on scenario)

rdata, wdata

data in, data out (same as ‘din, dout’, but used in different scenarios)

rdy, vld

ready, valid

src

source

sync, async

synchronous, asynchronous.red

tb, th, tc

Suffixes for test-bench/harness/case

tmp

temporary

tx, rx

transmit/receive (Use more explanatory name when any misunderstanding is possible. E.g use uart_1_tx, tx_moduleA2moduleB, tx_uart1_to_uart3 )