Search code examples
vhdlxilinxvivado

vhdl function is not being called


I have written a vhdl code something like this

entity myentity is
 port( number : in integer range 0 to 15; result : out integer);
 function myfunction(num: integer range 0 to 15) return integer is
 variable i: integer :=1;
 variable error1, error2, error, temp, concat: integer;
 variable res: integer;
 begin
  if (num<=1)then
   res := num;
  else 
   while (2**i < num) loop
    i:=i+1;
   end loop;
   error2 := num-(2**i); 
   error1 := num-(2**(i-1));
   if abs(error1)<error2 then
    error := error1;
   else error := error2;
   end if;
   if error=0 then
   res := to_integer(to_unsigned(num,8) sll i);
   else 
   temp := num-error;
   concat := myfunction(temp);
   res :=to_integer(to_unsigned(temp,4) & to_unsigned(concat,i-1));
   end if;
  end if;
 return res;
end myfunction;
end myentity;

architecture Behavioral of myentity is
begin
 result<=myfunction(number);
end Behavioral;

Function is recursive. The problem is, the architecture body is not calling the function. i.e., function lines are not being executed. When I compile the program, it shows no error. Any help? I changed the example to the original code.


Solution

  • With your new question code formatted for readability, report statements added for debugging and an added testbench to drive all possible integer values of number (0 to 15), creating a Minimal, Complete and Verifiable example:

    library ieee;             -- CONTEXT CLAUSE ADDED
    use ieee.numeric_std.all; -- unsigned, to_unsigned, to_integer, sll
     -- superfluous parentheses removed, indentation added  for clarity:
    entity myentity is
        port (
            number:  in  integer range 0 to 15; 
            result:  out integer
        );
    
        function myfunction (num: integer range 0 to 15) return integer is
            variable i: integer := 1;
            variable error1, error2, error, temp, concat: integer;
            variable res: integer;
        begin
            if num <= 1 then  -- CONDITION COULD BE num = 0
                res := num;
                report "num = " & integer'image(num);        -- ADDED REPORT
            else
                while 2 ** i < num loop
                    i := i + 1;
                end loop;
                report "i = " & integer'image(i);            -- ADDED REPORT
                error2 := num - 2 ** i; 
                report "error2 = " & integer'image(error2);  -- ADDED REPORT
                error1 := num - 2 ** (i - 1);
                report "error1 = " & integer'image(error1);  -- ADDED REPORT
                if abs error1 < error2 then
                    error := error1;
                else
                    error := error2;
                end if;
                report "error = " & integer'image(error);    -- ADDED REPORT
                if error = 0 then
                    res := to_integer(to_unsigned(num, 8) sll i);
                    report "res = " & integer'image(res);    -- ADDED REPORT
                else
                    temp := num - error;
                    report "temp = " & integer'image(temp);  -- ADDED REPORT
                    concat := myfunction(temp);
                    report "concat = " & integer'image(concat); -- ADDED REPORT
                    res := to_integer(to_unsigned(temp, 4) & 
                           to_unsigned(concat, i - 1) );
                    report "res = " & integer'image(res);    -- ADDED REPORT
                end if;
            end if;
            return res;
        end myfunction;
    end entity myentity;
    
    architecture behavioral of myentity is
    begin
        result <= myfunction(number);
    end architecture behavioral;
    
    entity myentity_tb is
    end entity;
    
    architecture foo of myentity_tb is
        signal result: integer;
        signal number: integer range 0 to 15;
    begin
    
    DUT:
        entity work.myentity 
            port map (
                number => number,
                result => result
            );
    STIMULI:
        process
        begin
            for i in 0 to 15 loop
                number <= i;
                report "number = " & integer'image(i);
                wait for 10 ns;
            end loop;
            wait;
        end process;
    end architecture;
    

    Analyzing the code, elaborating and running the testbench produces with a VHDL implementation dependent report statement format:

    myentity.vhdl:17:13:@0ms:(report note): num = 0
    myentity.vhdl:74:13:@0ms:(report note): number = 0
    myentity.vhdl:74:13:@10ns:(report note): number = 1
    myentity.vhdl:17:13:@10ns:(report note): num = 1
    myentity.vhdl:74:13:@20ns:(report note): number = 2
    myentity.vhdl:22:13:@20ns:(report note): i = 1
    myentity.vhdl:24:13:@20ns:(report note): error2 = 0
    myentity.vhdl:26:13:@20ns:(report note): error1 = 1
    myentity.vhdl:32:13:@20ns:(report note): error = 0
    myentity.vhdl:35:17:@20ns:(report note): res = 4
    myentity.vhdl:74:13:@30ns:(report note): number = 3
    myentity.vhdl:22:13:@30ns:(report note): i = 2
    myentity.vhdl:24:13:@30ns:(report note): error2 = -1
    myentity.vhdl:26:13:@30ns:(report note): error1 = 1
    myentity.vhdl:32:13:@30ns:(report note): error = -1
    myentity.vhdl:38:17:@30ns:(report note): temp = 4
    myentity.vhdl:22:13:@30ns:(report note): i = 2
    myentity.vhdl:24:13:@30ns:(report note): error2 = 0
    myentity.vhdl:26:13:@30ns:(report note): error1 = 2
    myentity.vhdl:32:13:@30ns:(report note): error = 0
    myentity.vhdl:35:17:@30ns:(report note): res = 16
    myentity.vhdl:40:17:@30ns:(report note): concat = 16
    ../../src/ieee/numeric_std-body.v93:2151:7:@30ns:(assertion warning): NUMERIC_STD.TO_UNSIGNED: vector truncated
    myentity.vhdl:43:17:@30ns:(report note): res = 8
    myentity.vhdl:74:13:@40ns:(report note): number = 4
    myentity.vhdl:22:13:@40ns:(report note): i = 2
    myentity.vhdl:24:13:@40ns:(report note): error2 = 0
    myentity.vhdl:26:13:@40ns:(report note): error1 = 2
    myentity.vhdl:32:13:@40ns:(report note): error = 0
    myentity.vhdl:35:17:@40ns:(report note): res = 16
    myentity.vhdl:74:13:@50ns:(report note): number = 5
    myentity.vhdl:22:13:@50ns:(report note): i = 3
    myentity.vhdl:24:13:@50ns:(report note): error2 = -3
    myentity.vhdl:26:13:@50ns:(report note): error1 = 1
    myentity.vhdl:32:13:@50ns:(report note): error = -3
    myentity.vhdl:38:17:@50ns:(report note): temp = 8
    myentity.vhdl:22:13:@50ns:(report note): i = 3
    myentity.vhdl:24:13:@50ns:(report note): error2 = 0
    myentity.vhdl:26:13:@50ns:(report note): error1 = 4
    myentity.vhdl:32:13:@50ns:(report note): error = 0
    myentity.vhdl:35:17:@50ns:(report note): res = 64
    myentity.vhdl:40:17:@50ns:(report note): concat = 64
    ../../src/ieee/numeric_std-body.v93:2151:7:@50ns:(assertion warning): NUMERIC_STD.TO_UNSIGNED: vector truncated
    myentity.vhdl:43:17:@50ns:(report note): res = 32
    myentity.vhdl:74:13:@60ns:(report note): number = 6
    myentity.vhdl:22:13:@60ns:(report note): i = 3
    myentity.vhdl:24:13:@60ns:(report note): error2 = -2
    myentity.vhdl:26:13:@60ns:(report note): error1 = 2
    myentity.vhdl:32:13:@60ns:(report note): error = -2
    myentity.vhdl:38:17:@60ns:(report note): temp = 8
    myentity.vhdl:22:13:@60ns:(report note): i = 3
    myentity.vhdl:24:13:@60ns:(report note): error2 = 0
    myentity.vhdl:26:13:@60ns:(report note): error1 = 4
    myentity.vhdl:32:13:@60ns:(report note): error = 0
    myentity.vhdl:35:17:@60ns:(report note): res = 64
    myentity.vhdl:40:17:@60ns:(report note): concat = 64
    ../../src/ieee/numeric_std-body.v93:2151:7:@60ns:(assertion warning): NUMERIC_STD.TO_UNSIGNED: vector truncated
    myentity.vhdl:43:17:@60ns:(report note): res = 32
    myentity.vhdl:74:13:@70ns:(report note): number = 7
    myentity.vhdl:22:13:@70ns:(report note): i = 3
    myentity.vhdl:24:13:@70ns:(report note): error2 = -1
    myentity.vhdl:26:13:@70ns:(report note): error1 = 3
    myentity.vhdl:32:13:@70ns:(report note): error = -1
    myentity.vhdl:38:17:@70ns:(report note): temp = 8
    myentity.vhdl:22:13:@70ns:(report note): i = 3
    myentity.vhdl:24:13:@70ns:(report note): error2 = 0
    myentity.vhdl:26:13:@70ns:(report note): error1 = 4
    myentity.vhdl:32:13:@70ns:(report note): error = 0
    myentity.vhdl:35:17:@70ns:(report note): res = 64
    myentity.vhdl:40:17:@70ns:(report note): concat = 64
    ../../src/ieee/numeric_std-body.v93:2151:7:@70ns:(assertion warning): NUMERIC_STD.TO_UNSIGNED: vector truncated
    myentity.vhdl:43:17:@70ns:(report note): res = 32
    myentity.vhdl:74:13:@80ns:(report note): number = 8
    myentity.vhdl:22:13:@80ns:(report note): i = 3
    myentity.vhdl:24:13:@80ns:(report note): error2 = 0
    myentity.vhdl:26:13:@80ns:(report note): error1 = 4
    myentity.vhdl:32:13:@80ns:(report note): error = 0
    myentity.vhdl:35:17:@80ns:(report note): res = 64
    myentity.vhdl:74:13:@90ns:(report note): number = 9
    myentity.vhdl:22:13:@90ns:(report note): i = 4
    myentity.vhdl:24:13:@90ns:(report note): error2 = -7
    myentity.vhdl:26:13:@90ns:(report note): error1 = 1
    myentity.vhdl:32:13:@90ns:(report note): error = -7
    myentity.vhdl:38:17:@90ns:(report note): temp = 16
    ./myentity_tb:error: bound check failure at myentity.vhdl:39
    ./myentity_tb:error: simulation failed
    

    Where we can see for a number value of 0 the function returns 0 which is assigned to result. That explains why without driving different values (1 through 15) on number through stimuli (here a testbench, a higher level in the design hierarchy) why result is 0 and produces no error. (Note without an assignment to result it's value would have been INTEGER'LOW the minimum value for that type, result has no subtype constraint and inherits it's subtype from the type mark in the port declaration for result).

    There are two classes of messages causing concern in the output for number values 1 through 15.

    The first is the report message from package numeric_std telling you you clipped left elements from the binary number eventually converted to integer and assigned to res. This represents inaccuracy in your algorithm that needs to be addressed. You can note that res (assigned to result in the concurrent signal assignment statement) is 64 when that occurs.

    The second is the error message when number was assigned a value of 9 and the value passed to the recursive call to myfunction was outside it's parameter num's range (0 to 15, the value 16 for variable temp). A bounds violation error is sufficient to cause simulation to cease, the integrity of the simulation is compromised. (And this is what strong typing does for you, the subtype of parameter num should have been chosen for a purpose in implementing myfunction).

    You can easily remove every report statement added for debugging when your algorithm functions satisfactorily after which you can test again.

    Note the values of number can be distinguished by what time they occur at during simulation.

    This answer shows why your code reports no error as well as showing how to tell what it's doing to allow debugging for other values of number.

    As we can see my the presence of the very first report statement the function myfunction is getting called. Also if result were not assigned it's default value would be a negative number.