Jump to content
  • 0

Magnitude issue when designing low-pass filter with FIR Compiler


Yannick

Question

Hello,

I'm building this filter, generating a .COE file in Matlab, which I use in the FIR compiler IP. Here are two screenshots of the settings. Do you know if the difference between the two pictures, in terms of magnitude, are just a displaying fact or if there is a real amlpification involved by the FIR compiler ? If it's the case, do you know how to fix it to generate the same filter as I designed in Matlab, so without gain ? 

Kind regards, 

 

Yannick

 

 

Matlab filter.png

vivado filter.png

Link to comment
Share on other sites

8 answers to this question

Recommended Posts

  • 0

@Yannick,

Looks good to me!

When doing digital signal processing, you really want to plan to use the highest gain that your processing will support.  Using integer math, a lowpass filter gain of 0dB means you have an allpass filter--not what you designed.  In order to maintain your performance, the coefficients had to be turned into integers.  What you should be looking for at this point is that the stop band remains as you would like it.  Since it remains at about 40dB, I'd say it's about as good as the original.  (You sure you only want 40dB?  I was always taught 70dB as a rule of thumb ...)

To know how much this filter will "amplify" your incoming signal, just add all the coefficients together.  (Works for lowpass filters ...)

As for how to make certain you aren't "amplifying" your signal, you sort of need to define what truth is in order to compare against it.  Is it 12-bit resolution you want?  Then after a filter, you may need to drop the lower bits to get back to 12.  However, the devil is in the details in order to make certain that you maintain your 12-bit range throughout your processing chain.  To handle things properly, you'll want to make certain that the constant 12'h800 and 12'h7ff signals pass through your processing chain (filter plus whatever else you will be doing to them) and turning into 12'h800 and 12'h7ff signals at the far end --- without overflowing any of the math in the middle.

Dan

Link to comment
Share on other sites

  • 0

@D@n,

Okay, I understand some points ! But, I'm not sure to have well understood how to know the amplitude of the filter output.

In the both cases here, I have 2 sine wave generated by a DDS, in unit circle mode which means, the range is [-0.5 ; 0.5]. Then, the two signals are multiplied. It gives me the signal called "result" with a [0 ; 1] range. Finally, this signal is low pass filtered (cut off frequency of the filter is 100 kHz) and I obtain this value on 40 bits which I don't understand. I don't know how to interpret it. 

Picture 1 : the 2 sine waves have a frequency of 100 kHz each

Picture 2 : the 2 sine waves have a frequency of 20 kHz each

100.png

20.png

Edited by Yannick
Link to comment
Share on other sites

  • 0

@Yannick,

