Electronic – How to convert single precision floating point numbers in a file into their 32 bit representation in VHDL

conversionfloating pointvhdl

Test data consists of single precision floating point numbers in a text file. These must be read into testbench and applied to a 32 bit std_logic_vector input port. The numbers can be read in as "real" type but how does one obtain their 32 bit representation to store in a std_logic_vector?

Floating point numbers consist of mantissa and exponent. Here the floating point number shall be reversed to get its actual representation inside the hardware and that will be stored in an std_logic_vector.


Here are a few numbers in the text file: -0.951835638, -0.154052139, 0.007186272. I need to convert these into their 32 bit binary representation and store it into std_logic_vector. These numbers are originally floating point with 8 bit exponent and 23 bit mantissa. I want them to be binary represented in this way when I store them into the std_logic_vector.

Best Answer

The testbench below is answer to my question. The result of conversion is stored in slv. The input file contains a column of real numbers of the type I mentioned in the question i.e single preciousion floating point numbers generated from a program probably written in C or C++. As expected, there is difference between real1 and real2 which is another thing I wanted to check.

The float_generic_pkg which is basis for the float_pkg defines the float32 as follows:

subtype float32 is float (8 downto -23);

Where the float type is:

subtype float is (resolved) UNRESOLVED_float;

Where the UNRESOLVED_float is actually:

type UNRESOLVED_float is array (INTEGER range <>) of STD_ULOGIC;

This means that the floating point type is fundamentally just a std_logic_vector and thus not the same thing as a real!

Anyway, the code sample below is answer to the question.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL; 
use IEEE.float_pkg.all;

library std;
use std.textio.all;

entity t_real_to_slv is
end  t_real_to_slv;

architecture beh of  t_real_to_slv is

  -- real number read from file
  signal real1: real;    
  -- float resulting from conversion of real1
  signal float1: float32;
  -- slv resulting from conversion of float1
  signal slv: std_logic_vector(31 downto 0);  
  -- float resulting from conversion of slv
  signal float2: float32;
  -- real number resulted from conversion of float type
  signal real2: real;
  -- difference between the real1 and real2
  signal real_delta: real;

begin

  process

    file text_in  : text open read_mode  is "../../../real_in.txt"; 
    file text_out : text open write_mode is "../../dump_out.txt";

    variable line_in, line_out : line;
    variable r_in, r_out : real;

  begin  

    for i in 1 to 10 loop 

      if(NOT ENDFILE(text_in)) then

        -- read the current line.
        readline(text_in,line_in);   

        -- read the real number from input file line
        read(line_in, r_in);        
        real1 <= r_in;
        wait for 1 ns;

        -- convert the real number to float32, the float32
        -- is merely a float with limits 8, -23
        float1 <= to_float(real1);      
        wait for 1  ns;

        -- convert the float into std_logic_vector so we can
        -- have the binary representation of real1      
        slv <= std_logic_vector(float1);
        wait for 1 ns;

        -- now convert slv into float32
        float2 <= to_float(slv);
        wait for 1 ns;

        -- now convert float32 into real type
        real2 <= to_real(float2);
        wait for 1 ns;

        -- calculate the difference between the real number found
        -- in the input text file and the real number 
        real_delta <= real2 - real1;
        wait for 0 ns;

        -- write the original real number 
        r_out := real1;
        write(line_out, r_out);
        write(line_out, ht);
        -- write the real number resulting from conversions     
        r_out := real2;
        write(line_out, r_out);
        write(line_out, ht);
        -- write difference between the original real number
        -- and the one generated from conversions
        r_out := real_delta;
        write(line_out, r_out);     
        writeline(text_out, line_out);

        -- verify that the floating point numbers are equal
        -- i.e no information is lost in conversion
        -- floa32->slv->float32; expected to pass
        assert float2 = float1 
        report "floating point values do not match"
        severity warning;

        -- verify that the floating point number read from the 
        -- file is equal to the number resulting from conversions
        -- i.e no information is lost in conversion
        -- real->floa32->slv->float32->real; expected to fail
        assert real2 = real1 
        report "real values do not match"
        severity warning;

      end if;
    end loop;

    assert false
    report "end of test"
    severity failure;
    wait;
  end process;

end architecture;

The gist of all this is these two lines:

real_to_slv := std_logic_vector(to_float(real_number));
slv_to_real_number := to_real(to_float(real_to_slv));

The slv must be declared as a 32 bit vector. Else, the conversions will fail at runtime. We need to use the float_pkg but not the float type itself in this case.