Search code examples
vhdlfpgaieee-754

Get IEEE-754 single precision representation of a real number in VHDL


I want to convert a real number to his bit representation, with the fields of sign, exponent and mantissa in a VHDL TB for testing purposses (as a STD_LOGIC_VECTOR of 32 bits). Is there anyway to convert a real number to this representation directly in VHDL?

I know that in C is possible use a struct to achieve it, but I don't know if it's possible in VHDL.

Thank you.

Edit:

I've found this solution:

https://www.edaplayground.com/x/gQiN

But the synthesizer throw this error:

[XSIM 43-4187] File "/proj/xbuilds/2021.2_INT_0504_1926/installs/all_platforms/Vivado/2021.2/data/vhdl/src/ieee_2008/float_pkg.vhdl" Line 45 : The "Vhdl 2008 Package Instantiation Declaration" is not supported yet for simulation.

Then, I think the best solution is build a VHDL function that convert a real number to their IEEE-754 bit representation.


Solution

  • At the end, I created this VHDL function that convert a real number to his IEEE-754 integer representation:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    
    
    -- Uncomment the following library declaration if using
    -- arithmetic functions with Signed or Unsigned values
    use IEEE.NUMERIC_STD.ALL;
    use ieee.math_real.all;
    
    package Help is
    
        type t_vector is array (natural range <>) of integer;
        type data_t   is array (natural range <>, natural range <>) of real;
        
        function float_2_slv 
        (
            num : real := 0.0
        )
        return std_logic_vector;
        
    end package Help;
    
    package body Help is
        ----------------------------------------------------------------------------------------------------
        function  float_2_slv 
        (
            num : real := 0.0
        ) 
        return std_logic_vector is
        
            constant bits_exponent : integer := 8;
            constant bits_mantissa : integer := 23;
            
            variable abs_num : real;
            variable sign : std_logic;
            variable exponent : real;
            variable exponent_norm : std_logic_vector(bits_exponent-1 downto 0);
            variable mantissa : real;
            variable mantissa_norm : std_logic_vector(bits_mantissa - 1 downto 0);
            variable quotient : real;
            
            variable slv  : std_logic_vector(31 downto 0);
            
        begin
            
            sign := '0';
            abs_num := abs(num);
            if num < 0.0 then
                sign := '1';
            end if;
            
            exponent := floor(log2(abs_num));
            quotient := 2.0 ** exponent;
            mantissa := abs_num / quotient;
            
            exponent_norm := std_logic_vector(to_unsigned(natural(127.0+exponent), bits_exponent));
            mantissa_norm := std_logic_vector(to_signed(natural(round(mantissa*(2.0**(bits_mantissa)))), bits_mantissa));
        
            slv := sign & exponent_norm & mantissa_norm;
        
            return slv;
        end;
    
    end package body Help;
    

    If it's required the conversion from a float to an IEEE-754 integer in Vitis, then, could be do it as in C:

    uint32_t get_IEEE754(float d)
    {
        uint32_t bits;
        memcpy(&bits, &d, sizeof(d));
        return bits;
    }