I've recently begun to use functions in VHDL and I'm trying to call a package of functions I created in one of my VHDL entities.
First, here's the code of the entity that calls the functions to affect a 3 bits bus entry.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.Func_Pack.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Math_Function is
Port ( clk : in STD_LOGIC;
Game_Mode : in STD_LOGIC;
Random_Number : in STD_LOGIC_VECTOR (2 downto 0);
Modified_Number : out STD_LOGIC_VECTOR (4 downto 0));
end Math_Function;
architecture Behavioral of Math_Function is
BEGIN
Out_Circuit : PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF Game_Mode = '1' THEN
IF rand = ("001" or "010") THEN
Modified_Number <= function1;
ELSIF rand = ("011" or "100") THEN
Modified_Number <= function2;
ELSIF rand = ("101" or "110") THEN
Modified_Number <= function3;
ELSE
Modified_Number <= Random_Number;
END IF;
ELSE
Modified_Number <= Random_Number;
END IF;
END IF;
END PROCESS Out_Circuit;
end Behavioral;
And the code of the function package that is supposed to modify the entry bus called Random_Number
with some simple arithmetic operations.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
package Func_Pack is
function rand(Random_Number : std_logic_vector(2 downto 0)) return std_logic_vector;
function function1(Random_Number : std_logic_vector(2 downto 0)) return std_logic_vector;
function function2(Random_Number : std_logic_vector(2 downto 0)) return std_logic_vector;
function function3(Random_Number : std_logic_vector(2 downto 0)) return
std_logic_vector;
end package;
package body Func_Pack is
function rand(Random_Number : std_logic_vector(2 downto 0)) return std_logic_vector is
variable number : integer range 0 to 9 ;
variable out_number : std_logic_vector(3 downto 0) ;
begin
number := 0;
number := to_integer(unsigned(Random_Number)) ;
out_number := std_logic_vector(to_unsigned(number / 2, 4)) ;
return out_number ;
end rand;
function function1(Random_Number : std_logic_vector(2 downto 0))
return
std_logic_vector is
variable number : integer range 0 to 9 ;
variable out_number : std_logic_vector(3 downto 0) ;
begin
number := 0;
number := to_integer(unsigned(Random_Number)) ;
out_number := std_logic_vector(to_unsigned(number mod 2 + 6, 4)) ;
return out_number ;
end function1;
function function2(Random_Number : std_logic_vector(2 downto 0))
return std_logic_vector is
variable number : integer range 0 to 9 ;
variable out_number : std_logic_vector(3 downto 0) ;
begin
number := 0;
number := to_integer(unsigned(Random_Number)) ;
out_number := std_logic_vector(to_unsigned(number + 3, 4)) ;
return out_number ;
end function2;
function function3(Random_Number : std_logic_vector(2 downto 0))
return
std_logic_vector is
variable number : integer range 0 to 9 ;
variable out_number : std_logic_vector(3 downto 0) ;
begin
number := 0;
number := to_integer(unsigned(Random_Number)) ;
out_number := std_logic_vector(to_unsigned(number - number mod 2 + 2, 4));
return out_number ;
end function3;
end package body;
As I previously said, I'm new to packages and functions and there might still be syntax errors or mistakes in my code.
Lack of explicit question notwithstanding, I assume you're having problems with:
IF rand = ("001" or "010") THEN
Modified_Number <= function1;
ELSIF rand = ("011" or "100") THEN
Modified_Number <= function2;
ELSIF rand = ("101" or "110") THEN
Modified_Number <= function3;
ELSE
Modified_Number <= Random_Number;
END IF;
You've written function1
, for instance, so that it takes an argument, but you're not providing one. The function prototype is:
function function1(Random_Number : std_logic_vector(2 downto 0)) return std_logic_vector;
You need to provide the required argument when you call the function, like:
IF rand = ("001" or "010") THEN
Modified_Number <= function1(rand);
Also be careful, as you appear to have several potential off-by-one errors - for one, your output Modified_Number
is a 5-bit vector, but you assign the result of your functions, which return out_number
, which is only 4 bits.
(edit)
Above, I missed the fact that rand
was itself a function that takes an argument. Your if statement should then be if rand(Random_Number) = ...
(see Brian's answer for another problem with the rest of those lines as you had them written).
Just make sure you understand the scope of the names you're using in your function. You wrote each function to take an argument Random_Number
. This is not the same as your Random_Number
input port to your Math_Function
entity - they happen to have the same name, but they're in different scopes, and the function does not automatically use the input port as its argument. From the perspective of the function, the name of the argument (the LRM term is "formal parameter") is a name local to that function only. When you declare a port, also named Random_Number
, you need to explicitly pass it to each function call.
Note that you could also just declare your functions in your architecture body, in which case signals outside the function itself would be in scope, provided you declared it as impure (and you wouldn't need the parameter at all). As long as you have your functions in a separate package as you posted here, though, you will need to pass them arguments explicitly. And I'm not sure you want to get into using impure functions, anyway.