Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

Multiplication Rounding

Hey guys,

I am multiplying two 32 bit numbers using LPM_MULT. Each number is in Q16.16 fixed point format. The product is a 64 bit Q32.32 number. I then shift the product to the right by 16 bits to get a Q32.16 bit number. Now, I would like to round the number to get a Q16.16 bit number. Large inputs are possible, so the product needs to be rounded.

Does anyone know a simple and effective algorithm that could be implemented in Verilog? In my old rounding system I would simply divide by 65536. Since I am using Q16.16 format, I don't think it will work anymore.

17 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Firstly, the interpretation of a value on 64 bits is only a mental perspective. In the past most fpga engineers used the perspective of integer interpretation. Today and as result of software mindset invasion through their tools we have at times to shift between both concepts(integer or fractional).

    if you discard 32 lsbs off 64 bits then in effect you are dividing the whole result by 2^32. Rounding will give nearest value. You don't round in the middle of bits at the imagined fractional point. In short you better think of 64 bits here as integer only(no decimal point). You round the 32 bits and it is the duty of receiving module to interpret the decimal point.

    if your value is so small (relatively) that it only occupies 32 LSBs then you are going to get either 0 or 1 effect on the 32 MSBs. You then interpret that as 0.0 or 0.1/2^16 in Q16.16 format if next module is going to look at it that way.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Just some clarification,

    Lets say you have Q2.2 notation. You have two numbers:

    01.11=1.75

    x 10.00=2.00

    The product should be 3.50

    If I do the binary multiplication in my calculator I get a Q4.4 result:

    00111000

    Now I perform the rounding by adding P(3) to P(7:4) I get:

    0011+0001=0100

    If I'm interpreting this correctly, it appears that my 3.5 rounded to a 4. But, there isn't any fractional part of the number. The rounding forced the result to Q4.0. Instead of getting 11.10=3.5, I got 0100=4.

    Now if I didn't do any rounding at all and just performed a shift to the right to align the decimal point, I would get:

    00001110 = 000011.10 = 3.5

    Maybe I'm confusing the concept of rounding. I want to get a rounded value, but I still want to have a fractional value. If I perform this rounding without the shift, then the output 0100 will go throughout the rest of the system and get interpreted as 01.00=1, since the decimal point is aligned throughout the rest of the system.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Regarding shift idea, you don't need to think that way, just discard 32 LSBs. shift is applicable if you keep 64 bits and want to shift divide or shift multiply.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    It is much simpler than your thoughts.

    Rounding is done when you divide a value and in your case when you discard 32 bits. (= /2^32).

    you can either discard directly without any else since your datawidth is 32 bits. or you round up to nearest value.

    The issues of deimal point is matter of interpretation of value, nothing else.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks for the reply Kaz. My concern was that the fractional part would cause the product to be huge. For example, if you have 111.010=7.25, it can be interpreted as 111010=58. Performing a rounding on a rather small number like 7.25 with a fraction might be the same as performing the rounding on a large number. Basically, I'm afraid that such a rounding algorithm would cause small numbers to become rounded as large numbers.

    Another concern is whether I should even shift at all after multiplication. Anytime you multiply a number you get 2*N decimal places, where N is the number of decimal places in the inputs. Since I only want N precision, I would the product by the right by N bits to discard them. With the method you gave, do I even need to do this at all? Would it be better just to round only?

    I know this question may seem kind of stupid, but I'm still learing about fixed point for the first time.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Most basic rounding is:

    if your result is 64 bits then add result(31) to result(61 : 32)

    Alternatively add '1' to result(61:31) then take result(61:32)

    Thats all.