VHDL Coding Rules: Tampere University of Technology Department of Computer Systems Version 4.4 - Jan 2009
VHDL Coding Rules: Tampere University of Technology Department of Computer Systems Version 4.4 - Jan 2009
Extra slides
z Few additions to rules and guidelines
Bad example:
A_37894 :process(xR,CK ,datai , DATAO )
BEGIN
if(XR =’1’ )THEN DATAO<= "1010";end if;
if(CK’event) THEN if CK = ‘1’ THEN
for ARGH in 0
to 3 Loop DATAO(ARGH) <=datai(ARGH);
end Loop;end if;
end process;
#3/40 Tampere University of Technology (TUT) - Jan 2009
About Coding Rules
This guide has
1. Rules
2. Guidelines
Use
Use only
only port
port modes IN and
modes IN and OUT.
OUT.
#10/40
Use
Use only only types STD_LOGIC and
types STD_LOGIC
Tampere University of Technology (TUT) - Jan 2009
and STD_LOGIC_VECTOR.
STD_LOGIC_VECTOR.
File contents and naming
One VHDL file should contain one entity
and one architecture, file named as
entityname.vhd
Package name should be
packagename_pkg.vhd
Test bench name should be
tb_entityname.vhd
A
A VHDL
VHDL file
file and
and the
the entity
entity it
it contains
contains have
have the
the same
same name.
name.
Every
Every entity
entity needs
needs aa testbench.
testbench.
#12/40 Tampere University of Technology (TUT) - Jan 2009
Sequential/synchronous process
Sensitivity list of a synchronous process has
always exactly two signals
z Clock, rising edge used, named clk
z Asynchronous reset, active low, named rst_n
Signals that are assigned inside sync process, will
become D-flip flops at synthesis
Never give initial value to signal at declarative part
z It is not supported by synthesis (but causes only a
warning)
SIGNAL main_state_r : state_type := "11110000";
Î Assign values for control registers during reset
z (Xilinx FPGAs may be exceptions to this rule)
Synchronous
Synchronous process
process is
is sensitive
sensitive only
only to
to reset
reset and
and clock.
clock.
#13/40 Tampere University of Technology (TUT) - Jan 2009
Sequential/synchronous process (2)
Correct way of defining synchronous process:
cmd_register : PROCESS (rst_n, clk)
BEGIN
IF (rst_n = '0') THEN
cmd_r <= (OTHERS => '0');
ELSIF (clk’EVENT AND clk = '1') THEN
cmd_r <= …;
END IF;
END PROCESS cmd_register;
Clock
Clock event
event is
is always
always to
to the
the rising
rising edge.
edge.
Assign
Assign values
values to
to control
control registers
registers during
during reset.
reset.
Include
Include all all input
input signals
signals of
of combinatorial
combinatorial process
process in
in the
the
sensitivity
sensitivity list.
list.
#15/40 Tampere University of Technology (TUT) - Jan 2009
Combinatorial/asynch. process (2)
An example of an asynchronous process:
decode : PROCESS (cmd_r, bit_in, enable_in)
BEGIN
IF (cmd_r = match_bits_c) THEN
match_0 <= '1';
IF (bit_in(1) = ‘1’ and bit_in(0) = ‘0’) THEN
match_both <= enable_in;
ELSE
match_both <= '0';
END IF;
ELSE -- else branch needed to avoid latches
match_0 <= '0';
match_both <= '0';
END IF;
END PROCESS decode;
Same signal cannot be on both sides of assignment in
combinatorial process
z That would create combinatorial loop, i.e. malfunction
Combinatorial
Combinatorial process process necessitates
necessitates complete
complete if-clauses.
if-clauses. Every
Every
signal
signal is is assigned
assigned in
in every
every if-branch.
if-branch.
#16/40 Tampere University of Technology (TUT) - Jan 2009
These naming conventions are must
General register output signalname_r
Combinatorial signal signalname
Constant constantname_c
Generic genericname_g
Variable variablename_v
Use
Use these
these naming
naming conventions.
conventions.
#17/40 Tampere University of Technology (TUT) - Jan 2009
Signal types
Direction of bits in STD_LOGIC_VECTOR
is always DOWNTO
Size of the vector should be
parameterized
Usually the least significant bit is
numbered as zero (not one!):
SIGNAL data_r : STD_LOGIC_VECTOR(datawidth_g-1
DOWNTO 0);
Direction
Direction of
of bits
bits in
in aa bus
bus is
is always
always DOWNTO.
DOWNTO.
#18/40 Tampere University of Technology (TUT) - Jan 2009
Named signal mapping in instantiations
Always use named signal mapping, never
ordered mapping
i_datamux : datamux
PORT MAP (
sel_in => sel_ctrl_datamux,
data_in => data_ctrl_datamux,
data_out => data_datamux_alu
);
Always
Always use
use named
named signal
signal mapping
mapping in
in component
component instantiations,
instantiations,
never
never ordered
ordered mapping.
mapping.
Use
Use constants
constants or
or generics
generics instead
instead of
of magic
magic numbers.
numbers.
#20/40 Tampere University of Technology (TUT) - Jan 2009
Use assertions
Easier to find error location
Checking always on, not just in testbench
Assertions are not regarded by synthesis
tools Î no extra logic
assert (we_in and re_in)=0
report ”Two enable signals must not active
at the same time”
severity warning;
If condition is not true during simulation,
z the report text, time stamp, component where
it happened will be printed
Ensure that your initial assumptions hold
z e.g. data_width is multiple of 8 (bits)
Use
Use assertions.
assertions.
#21/40 Tampere University of Technology (TUT) - Jan 2009
Comment thoroughly
Comment the intended function
z Especially the purpose of signals
z Not the VHDL syntax or semantics
z Think of yourself reading the code after a
decade.
A comment is indented like regular code
z A comment is placed with the part of code to
be commented.
Be sure to update the comments if the
code changes.
z Erroneous comment is more harmful than not
having a comment at all
Pay
Pay attention
attention to
to comments
comments
#22/40 Tampere University of Technology (TUT) - Jan 2009
Guidelines
Every
Every VHDL
VHDL file
file starts
starts with
with aa standard
standard header.
header.
#24/40 Tampere University of Technology (TUT) - Jan 2009
General code appearance
VHDL code must be indented
z Much easier to read
Indentation is fixed inside a project
z Comment lines are indented like regular code
In (X)Emacs VHDL mode, use
z Ctrl-c Ctrl-b to beautify buffer
z Ctrl-c ctrl-a Ctrl-b to align buffer
Maximum length of a line is 76 characters
z In VHDL language it is very easy to divide lines
z The commented code line should still fit to the console
window
Use blank lines to make code more readable
Use
Use indentation.
indentation. Keep
Keep lines
lines shorter
shorter than
than 76
76 characters.
characters.
#25/40 Tampere University of Technology (TUT) - Jan 2009
Naming in general
Descriptive, unambiguous names are very
important
Names are derived from English language
Use only characters
z alphabets ‘A’ .. ‘Z’,‘a' .. ‘z',
z numbers '0' .. '9' and underscore '_'.
z First letter must be an alphabet
Use enumeration for coding states in FSM
z Do not use: s0, s1, a, b, state0, ...
z Use: idle, wait_for_x, start_tx, read_mem, ...
Average length of a good name is 8 to 16
characters
Use
Use consistent
consistent and
and descriptive
descriptive names.
names.
#26/40 Tampere University of Technology (TUT) - Jan 2009
Naming the architecture
Architecture name is one of following:
behavioral
z Implies physical logic, cannot be compiled with
RTL tools
rtl
z Implies physical logic, compiled with RTL tools
structural
z Implies physical connections, but not any logic
Use
Use only
only conventional
conventional architecture
architecture names.
names.
#27/40 Tampere University of Technology (TUT) - Jan 2009
Label the processes
Label every process
z e.g. define_next_state, define_output
Makes easier to identify part of the code
implying specific logic in synthesis
Label is written two times in the code:
z Before and after the process
z e.g. define_next_state: process ...
Label
Label every
every process.
process.
#28/40 Tampere University of Technology (TUT) - Jan 2009
Clk and reset signals/inputs
Active low reset is rst_n
z Asynchronous set should not be used
z A register should never have both
asynchronous set and reset
Clock signal clk
z If there are more clocks the letters "clk"
appear in every one as a postfix
When a signal ascends through hierarchy,
its name should remain the same. This is
especially important for clock signals
Use
Use names clk and
names clk and rst_n.
rst_n.
#29/40 Tampere University of Technology (TUT) - Jan 2009
Naming intermediate signals
Signals from instance a to b are named:
signalname_a_b
z Needed in structural architectures
They NEVER have "in" or "out" specifiers
z output of a is connected to input of b
Î cannot decide which postfix to choose
Abbreviated component names are handy when
names are longer than a and b
With multiple targets use signalname_from_a
component
component aa component
component bb
data_a_b
data_out data_in
Intermediate
Intermediate signal’s
signal’s name
name includes
includes src
src and
and and
and dst.
dst.
#30/40 Tampere University of Technology (TUT) - Jan 2009
Naming the instantances
Component instance name is formed from the
component name
Attach prefix “i_” and identifier as a postfix:
i_componentname_id : componentname
PORT MAP…
e.g. i_fifo_out : entity work.fifo
PORT MAP…
This helps to track down the actual entity
z From simulation results
z From synthesis results
Exceptions possible with long entity names
z In this case, it might be best to shorten the entity
name
Instance
Instance is
is named
named after
after the
the component
component entity.
entity.
#31/40 Tampere University of Technology (TUT) - Jan 2009
Using for-generate
FOR GENERATE statement is used for repetitive
instantiations of the same component
Label generate statement
Example
g_datamux : FOR i IN 0 TO n_mux_c-1 GENERATE
i_datamux : datamux
PORT MAP (
sel_in => sel_in (i),
data_in => data_r (i),
data_out => data_mux_alu(i)
);
END GENERATE g_datamux;
FOR GENERATE creates identifiers (running numbers)
automatically to all instances
Use
Use FOR GENERATE for
FOR GENERATE for repetitive
repetitive instances
instances
#32/40 Tampere University of Technology (TUT) - Jan 2009
Recommended naming
Between components signalname_a_b
To multiple components signalname_from_a
Prefer
Prefer these
these naming
naming conventions
conventions
#33/40 Tampere University of Technology (TUT) - Jan 2009
Prefer generics
Basically, generic parameter is a fundamental idea in VHDL
that enables design reuse, use it.
Avoid constants (in packages or architecture)
z if data_width_c is defined is package, it is impossible to
have instances with different data_width_c values
Î E.g. This limits all adders in the system to 10 bits
z With generics, it is possible to have different adders
The component size should be changed with generics NOT
by modifying the code.
When the VHDL code is reused, there should be no need to read
the code except the entity definition
If there are illegal combinations of generic values, use
assertions to make sure that given generics are valid
However, having many generic parameters, complicates
verification
Prefer
Prefer generics
generics to
to package
package constants
constants
#34/40 Tampere University of Technology (TUT) - Jan 2009
Avoid bit vector literals
Avoid bit vector literals
Use conversion functions
Bit vectors must be edited by hand if
vector width changes
status_r <= "11110000";
Prefer
Prefer conversion
conversion over
over bit
bit vector
vector literals.
literals.
#35/40 Tampere University of Technology (TUT) - Jan 2009
Prefer arrays and loops
Use arrays and loops instead of different
names
z Array size can be generic
z Names (e.g "signal_0, signal_1, ...")
have to be modified by hand
z Naturally, loop limits must be known at
compile/synthesis time
priority_encoder : PROCESS (input)
BEGIN
first <= data_width_c-1;
FOR i IN data_width_c-2 DOWNTO 0 LOOP
IF (input(i) = ’1’) THEN
first <= i;
END IF;
END LOOP;
END PROCESS priority_encoder;
Prefer
Prefer arrays arrays over over multiple
multiple separate
separate signals
signals and
and loops
loops for
for
repetitive
repetitive operations.
operations.
#36/40 Tampere University of Technology (TUT) - Jan 2009
Avoid variables inside processes
Variables in processes usually make
VHDL difficult to understand
z Valid inside procedures fo functions
Use variables only for storing intermediate
values
Only used as “short-hand notation”
tmp_v := addr_r (3)(2);
data_r (tmp_v) <= a_in (tmp_v) + b_in(tmp_v);
Avoid
Avoid variables
variables in
in synthesizable
synthesizable code.
code.
#37/40 Tampere University of Technology (TUT) - Jan 2009
Contributors
Version 4, Dec. 2007: E. Salminen, A. Rasmus,
and A. Kulmala
z Earlier versions included also: M. Alho, K. Kuusilinna,
V. Lahtinen, H. Lampinen, J. Tomberg
See also VHDL FAQ:
z http://www.vhdl.org/comp.lang.vhdl/FAQ1.html
Further reading:
z M. Keating, P. Bricaud, Reuse methodology
manual: for system-on-a-chip designs, Kluwer
Academic Publishers Norwell, MA, USA, 1998 /
2002, ISBN:0-7923-8175-0
z Declaration of component B
z Signals the instantiations of component B drive
z Declaration of component C
z Signals the instantiations of component C drive
z …
z All other signals (if any)
Order of the component instantiations should be
the same than the order of the component
declarations
#46/40 Tampere University of Technology (TUT) - Jan 2009
Code appearance: Aligning I
One statement per line
One port declaration per line, own line also for end
parenthesis
Align the colons and port types in the entity port:
ENTITY transmogrifier IS
PORT (
rst_n : IN STD_LOGIC;
clk : IN STD_LOGIC;
we_in : IN STD_LOGIC;
cmd_0_in : IN STD_LOGIC_VECTOR(3-1 DOWNTO 0);
data_in : IN STD_LOGIC_VECTOR(5-1 DOWNTO 0);
valid_out : OUT STD_LOGIC;
result_out : OUT STD_LOGIC_VECTOR(6-1 DOWNTO 0)
);
END transmogrifier;
E.g.
data_output <= ((('0' & a) + ('0' & b)) AND c);
Differences of packages
Source: http://dz.ee.ethz.ch/support/ic/vhdl/vhdlsources.en.html
(visited 02.11.2005)
#54/40 19.01.2005
Tampere University of Technology (TUT) - Jan 2009