Not quite sure what problem you are having as the plots look good from here.  (I can't read the scale, though, on those images ...)

  1. In chart one, you create two 100 kHz signals and multiply them together.  That will create a signal near DC, and a signal at 200 kHz.  200kHz is significantly above your filter cutoff, so ... it's gone.  That leaves you with the signal near DC.  (I assume you are sampling in the MHz range still ...)  The fact that the signal near DC is not constant could be just a transient effect of your filter ... from here and with no more details I can't tell.
  2. In the second chart, the two 20kHz signals multiplied together create a signal at 40 kHz and one near zero again.  (If this doesn't make sense, work the double angle trig formulas and it should)  The 40kHz signal component is quite obvious on the chart.  Since 40kHz is below your cutoff, it passes right through without a problem.  You can also see an initial startup transient, much like I would expect.

I would also expect the startup transients for your filter to be the same length--both for the DC transient as well as for the 40 kHz transient.  I can't tell from your charts if there's a difference between the two transients -- since the two charts are on different time-scales.

Going back to your explanation above, I'm not sure it makes sense.  Ignoring the fixed point issues, a DDS should produce a sinewave between -1 and 1, not -1/2 and 1/2.  Second, multiplying two sinwaves together should produce a value that is also between -1 and 1.  Now if you add the fixed point issues back in, you'll need to multiply all of your numbers by 2^(N-1)-1 so that they will fit in an N bit number.  Hence, your DDS output should be between -2^(N-1)+1 and 2^(N-1)-1.  If you assume all your inputs have N bits, then multiplying your two values should then give you a result that fits in 2N bits.  (It won't quite use up the whole range ... [2^(N-1)-1]^2 is 2^(2N-2)-2^(N-1)+1 ...)  If you then run this though a filter having coefficients of N bits, your result will increase from 2N bits to 2N plus the number of bits in your filter taps, so in this example you'd end up with 3N bits for the multiply alone (neglecting the additional base two logarithm of your filter length for the accumulator portion of the FIR).  If your coefficients have 2N bits each, your result goes from 2N to 4N bits, etc. I'm not sure where in this sequence you would get either a [-1/2,1/2] range or a [0,1] range.

Dan

Link to comment
Share on other sites

  • 0
34 minutes ago, D@n said:

Not quite sure what problem you are having as the plots look good from here.  (I can't read the scale, though, on those images ...)

  1. In chart one, you create two 100 kHz signals and multiply them together.  That will create a signal near DC, and a signal at 200 kHz.  200kHz is significantly above your filter cutoff, so ... it's gone.  That leaves you with the signal near DC.  (I assume you are sampling in the MHz range still ...)  The fact that the signal near DC is not constant could be just a transient effect of your filter ... from here and with no more details I can't tell.
  2. In the second chart, the two 20kHz signals multiplied together create a signal at 40 kHz and one near zero again.  (If this doesn't make sense, work the double angle trig formulas and it should)  The 40kHz signal component is quite obvious on the chart.  Since 40kHz is below your cutoff, it passes right through without a problem.  You can also see an initial startup transient, much like I would expect.

@D@n

 

I am totally agree with your explanations and the simulation shows exactly what I was expecting, of course. 

 

34 minutes ago, D@n said:

Going back to your explanation above, I'm not sure it makes sense.  Ignoring the fixed point issues, a DDS should produce a sinewave between -1 and 1, not -1/2 and 1/2. 

Yes, I believed that it was between -1 and 1 but when I read this (picture 1), I made the conclusion of the [-1/2 ; 1/2] range. I'm probably totally wrong (probably a misunderstanding as english is not my native language as you probably guessed ^^). 

 

34 minutes ago, D@n said:

If your coefficients have 2N bits each, your result goes from 2N to 4N bits, etc.

My coefficients have 16 bits and the result of the multiplication as well, however the output width calculated by the FIR is 36 bits (picture 2) and finally, 40 bits as it is shown in the previous pictures of simulations (as it has to be a multiple of 8 if I well understood).

 

My main question was how to interpret this 40 bits vector, so if I  follow your reasoning, in the first case where the signal is filtered, the amplitude of the output near DC is 0 ? 

Besides, why do I have negative values with this 40bits vector ? 

amplitude mode.png

32 bits.png

Edited by Yannick
Link to comment
Share on other sites

  • 0

@Yannick,

FPGA's can't represent fractions.  Looking at your pictures above, you have 8-bit values coming out of your DDS.  Hence, the range of these values should be (at most) between -128 and 127.  According to the "unit circle" description above, 8-bit numbers are clipped to being between -64 and +64.  (There really isn't any +/- 0.5 within an FPGA, but one might think of these values are representing +/- 0.5, since they are nearly half of their full range.)

Multiplying two such values together should give you something in the range of -4096 and 4096 (you might think of this as -0.25 to 0.25).  Although this could fit into 14 bits, you've got it in 16.  Not a problem, just unused capacity.  Moving on ...

If your coefficients are 16-bits, then they should have values between +/- 32767 (ignoring -32768 for now).  Multiplying your 16 bit value with a 16-bit coefficient nominally gives you a 32-bit value.  (You are only using 14 bits, so you could spare a bit or two here if necessary ...)  If you have 16 such coefficients, log_2(16)=4, so adding the results of these multiplies together might give you an additional 4 bits, bringing you to 36 bits.  If you instead had 256 such coefficients, log_2(256)=8, so adding the result of the multiplies together would give you an additional 8 bits instead, bringing you to 40 bits.

At this point, you are getting some really HUGE numbers.  You and I both know that your signal isn't that big.  How do you get back to what your signal was?  To do that, you have to track the bit math and the multiplies.  If you decide that you started with +/- 0.5 numbers, scaled by 2^7, then your next step left you with +/- 0.25 numbers scaled by 2^14 ... and so on.  The reality, though, is you really don't have that many bits.  You really only have about 8-bits of information, packed tightly into 40 bits.  (Or ... not so tightly :P )  At this point, you need to drop some bits.  Well, actually, you should've dropped the bits agressively as you went along--but that's more of a logic is precious comment, rather than a how it must be done comment.  You can figure out how many bits to drop by tracking the maximum value and the standard deviation of any noise working its way through your system.

How do you go about shedding such bits?  My first approach to doing so was to just drop the low order bits.  While doable, this will introduce a DC bias into your result.  (I had to dig into this when building my own FFT ...)  The solution I found was convergent rounding ... but I'll let you look that one up.

Dan

P.S. ... I hadn't noticed that English wasn't your native language ;)

Link to comment
Share on other sites

  • 0

@Yannick  @D@n What I have done is took 2 dds and multiplied the outputs and fed it to fir compiler. The block design done is as in the figure. Then I created a hdl wrapper and tried simulating it..but its showing error as "design ()not found while processing module instance()" . Could you pease help me through this.

Screenshot 2021-07-06 133215.jpg

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...