VHDL Functions
Quick Syntax
function translate_xy(x : in integer;
y : in integer) return integer is
variable output : integer := 0;
begin
output := x + y + 25;
return output;
end function;
Purpose
Think of a function in VHDL as something that you give multiple inputs and it returns an output based on those inputs. If you need multiple outputs, check out procedures.
Functions are a nifty way to have common source code in one place that can be called from any other source code. If you find yourself doing the same kind of logic repeatedly throughout a design, then it's a good idea to make a function out of it.
What the pros do is usually have some sort of common_pack.vhd file or similar where they use it as a package that can be called by any other VHDL source file that needs to use any of the functions in that package. It's a great way to be able to bring in existing capability into new designs that can be used throughout the source files.
You can get as fancy as you want and break groups of functions into different package files that can be used with different sets of other source code. For example memory related functions with memory source code. However, that gets complicated and may be prone to errors for people that don't know where which functions are in which files. The common file approach usually works better.
Examples
Here's an example package file where you can have your functions:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package common_pack is
function translate_xy1 (x : in integer;
y : in integer) return integer;
function translate_xy2 (x : in integer;
y : in integer) return integer;
end package common_pack;
package body common_pack is
function translate_xy1 (x : in integer;
y : in integer) return integer is
variable output : integer := 0;
begin
output := x + y + 25;
return output;
end function;
function translate_xy2 (x : in integer;
y : in integer) return integer is
variable output : integer := 0;
begin
output := x + y - 25;
return output;
end function;
end package body common_pack;
And here's how you call it in the source file that you need to use the functions, assuming you compiled the package in library "work":
library work;
use work.common_pack.all;
And here's how you use the function in your code:
constant TRANSLATE_TO_Z : integer := translate_xy1(3,4);
Best Practices
1. If you do similar things often, capture it in a function.
2. For functions that are commonly used across multiple designs, put them in a common package file that can be used again.
3. Make sure your functions account for all possibilities of its inputs, and make the output initialized to a known value just in case.