Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

floating point multiplier

0 views
Skip to first unread message

niyander

unread,
Sep 30, 2009, 5:02:32 PM9/30/09
to

hello,

can any one tell me how a 32-bit single precision floating point
multiplier works.
actually i am designing a FPU using VHDL so need to know exact working
of it.

i would appreciate if some one can tell me through an example.

thanks

BGB / cr88192

unread,
Oct 1, 2009, 4:11:28 AM10/1/09
to

"niyander" <mightyca...@MUNGED.microcosmotalk.com> wrote in message
news:4ac3c768$0$5653$9a6e...@unlimited.newshosting.com...

IEEE 754 is advised for this...


but, anyways, S.Exponent.Significand=1.8.23, with an exponent bias of 127.


but, anyways, here is a simple example:
assume that the significand is a normalized fixed-point number.

so, 23 bits are present, but if normalized, there is an extra bit which is
implied;
if the exponent is 0 (literal, -127 biased), then the value is very small,
and this extra bit is 0 (and the value may be denormal). for other
exponents, this bit is 1 and the value is normalized.

so, assuming the normalized case, then we can extract the low 23 bits, set
bit 23 to 1, and the upper 8 bits to 0.

say, we do this for 2 floats (f and g), giving us i and j.

at this point, good old fixed point can be used:
k=(i*j)>>23;
or, for slightly better rounding:
k=(i*j+0x3FFFFF)>>23;
or for slightly simpler:
k=(i*j+0x400000)>>23;

now, what do we know of k?
its range is 0x800000-0x1FFFFFC (or approx 1.0 to 4.0).


now, as one may recal:
(a*2^x) * (b*2^y) = a*b * 2^(x+y)

so, we extract the 2 prior exponents, say we call them x and y.

z=x+y;
but, note the bias, and so to compensate, one can add -2*127, or -254
z=x+y-254;

now, note k, we want k to be normalized, thus:
if(k&0x1000000)
{ k>>=1; z++; }

and, as well:
if(z>255) return(Inf);
if(z<=0) return(0); //fudge case: small values just become 0...

