'ARM'에 해당되는 글 3건

  1. 2006/12/18 Saturation arithmetic
  2. 2006/12/18 Binary Arithmetic
  3. 2006/12/17 Barrel shifter
From Wikipedia, the free encyclopedia

Saturation arithmetic is a version of arithmetic in which all operations such as addition and multiplication are limited to a fixed range between a minimum and maximum value. If the result of an operation is greater than the maximum it is set ("clamped") to the maximum, while if it is below the minimum it is clamped to the minimum. The name comes from how the value becomes "saturated" once it reaches the extreme values; further additions to a maximum or subtractions from a minimum will not change the result.

For example, if the valid range of values is from -100 to 100, the following operations produce the following values:

  • 60 + 43 = 100
  • (60 + 43) - 150 = -50
  • 43 - 150 = -100
  • 60 + (43 - 150) = -40
  • 10 × 11 = 100
  • 99 × 99 = 100
  • 30 × (5 - 1) = 100
  • 30×5 - 30×1 = 70

As can be seen from these examples, familiar properties like associativity and distributivity fail in saturation arithmetic. This makes it unpleasant to deal with in abstract mathematics, but it has an important role to play in digital hardware and algorithms.

Typically, early computer microprocessors did not implement integer arithmetic operations using saturation arithmetic; instead, they used the easier-to-implement modular arithmetic, in which values exceeding the maximum value "wrap around" to the minimum value, like the hours on a clock passing from 12 to 1. In hardware, modular arithmetic with a minimum of zero and a maximum of 2n can be implemented by simply discarding all but the lowest n bits.

However, although more difficult to implement, saturation arithmetic has numerous practical advantages. The result is as numerically close to the true answer as possible; it's considerably less surprising to get an answer of 127 instead of 130 than to get an answer of -126 instead of 130. It also enables overflow of additions and multiplications to be detected consistently without an overflow bit or excessive computation by simple comparison with the maximum or minimum value (provided the datum is not permitted to take on these values).

Additionally, saturation arithmetic enables efficient algorithms for many problems, particularly in signal processing. For example, adjusting the volume level of a sound signal can result in overflow, and saturation causes significantly less distortion to the sound than wrap-around. In the words of researchers G. A. Constantinides et al:

When adding two numbers using two’s complement representation, overflow results in a ‘wrap-around’ phenomenon. The result can be a catastrophic loss in signal-to-noise ratio in a DSP system. Signals in DSP designs are therefore usually either scaled appropriately to avoid overflow for all but the most extreme input vectors, or produced using saturation arithmetic components.[1]

Saturation arithmetic operations are available on many modern platforms, and in particular was one of the extensions made by the Intel MMX platform, specifically for such signal processing applications.

Saturation arithmetic for integers has also implemented in software for a number of programming languages including C, C++, Eiffel, and most notably Ada, which has built-in support for saturation arithmetic. This helps programmers anticipate and understand the effects of overflow better. On the other hand, saturation is challenging to implement efficiently in software on a machine with only modular arithmetic operations, since simple implementations require branches that create huge pipeline delays.

Although saturation arithmetic is less popular for integer arithmetic in hardware, the IEEE floating-point standard, the most popular abstraction for dealing with approximate real numbers, uses a form of saturation in which overflow is converted into "infinity" or "negative infinity", and any other operation on this result continues to produce the same value. This has the advantage over simple saturation that later operations which decrease the value will not end up producing a "reasonable" result, such as in the computation \sqrt{x^2-y^2}.

이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan

Binary Arithmetic

Development 2006/12/18 01:26

Table of contents

  • Addition
    • Unsigned
    • Signed
    • Fractions
  • Multiplying
    • Unsigned
    • Signed
    • Fractions

This document will introduce you to the methods for adding and multiplying binary numbers. In each section, the topic is developed by first considering the binary representation of unsigned numbers (which are the easiest to understand), followed by signed numbers and finishing with fractions (the hardest to understand). For the most part we will deal with

Addition

Adding unsigned numbers

