LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

exponentially weighted moving average on FPGA

Hey guys,

 

I am looking for an example of an exponentially weighted moving average filter for FPGA.

I know the DFD kit, but you can't change the coefficients on the run of the FPGA code. Therefor I want to build it on my own or use an already existing example.

 

If anyone has one or any advices, please let me know.

 

Kind regards

 

Slev1n

0 Kudos
Message 1 of 11
(6,759 Views)

According to wikipedia:

https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average

 

You can calculate the exponential moving average as follows.

S[t] = a*Y[t] + (1-a)S[t-1]

 

This can be done with simple maths and a feedback node on an FPGA (I haven't bothered to sort out the FXP word lengths in the snippet below).

 

 MA.png

Message 2 of 11
(6,715 Views)

I think your formula is not completly correct.

 

 I build my own but as my input is a 64Bit integer coming from a CIC filter I had to use SGL in the end.

 

How would you change the Integer into FXP?

 

kind regards

Slev1n

0 Kudos
Message 3 of 11
(6,647 Views)

Ok, here is my FIX point version of an EWMA. Input 32bit output 32bit. If the stage is 2 the data is running thorugh the filter 2 times and therefor you double your attenuation.

 

Can someone of you approximate the error I am creating?

(The input is a 64bit integer which can be presented with 32Bits, you can check the explanaition to it)

 

kind regards

 

Slev1n

0 Kudos
Message 4 of 11
(6,627 Views)

Ok,

 

I want to simulate the frequency response of this filter.

 

from y[n] = alpha *x[n] + (1-alpha)*y[n-1] I come to H(w)=alpha+(1-alpha)*e^(-jw) but now I dont know how to get rid of the complex part to get a non complex function of the amplitude of the frequency response like this one: |H(w)| = [sin(w*M/2)/M*sin(w/2)] (moving average).

 

Can you guys give me a hint?

 

Slev1n

 

 

0 Kudos
Message 5 of 11
(6,558 Views)

I just derived the frequency response of the EWMA:

 

|H(w)|= alpha / sqrt(1²-2*1*(1-alpha)*cos(w/fs)+(1-alpha)²)

 

I plotted it with MATLAB for alpha=0.5:

Frequenzgang EWMA.PNG

 

You can find my fix point version attached to this file. I have problems with the stability. The result sometimes jumps between two values...

Can someone find the mistake? I think it has something to do with the conversions...

 

kind regards

Slev1n

0 Kudos
Message 6 of 11
(6,499 Views)

Hi Slev1n,

 

It would be easier to debug this with a testbench that provides a data set to reproduce the jumps you're seeing. Here's a few suggestions:

 

  1. The conversion from 36,2 to 36,1 at the output corresponds to a divide by 2--is that really what you want to happen there? To reduce the IWL at that point, I'm guessing you could just throw away the top bit without overflowing (ie, configure the Add with an output type of 35,1 in Wrap mode). You might want to start with Saturate mode until you can convince yourself that there will be no overflows. Monitoring the overflow output is helpful when developing algorithms like this--you can always get rid of it later when you're confident in the behavior.
  2. The shift register looks like it's unnecessary since the loop only executes once.
  3. The subtraction will overflow for an "alpha" of 0. That may be something you don't care about--otherwise you'll need a U25,1 output to handle that case.
  4. For initial algorithm development, I would get rid of the SCTL and handshaking signal logic just to simplify it until the numeric issues are solved. Since you're not using any of the handshaking functionality, you could also consider starting with the yellow Add/Subtract/Multiply and switching to High Throughput versions later when and if you need to use the pipelining features. The main advantage of the native primitives is that they execute much faster on the desktop. The performance in hardware should be identical for the non-registered configurations.

Hope this helps,

 

Jim

 

Message 7 of 11
(6,477 Views)

Hey Jim,

 

Q1 and Q2: I have this shift register, because later on I want to be able to multiple pass the input signal through the filter. That is how it will look like:

MP EWMA.PNG

Therefor i want to scale the output to I36.1 again to have the same fxp type.

 

Q3: Ok i will change it the output of the subtraction to U25.1

Q4: You are right, I will try to make the code easier. I will built a testbench, were I fed the filter with a noisy DC signal.

 

I will post my updates.

@JLewis: I think you can still help me with my cic 🙂

 

Kind regards

Slev1n

0 Kudos
Message 8 of 11
(6,448 Views)

So the actual error was beyond the filter at a bit shift...

 

I have now a working version, which can be implemented as a multipass as well. Can someone have a look at the pipeline logic?

 

kind regards

Slev1n

 

 

0 Kudos
Message 9 of 11
(6,391 Views)

Hi Slev1n,

 

Have you tested theses results against the original version? It looks like there may be some timing issues that would change the behavior. Here's a few suggestions:

 

  1. The Input Valid? signal goes through a feedback node and is offset by 1 cycle from the Input x[n] signal, so it would apply the next input sample, not the current one.
  2. Pipelining recursive paths is tricky, because the delays affect the transfer function. The problem is that you need a y[n-1] signal for the feedback path, but by the time the input propagates through the forward path delays, the best you can do is y[n-3]. There is a technique called lookahead pipelining that basically precomputes y[n-1] and y[n-2] to make this work. For your difference equation, you can compute y[n-1] directly (since you know the formula for y[n]):  y[n-1] = alpha * x[n-1] + (1-alpha)*y[n-2]. Repeating for y[n-2] and plugging all that into your original equation will give you the (somewhat more expensive) pipelined version of the original equation. A careful cycle-accurate testbench is essential for this sort of thing. I'm not sure what your "#multipass" input does, but that could complicate the situation further.
  3. Since your delays are known (other than the multipass thing), you might consider scheduling the handshaking yourself. In other words, leave the handshaking signals unwired and simply delay the Input Valid? the appropriate number of cycles to feed the Data ready? output. It looks like your diagram should always be able to accept new data, so you could just hardcode Ready for input? to return true.

Hope that helps,

 

Jim

 

Message 10 of 11
(6,356 Views)