Search code examples
functionvhdl

vhdl function package test


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.


Solution

  • 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.