Adding unsigned numbers in binary is quite easy. Recall that with 4 bit numbers we can represent numbers from 0 to 15. Addition is done exactly like adding decimal numbers, except that you have only two digits (0 and 1). The only number facts to remember are that

0+0 = 0, with no carry,
1+0 = 1, with no carry,
0+1 = 1, with no carry,
1+1 = 0, and you carry a 1.

so to add the numbers 0610=01102 and 0710=01112 (answer=1310=11012) we can write out the calculation (the results of any carry is shown along the top row, in italics).

Decimal Unsigned Binary
   1  (carry)
   06
  +07
   13
  110  (carry)
  0110
 +0111
  1101

The only difficulty adding unsigned numbers occurs when you add numbers that are too large. Consider 13+5.

Decimal Unsigned Binary
   0 (carry)
   13
  +05
   18
 1101 (carry)
  1101
 +0101
 10010

The result is a 5 bit number. So the carry bit from adding the two most significant bits represents a results that overflows (because the sum is too big to be represented with the same number of bits as the two addends).

Adding signed numbers

Adding signed numbers is not significantly different from adding unsigned numbers. Recall that signed 4 bit numbers (2's complement) can represent numbers between -8 and 7. To see how this addition works, consider three examples.

Decimal Signed Binary
 
   -2
   +3
    1
 1110 (carry)
  1110
 +0011
  0001
Decimal Signed Binary
 
   -5
   +3
   -2
 011  (carry)
  1011
 +0011
  1110
Decimal Signed Binary
 
   -4
   -3
   -7
 1100  (carry)
  1100
 +1101
  1001

In this case the extra carry from the most significant bit has no meaning. With signed numbers there are two ways to get an overflow -- if the result is greater than 7, or less than -8. Let's consider these occurrences now.

Decimal Signed Binary
 
    6
   +3
    9
  110  (carry)
  0110
 +0011
  1001
Decimal Signed Binary
 
   -7
   -3
  -10
 1001 (carry)
  1001
 +1101
  0110

Obviously both of these results are incorrect, but in this case overflow is harder to detect. But you can see that if two numbers with the same sign (either positive or negative) are added and the result has the opposite sign, an overflow has occurred.

Typically DSP's, including the 320C5x, can deal somewhat with this problem by using something called saturation arithmetic, in which results that result in overflow are replaced by either the most positive number (in this case 7) if the overflow is in the positive direction, or by the most negative number (-8) for overflows in the negative direction.


Adding fractions

There is no further difficult in adding two signed fractions, only the interpretation of the results differs. For instance consider addition of two Q3 numbers shown (compare to the example with two 4 bit signed numbers, above).

Decimal Fractional Binary
 
   -0.25
   +0.375
    0.125
 1110 (carry)
  1110
 +0011
  0001
Decimal Fractional Binary
 
   -0.625
   +0.375
   -0.25
  011  (carry)
  1011
 +0011
  1110
Decimal Fractional Binary
 
   -0.5
   -0.375
   -0.875
 1100  (carry)
  1100
 +1101
  1001

If you look carefully at these examples, you'll see that the binary representation and calculations are the same as before, only the decimal representation has changed. This is very useful because it means we can use the same circuitry for addition, regardless of the interpretation of the results.

Even the generation of overflows resulting in error conditions remains unchanged (again compare with above)

Decimal Fractional Binary
 
    0.75
   +0.375
    1.125
 110  (carry)
  0110
 +0011
  1001
Decimal Fractional Binary
 
   -0.875
   -0.375
   -1.25
 1001 (carry)
  1001
 +1101
  0110

Multiplication

Multiplying unsigned numbers

Multiplying unsigned numbers in binary is quite easy. Recall that with 4 bit numbers we can represent numbers from 0 to 15. Multiplication can be performed done exactly as with decimal numbers, except that you have only two digits (0 and 1). The only number facts to remember are that 0*1=0, and 1*1=1 (this is the same as a logical "and").

Multiplication is different than addition in that multiplication of an n bit number by an m bit number results in an n+m bit number. Let's take a look at an example where n=m=4 and the result is 8 bits

Decimal Binary
  10
  x6
  60
     1010
    x0110
     0000
    1010
   1010
 +0000    
  0111100
  

In this case the result was 7 bit, which can be extended to 8 bits by adding a 0 at the left. When multiplying larger numbers, the result will be 8 bits, with the leftmost set to 1, as shown.

Decimal Binary
   13
  x14
  182
     1101
    x1110
     0000
    1101
   1101
 +1101   
 10110110
  

As long as there are n+m bits for the result, there is no chance of overflow. For 2 four bit multiplicands, the largest possible product is 15*15=225, which can be represented in 8 bits.

Multiplying signed numbers

There are many methods to multiply 2's complement numbers. The easiest is to simply find the magnitude of the two multiplicands, multiply these together, and then use the original sign bits to determine the sign of the result. If the multiplicands had the same sign, the result must be positive, if the they had different signs, the result is negative. Multiplication by zero is a special case (the result is always zero, with no sign bit).

Multiplying fractions

As you might expect, the multiplication of fractions can be done in the same way as the multiplication of signed numbers. The magnitudes of the two multiplicands are multiplied, and the sign of the result is determined by the signs of the two multiplicands.

There are a couple of complications involved in using fractions. Although it is almost impossible to get an overflow (since the multiplicands and results usually have magnitude less than one), it is possible to get an overflow by multiplying -1x-1 since the result of this is +1, which cannot be represented by fixed point numbers.

The other difficulty is that multiplying two Q3 numbers, obviously results in a Q6 number, but we have 8 bits in our result (since we are multiplying two 4 bit numbers). This means that we end up with two bits to the left of the decimal point. These are sign extended, so that for positive numbers they are both zero, and for negative numbers they are both one. Consider the case of multiplying -1/2 by -1/2 (using the method from the textbook):

Decimal Fractional Binary
  -0.5
  x0.5 
  -0.25
      1100
     x0100
      0000
     0000
 +111100  
  11110000
 
  

This obviously presents a difficulty if we wanted to store the number in a Q3 result, because if we took just the 4 leftmost bits, we would end up with two sign bits. So what we'd like to do is shift the number to the left by one and then take the 4 leftmost bit. This leaves us with 1110 which is equal to -1/4, as expected.

On a 16 bit DSP two Q15 numbers are multiplied to get a Q30 number with two sign bits. On the 320C50 there are two ways to accomplish this. The first is to use the p-scaler immediately after the multiplier, or the postscaler after the accumulator. to shift the result to the left by one

이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan

Barrel shifter

Development 2006/12/17 01:44
From Wikipedia, the free encyclopedia

A barrel shifter is a digital circuit that can shift a data word by any number of bits in a single cycle. It is implemented as a sequence of multiplexors: the output of one MUX is connected to the input of the next MUX in a way that depends on the shift distance. The number of multiplexors required is n*log2(n), where n is the computer's register size. Four common word sizes and the number of multiplexors needed are listed below:
  • 64-bit -- 64 * log2(64) = 64 * 6 = 384
  • 32-bit -- 32 * log2(32) = 32 * 5 = 160
Take for example a four-bit barrel shifter, with inputs A, B, C, and D. The shifter can cyclically after the order of the bits ABCD. That is, it can 'shift' all of the outputs up to three positions to the right (and thus make any cyclic combiation of A, B, C, and D). The barrel shifter has a variety of applications, including being a vital component in microprocessors (alongside the ALU).

The barrel shifter is used in floating-point arithmetic hardware. For a floating-point and or subtract operation, the fractions of the numbers must be aligned, which requires shifting the smaller number (in magnitude) to the right, increasing its exponent, until it matches the exponent of the larger number. This is done by subtracting the exponents, and using the barrel shifter to shift the smaller number to the right by the difference, in one cycle. If a simple shifter were used, shifting by n bit positions would require n clock cycles.

Ref. University of Hamburg's Java Barrel shifter
이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Kyounghan