Advanced VHDL Concepts
Attributes, functions, packages, procedures, subtypes and pipelining — taking VHDL to the next level.
Attributes
Attributes let you retrieve information about VHDL objects. For example, where Python would use max(array), VHDL uses array'HIGH.
There are several families of attributes depending on the object type:
-- Attributes for ARRAY or scalar types
X'HIGH -- largest element / upper bound
X'LOW -- smallest element / lower bound
X'LEFT -- leftmost element / left bound
X'RIGHT -- rightmost element / right bound
-- Attributes for objects declared in an ARRAY or SUBTYPE
x'RANGE -- range of x
x'REVERSE_RANGE -- range of x in reverse order
x'LENGTH -- x'HIGH - x'LOW + 1 (integer)
-- Attributes for SIGNAL
x'EVENT -- TRUE if x changes state
x'ACTIVE -- TRUE if x changed during the last delta
x'LAST_EVENT -- time elapsed since last change of x
x'LAST_VALUE -- previous value of x
-- These attributes create a new SIGNAL
x'DELAYED(t) -- signal of same type as x, delayed by t
x'STABLE(t) -- TRUE if x has not changed for time t
x'QUIET(t) -- TRUE if x has not changed for time t
x'TRANSACTION -- toggles whenever x changes stateCase Sensitivity
VHDL is case-insensitive. The compiler does not distinguish between uppercase and lowercase. Signal, SIGNAL and signal are all equivalent.
Functions
A function is a block of instructions that returns a value. It must contain at least one return statement and may only contain sequential instructions — no process, no wait, no signal assignments.
-- Declaration (in architecture or package):
FUNCTION function_name
{(parameter_list)}
RETURN type_name;
-- Function body:
function function_name
{(parameter_list)}
return type_name is
begin
[statements]
end [function_name];Example — MAX function:
function MAX (
A : in integer;
B : in integer
) return integer is
begin
if (A > B) then
return A;
else
return B;
end if;
end MAX;Packages
A package groups shared declarations: types, constants, components, functions, procedures. Think of it as a reusable library.
-- Package declaration:
package package_name is
[type_declaration]
[subtype_declaration]
[constant_declaration]
[component_declaration]
end [package_name];
-- Package body (implementation):
package body package_name is
[type_declaration]
[subtype_declaration]
[constant_declaration]
[subprogram_declaration]
end [package_name];Procedures
A procedure is similar to a function, but it does not return a value (no return). It can directly modify variables or signals in the architecture. It may contain wait statements, unless called from a process or a function.
-- Declaration:
procedure procedure_name
{(parameter_list)};
-- Body:
procedure procedure_name
{(parameter_list)}
begin
[statements]
end [procedure_name];Subtypes
A subtype is a constrained type derived from another type. It restricts the allowed range of values.
type integer is range -2147483647 to 2147483647;
subtype absolu is integer range 0 to 2147483647;Pipelining
Pipelining means splitting a complex computation into successive stages, each registered in a flip-flop. This increases the maximum clock frequency at the cost of a small latency.
Example — computing Y = A×B - C without pipelining:
process(i_clk, i_reset)
begin
if (i_reset = '1') then
o_y <= 0;
elsif rising_edge(i_clk) then
o_y <= i_a * i_b + i_c;
end if;
end process;Same computation with a 2-stage pipeline:
process(i_clk, i_reset)
begin
if (i_reset = '1') then
r_mul <= 0;
o_y <= 0;
elsif rising_edge(i_clk) then
r_mul <= i_a * i_b; -- stage 1: multiplication
o_y <= r_mul + i_c; -- stage 2: addition
end if;
end process;The non-pipelined version synthesizes one multiplier and one adder in series. The pipelined version inserts a D flip-flop between the two operations to store the intermediate result r_mul.
Advantage: shorter critical path → higher clock frequency. Drawback: 1 cycle of extra latency between input and output.
Key takeaway: when your designs grow complex, split computations into multiple process blocks or functions. Pipelining is in this spirit — cleaner and more efficient code.