0
\$\begingroup\$

I am trying to convert a number I get from a keyboard to the IEEE-753 standard using VHDL or a logic implementation, I don't want the complete answer only a guide about how I should encourage this.

I read a keyboard and store in memory every digit from the entire and decimal part and the user also has the option to enter the exponent which is also saved in another memory position.

I read in this website about how to convert a decimal number to the IEEE standard. Suppose now that I have a number represented in scientific notation, for example:

22.523 x 10^20

I read this number in BCD from my memory so I need to convert it to binary to then process it, my idea is:

  1. Convert entire part to binary.
  2. Take binary entire part and multiply by 10 times indicated by the exponent in this case, 22 x 10^20.
  3. Convert decimal part to binary.
  4. Take binary decimal part and multiply by 10 times indicated by the [exponent]-[number of decimal digits] in this case, 523 x 10^17.
  5. Add the two binary numbers.

So now I have my number in binary and I can apply the method indicated in the website.

To represent this number I will need two registers, one for every part of the number the first one will need: log2(22 x 10^20) bits which is 71 bits and the second part will need log2(523 x 10^17) bits which is 66 bits so I will need 71+66 = 137 bits to store the result and then convert it to IEEE-753.

Is this normal? Is any other way to do it? Or is it accomplished on this way?

\$\endgroup\$
  • \$\begingroup\$ That's not how it's usually done, but why not start off with 22523e17 in the first place, instead of doing it piecewise? \$\endgroup\$ – Ignacio Vazquez-Abrams Oct 12 '13 at 1:11
  • \$\begingroup\$ Because I can't control it, I am reading this numbers from the memory and they are in the memory as the user entered them \$\endgroup\$ – Andres Oct 12 '13 at 1:15
2
\$\begingroup\$

First of all, this is not something you would normally do in hardware; you would do this in firmware on a microprocessor, either internal or external to the FPGA.

But if you absolutely had to design a datapath to do this, it should require nothing more than an integer adder and integer multiplier, along with a register we'll call the "integer accumulator" to handle the exponent, and an IEEE-754 adder and IEEE-754 multiplier along with an IEEE-754 accumulator register to handle the mantissa and ultimately produce the final result.

Let's get some terminology straight: In a number like 22.523×1020, the "22.523" is the mantissa and the "20" is the exponent. Let's call them the "decimal mantissa" and "decimal exponent" to distinguish them from the binary mantissa and binary exponent we'll eventually be producing.

Start by converting the decimal exponent to binary, which requires scanning its digits left-to-right, multiplying the integer accumulator by 10 before adding in the next digit. Negate the result if the exponent is negative.

Now, start converting the decimal mantissa. Again, scanning from left-to-right, we use a lookup table to convert each BCD digit to its IEEE-754 equivalent. We take the IEEE-754 accumulator, multiply it by 10, and add the converted digit to it. After we encounter the decimal point, we continue converting digits, but now we also decrement the binary version of the decimal exponent we computed in the previous paragraph once for each digit.

At this point, we have an integer representation of the decimal mantissa in the IEEE-754 accumulator, and we have a properly adjusted version of the original decimal exponent in the integer accumulator.

The final step is to look at the integer accumulator. If it is positive, you go into a loop that multiplies the IEEE-754 accumulator by 10 (again, from a lookup table) and decrements the integer accumulator until it reaches zero. If the integer accumulator was negative, you multiply the IEEE-754 accumulator by 0.1 and increment the integer accumulator until it is zero. In either case, when you finish, you have the final floating-point number in the IEEE-754 accumulator.

Oh, and if the decimal mantissa is negative, set the sign bit in the IEEE-754 number.

There are many potential ways to optimize this process, but that would depend on your exact situation. I hope this is enough to get you going.

\$\endgroup\$
  • \$\begingroup\$ Very nice explanation! Can you clarify and we have a properly adjusted version of the original decimal mantissa in the integer accumulator. What is the integer accumulator? You mentioned converting exponent to binary, then with IEEE-754 accumulator convert the "decimal mantisa" to an integer by also adjusting the exponent but never mentioned integer accumulator. Sorry if I misunderstood you. \$\endgroup\$ – Andres Oct 12 '13 at 4:48
  • \$\begingroup\$ Sorry about that. I've added a clarification to the second paragraph. \$\endgroup\$ – Dave Tweed Oct 12 '13 at 4:56
  • \$\begingroup\$ Thank you! So, I have to create at least a big register to hold the final number which can be very big. In the max value of IEEE I will need a 128bit register. Do you know of any way to directly do the conversion using the exponent instead of applying the exponent to the number? \$\endgroup\$ – Andres Oct 12 '13 at 14:19
  • \$\begingroup\$ No, a single-precision IEEE-754 number is always exactly 32 bits. The "integer accumulator" needs to be 8 bits and the "IEEE-754 accumulator" needs to be 32 bits. If you're doing double-precision, use 12 bits and 64 bits, respectively. \$\endgroup\$ – Dave Tweed Oct 12 '13 at 17:05
  • \$\begingroup\$ I think there is something I am not understanding. The final step is to look at the integer accumulator. If it is positive, you go into a loop that multiplies the IEEE-754 accumulator by 10 and decrements the integer accumulator until it reaches zero that means in this case I would multiply 22523 x 10, 17 times, that number will require 71 bits to be stored and THEN I have to start converting that to IEEE. Am I right? \$\endgroup\$ – Andres Oct 12 '13 at 17:47
0
\$\begingroup\$

You need to keep the mantissa and the exponent separate for as long as possible.

22.523 = 22523 x 10^-3, so 22.523x10^20 is 22523x10^17.

So the conversion of the mantissa is pretty much like any conversion of base 10 to base 2 integers, but you just need to record when you see the decimal point, and how many digits come after the decimal point.

mantissa    = 0
in_fraction = false
denominator = 0
while (more input):
  if (no more mantissa (i.e. you see a non-digit)):
    break
  if (next_character is a "."):
    in_fraction = true
    continue
  mantissa = mantissa * 10 + next_digit
  if (in_fraction):
    denominator = denominator + 1

now read the exponent
exponent = exponent - denominator
now follow the rest of the algorithm (which is the really hard part)

The really hard part is that the mantissa is a fraction with some power of 5s and 2s in the denominator. When you try to accurately approximate the fraction with a fraction with just a power of 2 denominator you sometimes have to do the long division.

The classic paper that showed how to deal with the roundoff of dividing by 5 is William D. Clinger, "How to read floating point numbers accurately", Proc ACM Conf on Prog Lang Dsgn and Impl, (PLDI):92-101, 1990. If I remember correctly he gives some optimizations that sometimes allow you to get away without doing the many-digit arithmetic.

\$\endgroup\$
  • \$\begingroup\$ Thank you! Yes the hard part is to implement what I read here: madirish.net/240. But with your method I only get the entire part with the exponent, and I can't find information about how to convert a number with exponent I only find information about converting decimal numbers without exponent (ie 327.8 not 0.3278 x 10^3). That's because I was converting the number to a number with no exponent. \$\endgroup\$ – Andres Oct 12 '13 at 1:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.