(note, supporting denormals is possible, and may be more proper, just I
don't feel like dealing with this issue here...).


now, there are the signs, but this is trivial enough:
u=s^t; (or 's xor t', in this case).

note, example, xor:
0^0=0
0^1=1
1^0=1
1^1=0
and:
1*1=1
1*(-1)=-1
(-1)*1=-1
(-1)*(-1)=1


now, we can compose a new float u.z.k (granted, only using the low 23 bits
from k).


note: I may be incorrect here somewhere, but maybe at least this is a
starting point...


or such...


> thanks


Tim Roberts

unread,
Oct 1, 2009, 4:12:48 AM10/1/09
to

At a high level, you xor the signs, add the exponents, multiply the
mantissas, and normalize the result. There's a rough outline in the
Wikipedia page on "single precision floating point".
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

niyander

unread,
Oct 1, 2009, 6:48:57 AM10/1/09
to

On Oct 1, 1:11=A0pm, "BGB / cr88192" <cr88...@MUNGED.microcosmotalk.com>
wrote:
> "niyander" <mightycatniyan...@MUNGED.microcosmotalk.com> wrote in message

>
> news:4ac3c768$0$5653$9a6e...@unlimited.newshosting.com...
>
>
>
> > hello,
>
> > can any one tell me how a 32-bit single precision floating point
> > multiplier works.
> > actually i am designing a FPU using VHDL so need to know exact working
> > of it.
>
> > i would appreciate if some one can tell me through an example.
>
> IEEE 754 is advised for this...
>
> but, anyways, S.Exponent.Significand=3D1.8.23, with an exponent bias of 1=

27.
>
> but, anyways, here is a simple example:
> assume that the significand is a normalized fixed-point number.
>
> so, 23 bits are present, but if normalized, there is an extra bit which i=
s
> implied;
> if the exponent is 0 (literal, -127 biased), then the value is very small=
,

> and this extra bit is 0 (and the value may be denormal). for other
> exponents, this bit is 1 and the value is normalized.
>
> so, assuming the normalized case, then we can extract the low 23 bits, se=
t

> bit 23 to 1, and the upper 8 bits to 0.
>
> say, we do this for 2 floats (f and g), giving us i and j.
>
> at this point, good old fixed point can be used:
> k=3D(i*j)>>23;

> or, for slightly better rounding:
> k=3D(i*j+0x3FFFFF)>>23;
> or for slightly simpler:
> k=3D(i*j+0x400000)>>23;

>
> now, what do we know of k?
> its range is 0x800000-0x1FFFFFC (or approx 1.0 to 4.0).
>
> now, as one may recal:
> (a*2^x) * (b*2^y) =3D a*b * 2^(x+y)

>
> so, we extract the 2 prior exponents, say we call them x and y.
>
> z=3Dx+y;

> but, note the bias, and so to compensate, one can add -2*127, or -254
> z=3Dx+y-254;

>
> now, note k, we want k to be normalized, thus:
> if(k&0x1000000)
> =A0 =A0 { k>>=3D1; z++; }

>
> and, as well:
> if(z>255) return(Inf);
> if(z<=3D0) return(0); =A0 =A0//fudge case: small values just become 0...

>
> (note, supporting denormals is possible, and may be more proper, just I
> don't feel like dealing with this issue here...).
>
> now, there are the signs, but this is trivial enough:
> u=3Ds^t; (or 's xor t', in this case).
>
> note, example, xor:
> 0^0=3D0
> 0^1=3D1
> 1^0=3D1
> 1^1=3D0
> and:
> 1*1=3D1
> 1*(-1)=3D-1
> (-1)*1=3D-1
> (-1)*(-1)=3D1
>
> now, we can compose a new float u.z.k (granted, only using the low 23 bit=
s

> from k).
>
> note: I may be incorrect here somewhere, but maybe at least this is a
> starting point...
>
> or such...
>
> > thanks
>
>

Thanks BGB Really appreciate that.

niyander

unread,
Oct 1, 2009, 6:49:31 AM10/1/09
to

On Oct 1, 1:12=A0pm, Tim Roberts <t...@MUNGED.microcosmotalk.com> wrote:

> niyander <mightycatniyan...@MUNGED.microcosmotalk.com> wrote:
>
> >can any one tell me how a 32-bit single precision floating point
> >multiplier works.
> >actually i am designing a FPU using VHDL so need to know exact working
> >of it.
>
> >i would appreciate if some one can tell me through an example.
>
> At a high level, you xor the signs, add the exponents, multiply the
> mantissas, and normalize the result. =A0There's a rough outline in the

> Wikipedia page on "single precision floating point".
> --
> Tim Roberts, t...@probo.com
> Providenza & Boekelheide, Inc.

Thanks Tim, i'll check it out on wikipedia.

Jerry Coffin

unread,
Oct 1, 2009, 11:48:06 AM10/1/09
to

In article <4ac3c768$0$5653$9a6e...@unlimited.newshosting.com>,
mightyca...@MUNGED.microcosmotalk.com says...

>
> hello,
>
> can any one tell me how a 32-bit single precision floating point
> multiplier works.

The simple answer is that it works like a 24-bit integer multiplier
and an 8-bit adder (assuming you split it as an 8-bit exponent and a
24-bit significand).

To get an idea of how that works, let's start with a _really_ simple
(and mostly useless) fixed-point format -- one with only 8 bits, all
after the decimal point. So, for example, we could represent .11
(hex) as 0x11, and .12 (hex) as 0x12. If we multiply those, we get
0x132. Now as we all know, if you multiply two-digit numbers, the
result can be up to four digits. Since this is all after the decimal
point, it means the result is really 0x0132 -- and all four digits
are after the decimal point. If we want to convert back to our
original format, we have to throw away the bottom byte, and keep only
the upper byte.

Now, consider extending that out to 16 bits instead of 8: we start
with 0x1100 and 0x1200, and our result is 0x01320000. This time to
get back to the original result, we keep the top 16 bits, and throw
away the bottom 16 (see a pattern starting to emerge?)

Now, let's think of a really simple floating point format: we'll take
that 16-bit number (still all after the decimal point), but add an 8-
bit exponent, so (for example) a value of 1 become a significand of
0x1000 (0.1 hex) and an exponent of 1. To multiply these numbers, we
have to multiply the significands, just like before, but also add the
exponents. We get the correct result, but instead of being .1 with an
exponent of 1, we get .01 with an exponent of 2. That's fine except
for one minor detail -- though it doesn't happen in this case, we
could lose some accuracy. If we kept multiplying this way, we'd keep
getting smaller and smaller significands with larger and large
exponents, until at some point our significand underflowed, and
(since in this case it has only one bit set) we were left with a
significand of 0.

We clearly don't want that; the cure is to normalize the number after
each operation -- shift the significand left until there's a digit in
the left-most position (and with each shift, subtract one from the
exponent, of course). Only after we've done that do we discard the
bottom bits of the result.

To implement something like that in assembly language, we could write
code something like this:

; warning: really just pseudo-code -- not tested.
.586P
.model flat, c

fp_num struc
significand dw ?
exponent db ?
fp_num ends

.data
a fp_num {01000h, 01h}
b fp_num {01000h, 01h}
res fp_num {0h, 0h}

.code
fp_mul proc
mov ebx, offset FLAT:a
mov esi, offset FLAT:b
mov edi, offset FLAT:res
assume ebx:ptr fp_num
assume esi:ptr fp_num
assume edi:ptr fp_num
movzx eax, [esi].significand
movzx ebx, [edi].significand
imul eax, ebx
mov cl, [esi].exponent
mov ch, [ebx].exponent
add cl, ch
normalize:
test eax, 0f0000000h
jnz done
shl eax, 4
dec cl
jmp normalize
done:
shr eax, 16
mov [edi].significand, ax
mov [edi].exponent, cl
ret
fp_mul endp
end

Now, as it stands this is hexadecimal floating point -- i.e. a '1' in
the exponent means one hexadecimal digit. I used that mostly because
it's easy when you're writing the numbers in hexadecimal. In reality,
you probably want to use binary floating point like everybody else
(though IBM mainframes have done hexadecimal FP for decades). As far
as the code above goes, about all that means is that when you're
normalizing you only shift left one bit at a time instead of four,
and you test for a value of 80000000h instead of 0f0000000h. Of
course, if you intended to really use this, you'd probably use BSR to
find how many bits of shifting were needed to normalize, and subtract
that from 16 to get the number of bits to shift right before storing
(i.e. combine the left shifts to normalize and the right shift prior
to storage into a single shift of the right distance). I haven't
messed with that, because in hardware you won't do it -- the final
"right shift" will be just a matter of connecting bits 47 downto 24
as your outputs.

There is one extra trick with binary though: since you're always
shifting left until there's a one in the MSB, you can take that MSB
for granted -- when you store your FP number, you don't bother
storing that bit, since it's always a 1. When you're going to operate
on a number, you hardwire the MSB to a one, and load the bits that
were stored into the bits below that.

Since you're working on FP multiplication you presumably already know
how to do integer multiplication (though, of course, I could be wrong
about that -- if so, just ask).

--
Later,
Jerry.

0 new messages