1
\$\begingroup\$

I'm having a bit of a hard time trying to get my head around binary radix's. Specifically when it comes to use them in a circuit. On their own I can understand them fine. For example, 2s complement, fixed point, BCD etc..

This is where I'm getting confused.

I've been building a FIR filter in VHDL and have come to the point where I have to implement the coefficients. Each coefficient is below 1 and is 9 bits. The numbers are signed fixed point numbers. The first 8 bits are the fractional part with the 9th bit the sign bit / integer bit.

Now my problem is: now that I have chosen a format (say, 8 bits for fractional part of the number), does that mean every other number I choose to input into the system have to follow the same radix? Fixed point with 8 fractional bits?

As what I'm being told is, when you input an impulse response to the filter the output should be each coefficient in order. When I use "0000000001" as the input then yes I do get each coefficient on the output. But I don't understand how. I understand that a '1' is getting clocked through each stage and being multiplied with each coefficient on each clock but it doesn't represent a "1" in the same format or radix as my coefficients. A true 1 would be "0100000000" as the first 8 bits are fractional.

I'm having a hard time getting my head around the number side of system, the structure and how it's supposed to work.

Is there something wrong with my understanding?

\$\endgroup\$
3
\$\begingroup\$

Let's suppose you have a coefficient and a signal input value. If the coefficient has \$F_C\$ fraction bits and the input has \$F_I\$ fraction bits then their product will have \$F_C + F_I \$ fraction bits. When you used 000000001 to represent the integer 1 you had implicitly set \$F_I = 0\$ so the products had the same format as the coefficients. If you use fixed-point values that are \$\ge 1.0\$ then you will need bits to the left of the binary point to represent the integer part of the value. As with the fraction bits, the number of integer bits in the product will equal the sum of the numbers of integer bits in the multiplier and multiplicand.

When you add fixed-point values they must have the same number of fraction bits (i.e. the binary point is aligned) and the sum will have the same number of fraction bits as the addends. If you don't have information about the actual range of values for the sum then you need to assume that a carry can occur, so you need an additional bit to the left of the binary point to represent the integer part of the number. That is, you need one more integer bit in the sum than the maximum number of integer bits in either of the addends.

\$\endgroup\$
  • \$\begingroup\$ Thanks Joe, so I understand now about how I've implicitly set to 0 fraction bits. So I understand that you do not need your inputs to be the same format as other numbers in the system as long as the output format is correct. So that means to be able to properly use the device you need to know where the decimnal point is on its internal numbers (coeefecients in this case) to know how to read the output? Is this information given on the data sheets ? How do you know what format the device works with? \$\endgroup\$ – binarysmacker May 2 '14 at 18:12
  • \$\begingroup\$ When doing signal processing you can usually assume whatever you like about the number of fraction bits in the digitized value from an A/D converter. There's nothing in the physical hardware that determines the format of the data. As long as the filter is linear then it really doesn't matter. \$\endgroup\$ – Joe Hass May 2 '14 at 18:17
  • \$\begingroup\$ What I mean is. The filter I've designed, the coefficients are hard coded in VHDL and I've decided on 9 bits with 8 fractional bits. If I was to give this filter to someone to use, they would not know how to read the output without knowing the format the coefficients are in? Due to needing to know how many fractional bits there are as the fractional bits add up in the output as you explained. \$\endgroup\$ – binarysmacker May 2 '14 at 18:21
  • \$\begingroup\$ Yes, when you design using fixed-point arithmetic it is vital that you document the design very well so that someone else can understand what you did. That includes specifying the format for the output values. However, for linear filters this is usually only important if you want to compare results between fixed-point and floating-point versions. \$\endgroup\$ – Joe Hass May 2 '14 at 19:15
2
\$\begingroup\$

"A true 1 would be "0100000000" as the first 8 bits are fractional..": As your numbers are 8bit fractional + sign (a.k.a Q0.8 format where the Q denotes signed), a true 1 cannot be represented. The number range is 1-1LSB to -1 (where 1LSB means the numeric value of one least significant bit). i.e. the max fullscale range is 011111111 to 100000000 . "0100000000" = 1/2 in this system.

When you use "0000000001" as the input then your output will be the impulse response of the FIR filter [say h(n)] multiplied by 1LSB. i.e. h(n)*2^-8 . Therefore it should be a scaled version of h(n).

To directly answer your question, you do not need to keep the bitwidths the same. Normally in DSP processor filter design you do because the bitwidths are determined by the DSP processor designer in advance. In ASICs/FPGAs you have the freedom to do as you please. But the most important thing is to align the fractional point so that fullscale in = fullscale out.

To achieve this alignment of the binary point you need to remember that multiplying a Q0.8 number by a Q0.8 number is a Q0.16 number so you have 8 extra LSBs, i.e. you LEFT ALIGN fractional numbers at the binary point insering extra Zero-Lsbs on the right as appropriate.

For example in integer maths the product of 0010, 0010 = 0100 in Q0.2 maths 0.10 x 0.10 = 0.0100 i.e. the answer has been filled out with extra bits to the right so in VHDL your input would require a zero-fill on the right to the same level.

But the main issue with scaling in filters is actually the maximum fullscale signal that you could get at the output. For a worst case analysis you would use the L1 norm which is simply the sum of the absolute value of the impulse response for a fullscale input (e.g. h={0.2, -0.5, 1.0, -0.5, 0.2} L1 = 0.2+0.5+1+0.5+0.2= 2.4 which means that the output max value can be 2.4 tiles the input max value worst case.

To deal with that you need to add 3 more bits to the magnitude (sign,3 bits.8 frac bits) or divide all coefficient by 2.4.

\$\endgroup\$
  • \$\begingroup\$ My coefficients are 8 bits plus sign. The input is 10 bits. So the input is able to represent a true 1 as I've said but not the coefficients? \$\endgroup\$ – binarysmacker May 2 '14 at 18:15
1
\$\begingroup\$

You don't have to use the same representation for every operand. Your coefficients may be normalized, but your input samples can be a different range/precision - it's up to you (more or less) to define where the binary point is. If your input is an 8-bit integer, then a "true 1" is "00000001". Maybe you want your input to be 0000.0000 instead (smaller range, more precision - it might help to write the binary point to visualize how the math works), in which case a 1 is "00010000". Either way, the number of fractional bits you get out depends on how many you put in (8 from your coefficient, and however many from your samples).

\$\endgroup\$
  • \$\begingroup\$ So to know how to read the output of a system you need to know the format of the numbers that are hardcoded inside it (and the format of your input). How is that information represented/what does it come under? Is it on the data sheets? \$\endgroup\$ – binarysmacker May 2 '14 at 18:17

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.