Search code examples
vhdl

"=" Function exists for all types, where can I explicitly get it from?


In the following code, I am using numeric_std_unsigned. This defines "=" such that if S has a meta value, it will always fail the compare, regardless of what it is comparing to.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;

entity lib_test is
end entity;

architecture sim of lib_test is
begin

  process
    variable s    : std_logic_vector(7 downto 0);
  begin

    s := x"UU";
    report "s=" & to_string(s);

    if s = x"UU" then
      report "S match";
    else
      report "S no match";
    end if;

    wait;
  end process;

end architecture sim;

My Question is, other than manually adding all the functions I need from numeric_std_unsigned and leaving out the "=" function defined for arithmatic, or using explicit references to every function call (and not using numeric_std_unsigned.all at the top), is there a path I can explicitly use to get the "=" function implicitly defined for SLV?


Solution

  • Running your original test case with some white space modification:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std_unsigned.all;
    
    entity lib_test is
    end entity;
    
    architecture sim of lib_test is
    begin
    
        process
            variable s:     std_logic_vector(7 downto 0);
        begin
    
            s := x"UU";
            report "s = " & to_string(s);
    
            if s = x"UU" then
                report "S match";
            else
                report "S no match";
            end if;
            wait;
        end process;
    end architecture sim;
    

    yields a reproducible error:

    ghdl -a --std=08 lib_test.vhdl
    ghdl -e --std=08 lib_test sim
    ghdl -r --std=08 lib_test sim
    lib_test.vhdl:16:9:@0ms:(report note): s = UUUUUUUU
    ../../src/ieee2008/numeric_std-body.vhdl:1776:7:@0ms:(assertion warning): NUMERIC_STD."=": metavalue detected, returning FALSE
    

    There are four ways to cure the issue in VHDL.

    Using an alias in an inner declarative region to specify the correct "=" operator:

    architecture sim_alias of lib_test is
    begin
    
        process   -- <-- inner declarative region
            variable s:     std_logic_vector(7 downto 0);
            alias "=" is ieee.std_logic_1164."="
                    [ieee.std_logic_1164.std_ulogic_vector,
                     ieee.std_logic_1164.std_ulogic_vector return
                     std.standard.BOOLEAN];
        begin
    
            s := x"UU";
            report "s = " & to_string(s);
    
            if s = x"UU" then
                report "S match";
            else
                report "S no match";
            end if;
            wait;
        end process;
    end architecture sim_alias;
    

    resulting in:

    ghdl -e --std=08 lib_test sim_alias
    ghdl -r --std=08 lib_test sim_alias
    lib_test.vhdl:39:9:@0ms:(report note): s = UUUUUUUU
    lib_test.vhdl:42:13:@0ms:(report note): S match
    

    Testing the string value:

    architecture sim_string of lib_test is
    begin
    
        process
            variable s:     std_logic_vector(7 downto 0);
        begin
    
            s := x"UU";
            report "s = " & to_string(s);
    
    
            if to_string(s) = x"UU" then
                report "S match";
            else
                report "S no match";
            end if;
            wait;
        end process;
    end architecture sim_string;
    

    also producing the correct result:

    ghdl -e --std=08 lib_test sim_string
    ghdl -r --std=08 lib_test sim_string
    lib_test.vhdl:58:9:@0ms:(report note): s = UUUUUUUU
    lib_test.vhdl:62:13:@0ms:(report note): S match
    

    Calling the correct "=" function:

    architecture sim_function_call of lib_test is
    begin
    
        process 
            variable s:     std_logic_vector(7 downto 0);
        begin
    
            s := x"UU";
            report "s = " & to_string(s);
    
           if ieee.std_logic_1164."=" (s, x"UU") then
                report "S match";
            else
                report "S no match";
            end if;
            wait;
        end process;
    end architecture sim_function_call;
    

    also successful:

    ghdl -e --std=08 lib_test sim_function_call
    ghdl -r --std=08 lib_test sim_function_call
    lib_test.vhdl:78:9:@0ms:(report note): s = UUUUUUUU
    lib_test.vhdl:81:13:@0ms:(report note): S match
    

    Use a case statement:

    architecture sim_case of lib_test is
    begin
    
        process 
            variable s:     std_logic_vector(7 downto 0);
        begin
            s := x"UU";
            report "s = " & to_string(s);
            case s is
                when x"UU" =>
                    report "S match";
                when others  =>
                    report "S no match";
            end case;
            wait;
        end process;
    end architecture sim_case;
    

    also producing the same result:

    ghdl -e --std=08 lib_test sim_case
    ghdl -r --std=08 lib_test sim_case
    lib_test.vhdl:96:9:@0ms:(report note): s = UUUUUUUU
    lib_test.vhdl:99:17:@0ms:(report note): S match
    

    Also note that if you were assigning a signal or variable you could use a selected signal assignment or a selected variable assignment, both of which represent case statements which are guaranteed to use the predefined "=".

    You could also author your own function providing an overload for "=" operator exhibiting the correct behavior. Like the use of an alias this would depend on the use of an inner declarative region (here the process statement) to prevent the predefined operator from being used in an arithmetic context where the operator in ieee.numeric_std_unsigned is intended.

    Likewise you could author your own function for use in a function call, or with a little malice of forethought use

      -- Id: M.5
     function STD_MATCH (L, R : STD_ULOGIC_VECTOR) return BOOLEAN;
      -- Result subtype: BOOLEAN
      -- Result: terms compared per STD_LOGIC_1164 intent
    

    From package numeric_std.

    The issue comes about from mixing evaluation of a std_logic_vector value (base type std_ulogic_vector) both as metavalues and numeric values, which is likely driven by style issues when package numeric_std type unsigned could be used along with type conversions, noting the dearth of mapping between VHDL port types and interface types in multi-language supporting simulators (such as Modelsim).

    The solution to abandon strong typing may not be the ideal solution. The proficiency required to patch up your VHDL source as a result is roughly equivalent to knowing when and where to perform type conversions. These are all 'gimmick' solutions.