CIC Decimation Filter "zero crossing" distortion

Started by JC April 13, 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 % 2 cascades 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 % 3 cascades 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. Any suggestions or comments?
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:

>Any suggestions or comments?
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