Search code examples
functionvhdlpackagefpga

Why am I getting a "No matching subprogram was found." error?


I wrote a function inside a package file, and I'm calling it inside the main vhd file. It seems to me everything is correctly in place. But the Sigasi editor says "No matching subprogram was found." at the line where I called the function.

This is the package file content:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.numeric_std.ALL;

PACKAGE pkg IS

TYPE t IS ARRAY (positive RANGE <>) OF std_logic_vector(7 DOWNTO 0);
FUNCTION char2byte (SIGNAL yazi_char: character) RETURN std_logic_vector;   

END pkg;


PACKAGE BODY pkg IS

FUNCTION char2byte (SIGNAL yazi_char: character) RETURN std_logic_vector IS
VARIABLE yazi_byte: std_logic_vector;

BEGIN
case yazi_char is

    when '0' =>        yazi_byte:=x"30";
    when '1' =>        yazi_byte:=x"31";
    when '2' =>        yazi_byte:=x"32";
    ....

    when others => 

end case;

RETURN yazi_byte;
END char2byte;

END pkg;

And this is the main file content:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use WORK.pkg.ALL;

entity rs232 is
port(

clk:in std_logic;
tx_port:out std_logic

);
end rs232;


architecture Behavioral of rs232 is
signal yazi_byte: t;
begin

yazi_byte<=char2byte("y");

process(clk)
begin
....
end process;
end Behavioral;

Where is the fault? The funny thing is, ISE is giving another error, not a "No matching subprogram was found.".

It is:

ERROR:HDLParsers:522 - "D:/UME/FPGA/ise_projeleri/RS232_TEST/pkg.vhd" Line 16. Variable yazi_byte is not constrained.
ERROR:HDLParsers:3304 - "D:/UME/FPGA/ise_projeleri/RS232_TEST/pkg.vhd" Line 16. Can not determine the "others" values in aggregate. (LRM 7.3.2)

Thanks for helping.


Solution

  • The problem is that you are confusing a std_logic_vector with t, an array of std_logic_vector.

    signal yazi_byte: t;
    begin
    yazi_byte<=char2byte("y");
    ...
    

    Now t is an unconstrained array, which allows you to declare ts of different sizes when you use the package. There are two ways to do this :

    • declare a t and initialise it in the declaration : the initialiser (function call or array aggregate) defines its size. Works for signals but especially useful for constants
    • constrain it to the size you need in the declaration.

    Thus the first example is constrained to be 4 bytes long:

    constant deadbeef : t := (X"DE", X"AD", X"BE", X"EF");
    

    And your second example is currently 1 byte long: however you still need to address that byte within it... This is actually why you get the obscure-looking error message.

    signal yazi_byte: t(0 downto 0);
    begin
    yazi_byte(0) <= char2byte("y");
    ...
    

    VHDL has operator and function overloading, so the compiler is looking for a "char2byte" function that returns an array of std_logic_vector because that's the type of the variable you are assigning to. It can't find one (hence "no matching subprogram") because the only "char2byte" you wrote returns a single std_logic_vector, not an array of them.

    So addressing a single element of that array will let it find your char2byte - and now the error message makes perfect sense...