# CIC Decimation Filter "zero crossing" distortion

Started by April 12, 2018
```Hi,

I am designing a simple decimation filter, with decimation rate at 5 (1st stage) and 20 (2nd stage). N=2 and 3 for each stage. Bin=1. Bout=16. Input Sampling frequency at 50 KHz and output at 500 Hz.

The fixed point matlab simulation (2's complement) shows that with Sinewave input at 5Hz, there are a few "flat" "zero" crossing points in each sinewave cycle. I check the output of each integrator and differentiator stages. It looks like this is caused by the modulo function. When the output of the differentiator is too "negative", it got "round up" and get into the middle points, (which is the right way to do for 2's complement system.), therefore there are a few points that are instead of "following the sinewave curve", now are like a flat line.  The distortion appears at every wave cycle.

I wonder if anyone have seen this type of issue and any suggestions?

I would like to post a screen shot here, but didn't find a way yet. If anyone has any suggestions, please let me know.

Thank you very much!
JC
```
```On Thursday, April 12, 2018 at 6:39:28 PM UTC-7, JC wrote:
> Hi,
>
> I am designing a simple decimation filter, with decimation rate at 5 (1st stage) and 20 (2nd stage). N=2 and 3 for each stage. Bin=1. Bout=16. Input Sampling frequency at 50 KHz and output at 500 Hz.
>
> The fixed point matlab simulation (2's complement) shows that with Sinewave input at 5Hz, there are a few "flat" "zero" crossing points in each sinewave cycle. I check the output of each integrator and differentiator stages. It looks like this is caused by the modulo function. When the output of the differentiator is too "negative", it got "round up" and get into the middle points, (which is the right way to do for 2's complement system.), therefore there are a few points that are instead of "following the sinewave curve", now are like a flat line.  The distortion appears at every wave cycle.
>
> I wonder if anyone have seen this type of issue and any suggestions?
>
> I would like to post a screen shot here, but didn't find a way yet. If anyone has any suggestions, please let me know.
>
> Thank you very much!
> JC

BTW, the verilog simulation result also matches the matlab model, so it looks like the matlab model is doing its job. But the hardware is displaying this distortion because of the design. I wonder how to solve this issue.

Can anyone please tell me how to post a screenshot here since one picture is better than a thousand words?

Thank you!
```
```JC  <jingcao.cao@gmail.com> wrote:

>When the output of the differentiator is too "negative", it
>got "round up" and get into the middle points, (which is the right way
>to do for 2's complement system.),

I'm not quite sure what you're saying here, however in a CIC filter
as standardly implemented in 2's complement, there should be no rounding.
There should only be truncation, and when truncating, a value should
never become more positive.  The lower bits should be discarded without
further rounding.  So it's always "truncation towards negative infinity".

So, what you just wrote above sounds very suspicious.

Steve
```
```Hello JC.
I suggest you post your question on the 'DSPrelated.com Forum'. That way yo=
u can post images (screen shots.) And explain your question as *VERY* caref=
ully and completely as you are able.  For example, tell us what "N=3D2 and =
3 for each stage" means. (Remember, we can't read you mind.)
```
```On Thursday, April 12, 2018 at 8:46:06 PM UTC-7, Steve Pope wrote:

>
> I'm not quite sure what you're saying here, however in a CIC filter
> as standardly implemented in 2's complement, there should be no rounding.
> There should only be truncation, and when truncating, a value should
> never become more positive.  The lower bits should be discarded without
> further rounding.  So it's always "truncation towards negative infinity".
>
> So, what you just wrote above sounds very suspicious.
>
>
> Steve

Hi Steve,

Thank you very much for the reply. Indeed my original post is a very confusing and suspicious one, and I apologize for that. Let me try again here.

I am trying to design a decimation filter with decimation rate at 100 and bandwidth around 1Hz to 100Hz. Of course the exact bandwidth will be finalized by the following Low Pass and High Pass filters, but that's not the focus here. The required input bit (Bin) is 1 and the output bit (Bout) is 16.

Currently I have two cascade stages of CIC decimation filter to achieve this goal. The first stage of CIC filter has decimation rate at 5, with 2 integrators and 2 differentiators. Bin=1. Rdec1=6. Based on Hogenauer's paper, the bit widths for the 2 integrators are Rint1=[6 6], and the bit widths for the 2 differentiators are Rdif1=[6 6].

The second stage of CIC filter has decimation rate at 20, with 3 integrators and 3 differentiators. Bin=6. Bout=16. The bit widths for the 3 integrators are Rint2=[19 19 19], and the bit widths for the 3 differentiators are Rdif2=[19 19 18].

So the matlab code looks like this:

F0 = 5; %Input Sine wave frequency
FS = 50e3;              % Initial Sample Rate
Rint1 = [6 6];   		% Vector of register lengths for 1st stage integrators
Rdif1 = [6 6];   		% Vector of register lengths for 1st stage differentiators
M1 = [1 1];          	% Differential delay of differentiators
Rdec1 = 6;				% bit width of output of dec1

Rint2 = [19 19 19];   	% Vector of register lengths for 2nd stage integrators
Rdif2 = [19 19 18];   	% Vector of register lengths for 2nd stage differentiators
M2 = [1 1 1];          	% Differential delay of differentiators
Rdec2 = 16;				% bit width of output of dec2

OSR = [5 20] ; %Oversampling rate for each decimation stage

[x sd] = sd_mod(FS, 1e-3, F0, T); %sd_mod() is a first order sigma-delta modulator with a sinewave input

% Decimation Stage 1
int1_1 = integrator(FS, Rint1(1), sd);
int1_2 = integrator(FS, Rint1(2), int1_1);
% Decimation
d1 = downsample(int1_2, OSR(1), 0);
dif1_1 = comb(FS/OSR(1), Rdif1(1), M1(1), d1); % comb Function definition: y=comb(FS, nbits, M, x)
dif1_2 = comb(FS/OSR(1), Rdif1(1), M1(2), dif1_1);
dec1 = dif1_2;

%Decimation Stage 2
int2_1 = integrator(FS/OSR(1), Rint2(1), dec1);
int2_2 = integrator(FS/OSR(1), Rint2(2), int2_1);
int2_3 = integrator(FS/OSR(1), Rint2(3), int2_2);
% Decimation
d2 = downsample(int2_3, OSR(2), 0);
dif2_1 = comb(FS/prod(OSR(1:2)), Rdif2(1), M2(1), truncate(d2,Rint2(3)-Rdif2(1)));
dif2_2 = comb(FS/prod(OSR(1:2)), Rdif2(2), M2(2), truncate(dif2_1,Rdif2(1)-Rdif2(2)));
dif2_3 = comb(FS/prod(OSR(1:2)), Rdif2(3), M2(3), truncate(dif2_2,Rdif2(2)-Rdif2(3)));
dec2 = truncate(dif2_3,Rdif2(3)-Rdec2);

At each differentiator, the lower bits are truncated.

Function comb() goes like this:
function y = comb(FS, nbits, M, x)
y(1:M) = x(1) * ones(1,M);
for i = M+1:(length(x))
y(i) = x(i) - x(i-M);
y(i) = modulo(y(i), nbits);
end

Function x=modulo(x,nbits)
R = 2^nbits;
delta = 1;            %quantization step
x=fix(x);          %ensures only integers
nmax = R;
max_x = nmax-delta;
min_x = 0;
for i=1:length(x)
while x(i) > max_x
x(i) = x(i)- nmax;
end
while x(i) < min_x
x(i) = x(i)-(-nmax);
end
end

Here is the problem I have.
From lower-bits-truncated dif2_2 (refer to d22 here) to dif2_3 (refer to d23), at index 101,
d22(101)=61164, d22(102)=8127
so d23(102)= d22(102)-d22(101)=-53037
in 2's complement, through function modulo, the real output of d23 will be
-53037 + 2^16 = 12499
At index 103, d22(103) = 20628
so d23(103) = d22(103) - d22(102) = 12501

At index 104, d23(104) ends up with the same range of value around 12500.

So in this cycle of sinewave output, there are three points of almost flat line. The happens to every half cycle of the sinewave. Because the decimation filter gain is at 25000. After offset shifting, this looks like a zero-crossing distortion at each cycle.

Obviously in the real system, the input wave wouldn't be a perfect sinewave, and we rely on the hardware to detect all the waves with frequency in the passband and make decisions. I am concerned that this distortion will cause confusion in the system downstream.

```
```On Friday, April 13, 2018 at 12:56:01 AM UTC-7, Richard (Rick) Lyons wrote:
> Hello JC.
> I suggest you post your question on the 'DSPrelated.com Forum'. That way you can post images (screen shots.) And explain your question as *VERY* carefully and completely as you are able.  For example, tell us what "N=2 and 3 for each stage" means. (Remember, we can't read you mind.)

Hi Richard,

Thank you for the reply and I apologize for my original messy description. I re-worded my problems above and hopefully this time it's a bit clearer.

Thank you for pointing me to the DSPrelated forum. I will take a look over there too.

Thank you!
```
```JC  <jingcao.cao@gmail.com> wrote:

Yes, you modulo function also looks suspicious:

> Function x=modulo(x,nbits)
>         R = 2^nbits;
>         delta = 1;            %quantization step
>            x=fix(x);          %ensures only integers
>            nmax = R;
>            max_x = nmax-delta;
>            min_x = 0;
>            for i=1:length(x)
>                 while x(i) > max_x
>                       x(i) = x(i)- nmax;
>                 end
>                 while x(i) < min_x
>                       x(i) = x(i)-(-nmax);
>                 end
>            end

If x is a 2's complement integer, you would want, instead of the above,

max_x = 2^(nbits - 1) - 1

min_x = -2^(nbits - 1)

And you want to use floor() instead of fix() so as to
always truncate towards minus infinity.

Meta issue: over the long run you are better off using standard
fixed-point data types.  I prefer System C fixed point types.
For example your first stage integrators would be

sc_fixed<16, 16, SC_TRN, SC_WRAP>

If you generalize your modulo function to a general-purpose fixed
point function, which allows as arguments the total bits, integer bits,
and the most common rounding and saturation modes (basically SC_RND or
SC_TRN; and SC_WRAP or SC_SAT) then your code becomes clearer.

Hope this helps

Steve

```