# How to properly match bit growth of a FIR filter with a reference value

I am trying to implement a chain of CIC/FIR filters on an ZYNQ FPGA. Using the Xilinx FIR compiler works fine so far but I am unable to properly get all the math.

At the moment I have 2 chains of filters:

• $5\times$ downsampling, passband $12.5\text{MHz}$:
→ FIR filter 2, 5x downsampling, input 17.7.0, output 17.7

• $625\times$ downsampling, passband $100\text{kHz}$:

→ CIC filter, $25\times$ downsampling, input 14 bit, output 16 bit

→ Compensation FIR filter, no downsampling, input 17.7, output 17.7

→ FIR filter 1, $5\times$ downsampling, input 17.7.0, output 17.7

→ FIR filter 2, $5\times$ downsampling, input 17.7.0, output 17.7

I have a 14 bit, $20\text{kHz}$ signal that I feed into both chains:

• If I feed it into the first chain I sign extend the 14bit value to 17bits and add 7 zero-bits at the end (.7). I get a nice output that wins me one bit.

• If I feed the signal into the second chain I directly feed the 14bit signal into the CIC filter and left-shift the output signal to only keep the 16 MSBs. I then sign extend that 16bit value to 17bit (yes I could have also just kept the first 17bits of the CIC return value, if that would be better, please tell me) and add 7 zero-bits at the end (.7) as well. The filters win me 1-2 bit until the output of the "FIR filter 1" but at the output of the "FIR filter 2" I have an output where I lost 8bit (upper 8 non-sign bits are 0). This is the exact same FIR filter that gives me +1 bit in the first ($5\times$ downsampling) chain ... This broken chain also seems to have a lot of jitter after one period ... (I can exclude overflows as the source of error as the Xilinx FIR compiler guarantees no overflows).

How can this be, what am I missing?

In the same question I would like to ask:

Let's assume all the chains finally work properly. I then will have different bit growth. Initially I knew that 14bit correspond to $2.2\text{Vpp}$ which means that 12.86bits correspond to $1\text{V}$. But now I suddenly have a 17.7bit output. How do I know where my $1\text{V}$ reference level is now? Because it has shifted some. I am quite sure that accounting just for the DC gain yields wrong results.

# My waveforms:

Output $5\times$ chain:

Chain $625\times$:

• Did you design the CIC filter or is it a Xilinx core? Do you use rounding before truncating the data? – Ben Jul 28 '17 at 13:26
• Yes it is a CIC filter created with the Xilinx core. I do not use rounding before truncating the data. Also what would that have an impact on? I would assume that woul maximally influence one bit or am I wrong? – Yatekii Jul 28 '17 at 15:55
• You should always round before truncating. Otherwise you can introduce a DC offset. Second of all, keep track of all the gains of your filter, ok? Keep track of which bits are guard bits (bits to prevent overflow so you can saturate instead), which bits are fractionnal, assuming your original is all integer. Can you send me a link to your filter cores? – Ben Jul 28 '17 at 15:59
• Hmm ok so I need to round properly everywhere (have to figure out how I do that best, but that's doable). Yes, keeping track of the gain and how I apply it properly is my problem I am trying to solve :-) Sure I can hook you up with my Vivado project (I have one for sim purposes without any processing system), I will just have to make it ready as I use a custom core to multiplex, which I have to put at a proper place, so it works for you too with the IP repos :) – Yatekii Jul 28 '17 at 17:28
• Pretty sure that there is a rounding option in the Xilinx cores. At least with Altera, you can do it. – Ben Jul 28 '17 at 17:33