# Conversion from fixed point to IEEE 754 [closed]

I am trying to design a simple processor (in VHDL) that takes in its input a real number coded in the fixed point representation in 2's complement (10 bits for the integer part, and 6 for the fractional part), and outputs its IEEE 754 single-precision format equivalent:

I have been searching for a while now, and still couldn't find any resources on this type of conversion, at least some flow chart from which I could start.

• Make sure when you're grabbing a picture from an external source, you need to cite it so that 1) You're not plagiarizing and 2) We can refer to what you're reading to better understand the background information.
– user103380
Commented Sep 16, 2019 at 19:24
• @KingDuken The picture wasn't taken from any source, I made it with paint. If there happens to be one similar to it, it's certainly a pure coincidence. Commented Sep 16, 2019 at 19:28
• Understood :) Just looked like something from an online resource.
– user103380
Commented Sep 16, 2019 at 19:32

Basically, you do four things:

• convert from 2’s complement to signed magnitude, save the sign
• count leading zeroes (find first ‘one’)
• add a bias to that to make the exponent
• shift the integer to normalize it as the mantissa.

About four lines of code that synthesizes to some logic, an adder, and a shift mux.

EDIT: As Tim said, before you do all that you also need to convert the 2’s complement integer to signed magnitude. So one more line.

• The OP needs to determine the sign and make the number positive first (while setting the sign bit in the output), and needs a separate path for zero. So maybe five or six lines. Commented Sep 16, 2019 at 19:57

For -2008 compatibility there are IEEE packages fixed_pkg and float_pkg which provide conversion functions:

library ieee;
use ieee.std_logic_1164.all;

entity fixed_to_float is
port (
fixed_input:    in  std_logic_vector (15 downto 0);
float_out:      out std_logic_vector(31 downto 0);
clk:            in  std_logic
);
end entity fixed_to_float;

architecture fie of fixed_to_float is
use ieee.fixed_pkg.all;
use ieee.float_pkg.all;
use ieee.fixed_float_types.all;  -- rounding style

function slv_to_float32(input:  std_logic_vector) return std_logic_vector is
begin
report "input =" & LF & to_string (input);
report "to_sfixed =" & LF &to_string (to_sfixed(input, 9, -6));
report "float32 =" & LF & to_string (to_float(to_sfixed(input, 9, -6), 8, 23,round_zero));
return to_slv(to_float(to_sfixed(input, 9, -6), 8, 23, round_zero));
end function;
begin
process (clk)
begin
if rising_edge(clk) then
float_out <= slv_to_float32(fixed_input);
end if;
end process;
end architecture fie;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity fixed_to_float_tb is
end entity;

architecture foo of fixed_to_float_tb is
signal fixed_input: std_logic_vector (15 downto 0);
signal float_out:   std_logic_vector(31 downto 0);
signal clk:         std_logic := '0';

begin
DUT:
entity work.fixed_to_float
port map (
fixed_input => fixed_input,
float_out   => float_out,
clk         => clk
);
CLOCK:
process
begin
wait for 5 ns;
clk <= not clk;
if now > 5 ns then
wait;
end if;
end process;
STIMULUS:
process
begin
fixed_input <= "0011000011101001";
wait;
end process;
end architecture;


The 'notes' to go with the above fixed_to_float architecture:

-- 16 bit sfixed with 10 bit integer and 6 bit fraction sfixed(9 downto -6)
-- the binary point is between index 0 and index -1

-- IEEE-754 single precision floating point.  This is a "float"
-- in C, and a FLOAT in Fortran.  The exponent is 8 bits wide, and
-- the fraction is 23 bits wide.  This format can hold roughly 7 decimal
-- digits.  Infinity is 2**127 = 1.7E38 in this number system.
-- The bit representation is as follows:
-- 1 09876543 21098765432109876543210
-- 8 76543210 12345678901234567890123
-- 0 00000000 00000000000000000000000
-- 8 7      0 -1                  -23
-- +/-   exp.  fraction

-- signed fixed point to float
-- function to_float (
--   arg                     : UNRESOLVED_sfixed;
--   constant exponent_width : NATURAL    := float_exponent_width;  -- length of FP output exponent
--   constant fraction_width : NATURAL    := float_fraction_width;  -- length of FP output fraction
--   constant round_style    : round_type := float_round_style;  -- rounding
--   constant denormalize    : BOOLEAN    := float_denormalize)  -- rounding option
--   return UNRESOLVED_float;

-- to_float(sfixed, exponent width, fraction width, round_zero)
-- float32 8 exp 23 frac round_type -> round_zero (truncate)
-- denormalize is default value


These packages can sometimes be found in library ieee_proposed for -1993 compliance and are synthesis eligible.

The above testbench produces:

/usr/local/bin/ghdl -a  --std=08 fixed_to_float.vhdl
/usr/local/bin/ghdl -e  --std=08 fixed_to_float_tb
/usr/local/bin/ghdl -r --std=08 fixed_to_float_tb
fixed_to_float.vhdl:45:9:@5ns:(report note): input =
0011000011101001
fixed_to_float.vhdl:46:9:@5ns:(report note): to_sfixed =
0011000011.101001
fixed_to_float.vhdl:47:9:@5ns:(report note): float32 =
0:10000110:10000111010010000000000


While report statement format is implementation dependent the report string values should be reported faithfully. The report statements can be removed.

These show for the example given that the conversion is accurate. Note the exponent is a signed magnitude value occupying 8 bits, the mantissa is 23 bits signed magnitude and the sign occupies 1 bit for a 32 bit IEEE Std 754 floating point number. The rounding style for the to_float function call has been set to round_zero (truncate) to demonstrate the mantissa fidelity. Also note the left most mantissa '1' bit is not included in the format.

These conversions are synthesis eligible where the packages are supported or allowed by synthesis vendors. (Historically they'd prefer to sell you IP in any case you're responsible for design validation/verification).

As far as the hardware there'll be a 16 bit adder and multiplexer for producing the absolute value of the fixed point value, a priority encoder for determining the shift distance (and exponent) and a shifter for normalization.

The packages are briefly described in IEEE Std 1076-2008 16.10 Fixed-point package and 16.11 Floating-point package. The -2008 sources can currently be found at IEEE Standards Downloads and Executable Files.

The original packages including support for older revisions of the VHDL standard can be found deposited by their author on github where you'll find some documentation.

• Thank you for taking the time to make this in-depth answer. Commented Sep 17, 2019 at 11:15