3

I have a general question regarding the calling of procedures with other types. In the general sense, what is the correct way to declare an overload of a procedure so it may be called later using multiple types?

Consider the dummy case of a simple procedure that should work the same for both std_logic_vector / unsigned / std_logic. The unsigned variant in my example will fail bc of a looped call to itself, and the std_logic variant will fail because of an ambiguous call. However, directly converting in the procedure call is not allowed and will cause an error as well (ref: IEEE Std 1076-2008 section 4.2.2.3 "Signal parameters"). Creating an intermediate signal is also not an option, as signals cannot be declared in a procedure's declarative part.

What is the best practice for making overloads when knowing the core procedure will handle all cases the same way (as with my dummy case of using the "=" operator)?

package body dummy_pkg is
    procedure dummy_procedure(
        signal value_1 : std_logic_vector;
        signal value_2 : std_logic_vector
    ) is
    begin
        assert value_1 = value_2
            report "dummy_procedure: value_1 and value_2 are not equal"
            severity error;
        wait until value_1'event or value_2'event;
    end procedure dummy_procedure;

    procedure dummy_procedure(
        signal value_1 : unsigned;
        signal value_2 : unsigned
    ) is
    begin
        dummy_procedure(
            value_1 => value_1,
            value_2 => value_2
        );
    end procedure dummy_procedure;

    procedure dummy_procedure(
        signal value_1 : std_logic;
        signal value_2 : std_logic
    ) is
    begin
        dummy_procedure(
            value_1(0) => value_1,
            value_2(0) => value_2
        );
    end procedure dummy_procedure;

end package body dummy_pkg;

I understand I can work around this by simply writing the procedure out for each type, but if I am missing an obvious solution, it would be nice to learn for future use.

2 Answers 2

3

Slightly off-topic, but if you upgrade to VHDL-2019, it becomes easier. This is not quite your example, but it is one I have tested. You need a VHDL-2019 simulator - currently this is Aldec. Nvc (open source) is actively working on 2019. Be sure to talk to your commercial vendors to get this supported.

library ieee ; 
  use ieee.std_logic_1164.all ; 
  
package MuxPkg is
  function Mux4 (
    Sel : std_logic_vector;  
    A   : type is private ;
    B, C, D : A'subtype
  ) return A'subtype ; 

end package MuxPkg ;

package body MuxPkg is
  
  function Mux4 (
    Sel : std_logic_vector;  
    A   : type is private ;
    B, C, D : A'subtype
  ) return A'subtype is 
    variable LeftMostValueReturn : A'subtype ; 
  begin
    case Sel is
      when "00" =>     return A ; 
      when "01" =>     return B ; 
      when "10" =>     return C ; 
      when "11" =>     return D ; 
      when others =>   return LeftMostValueReturn ; 
    end case ; 
  end function Mux4 ; 

end package body MuxPkg ;
Sign up to request clarification or add additional context in comments.

Comments

3

I think I figured it out! (But I will keep the question open if there are other thoughts on the matter). From page 17 of "VHDL-2008; Just the new stuff", I found that I can declare a generic type as the generic of a procedure. From that, I can declare any new with the generic map locked to a specific type. The example becomes then (note we lose all but one procedure body)

package dummy_pkg is
    -- Procedure declaration for procedure
    procedure dummy_procedure
    generic(type gt_generic_type)
    parameter(
        signal value_1 : gt_generic_type;
        signal value_2 : gt_generic_type
    );
    procedure dummy_procedure is new dummy_procedure
        generic map (gt_generic_type => std_logic_vector);
    procedure dummy_procedure is new dummy_procedure
        generic map (gt_generic_type => unsigned);
    procedure dummy_procedure is new dummy_procedure
        generic map (gt_generic_type => std_logic);
end package dummy_pkg;

package body dummy_pkg is
    procedure dummy_procedure
    generic(type gt_generic_type)
    parameter(
        signal value_1 : gt_generic_type;
        signal value_2 : gt_generic_type
    ) 
    is
    begin
        assert value_1 = value_2
            report "dummy_procedure: value_1 and value_2 are not equal"
            severity error;
        wait until value_1'event or value_2'event;
    end procedure dummy_procedure;

end package body dummy_pkg;

See also how to pass functions to the procedure so that may use type specific functions (e.g to_string): Can the VHDL image attribute be invoked on a generic type?

4 Comments

Please edit your answer, comments are not for addition, clarifications, and so on.
Slightly off topic, but relating to this answer. If anyone knows how to do a generic type solution where the procedure uses the 'range attribute, please let me know. Using the soluting here means the compiler will not allow for the use of type-specific attributes, but it would be nice to know for when I know only 'range applicable types will be used.
Correct. VHDL-2008 only allows you to create a generic type as a private type. With this only basic operations of assignment, allocation, type qualification and type conversion and expressions with the predefined equality (=) and inequality (/=) operators are supported. So no 'range. Any other subprogram you need you have to pass as a generic.
OTOH, with VHDL-2019, you can designate the generic type to be an array type. Then you get 'range. However, you cannot map a scalar type to the array type.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.