Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
18 years ago

Periodic artifacts on output of IIR Filter

Hi,

I'm trying to create a 2nd order IIR filter based on a Direct Form I biquad. I've implemented a LP filter at 1000 Hz with pre-calculated butterworth co-efficients. The filter works, but i can see periodic artifacts every 200 samples or so on the output. Otherwise the output signal looks fine on the scope.

I've got two theories:

- The co-efficients are in-correctly calculated (rounding or quantization problems)

- Rounding errors within the feedback loop, when the 64-bit accumulator result is truncated to 32-bit.

Would the periodic nature of the problem be consistent with either of these theories?

I've played around with the rounding of the co-efficients and nothing has seemed to help. I've also tried to do some rounding by adding 1 to the result y[n] if the truncated bits were greater than 0.5. I've attached a picture of my setup in block diagram.

I have used signed (2's complement) fixed integers of 16.16 format for the 16-bit audio samples and the filter co-efficients.

I've calculated my co-efficients in Octave(Matlab), following this helpful tutorial:

http://www.planetanalog.com/showarticle.jhtml?articleid=12802683

Thanks in advance, Evan.

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello,

    you don't describe the "artifacts" in detail. Are this low amplitude "limit cycles"? Basically, the filter must have some resolution extra internally to be accurate up to the resolution of input/output signal. If so, and with appriorate rounding at the ouput, limit cycles should disappear at the output. I noticed, that the referenced literature isn't discussing quantization effects in filter design, also in Matlab or Octave simulation, they would be ignored unless you particularly simulate fixed point arithmetics. For an exact simulation of quantization noise, overflow, and possible limit cycles or even dynamic instability this would be necessary.

    I also don't understand exactly, how you scale input signal respectively how you handle possible overflows when truncating the multiply results. What's nominal full scale signal with your 16.16 format, how do you scale 16 or 24 bit digital audio to it? generally, in a filter, the signal amplitude can appear magnified at some nodes. You have to assure, that the signal isn't truncated with any arbitrary full scale input anyway. Thus some headroom must be granted in signal scaling. On the other hand the said resolution extra could be lost when scaling the input too low.

    Regards,

    Frank
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Make sure results(63 downto 48) are either all F's or all 0's. If not, you have a problem.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello,

    --- Quote Start ---

    Make sure results(63 downto 48) are either all F's or all 0's. If not, you have a problem.

    --- Quote End ---

    that's true, but I guess, the said "artifacts" are rather limit cycles visible at the output cause the input/output signal is scaled too low. Without additional fractional bits in internal processing, such quantization effects can't be avoided. Also rounding rather than truncation at the output is necessary, when toggling of least significant bits respectively sign is unwanted. When discarding most significant bits, as with the said bit 48 to 63, saturation logic is a must, unless you can't be absolutely sure, that no overflow can occur.

    A good method, to keep the code readable anyway is to use a function for saturation and truncation of multiply output, here with configurable shift for scaling purposes. With the normalized 16.16 format, that shift factor should be 16:

    FUNCTION MUL_ASL (X1,X2: SIGNED; N: INTEGER) RETURN SIGNED IS
    VARIABLE P:SIGNED(X1'length+X2'length-1 downto 0);
    BEGIN
      P:=X1*X2;
      IF P(P'left-1 downto P'left-N) /= 0 AND P>=0 THEN
        P:= (others => '1');
        P(P'left-N):='0';
      ELSIF P(P'left-1 downto P'left-N) /= -1 AND P<0 THEN
        P:= (others => '0');
        P(P'left-N):='1';
      END IF;	
    -- Result length equal to X2
      RETURN P(P'left-N downto X1'length-N);
    END;

    Regards,

    Frank
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks for the replies.

    Well as it turns out it was nothing to do with the filter at all. I had a state machine that would start the filtering when a new sample was ready. This signal, new_sample_ready was generated in the audio clock domain and received in the system clock domain. I forgot to implement a synchronizer to cross the domains (stupid mistake.) This may explain why they were periodic in nature as well.

    To answer your question question about scaling, i receive a 16-bit sample from the ADC and shift it up 16-bits before multiplying it with my 16.16 fixed point values. So 31 downto 16 is audio and 15 downto 0 is left as 0's (i.e. fraction part of 0).

    The value (63 downto 48) is always FFFF or 0. I wouldn't think the co-efficients are big enough for this overflow (there typically less than +/-4) and the filter has slightly less than 0db gain overall.

    Thanks for your advice on saturation and truncation. I will look into rounding the multiplier output with saturation instead of just truncation.

    Cheers, Evan.