LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

[FPGA] average over periods of data

Hi,

 

I have large amount of periodic data that I would like to average, but I am running into problem due to clock mismatch. Please bear with me for any stupid question. Here's the description of the problem

 

The actual data is generated at 2 MSPS rate, but the ADC is sampling it at 130 MSPS. 

I am reading these data through a SCTL in FPGA at the 130MS clock rate. I am able to downsample the data to match 2MS clock rate without a problem. 

Now suppose the data is periodic at 10kHz, which means 200 points per period is generated at the 2MHz clock rate. Ideally I would like to report 200 points (one period) every second without throwing out any data. So I would like to average over periods of data, and downconvert it to 200 SPS. In this case, I will need to average over 10000 periods. 

 

If I slack the problem a little bit, instead of reporting every second, I can report it every ms, this means I only need to average over 10 periods. So I would like to have something like y[n] = 0.1*(x[n]+x[n-200]+...+x[n-1800])

 

Earlier I tried to apply this convolution like solution through a FIR filter. The thing is that, with the clock running at 130 MSPS, I actually need something like y[n] = 0.1*(x[n]+x[n-200*65]+...+x[n-1800*65]), which is apparently too much for a FIR filter, unless the filter can distinguish between the incoming rate and actual clock rate. And even if I specify the input clock frequency and clock frequency in Xilinx FIR 5.0 compiler, the output shows that the difference is not recognized.

 

So is there a better way to do this? Any suggestion will be helpful!

 

Thank you!

0 Kudos
Message 1 of 3
(4,105 Views)

Hello yifengc,

 

previously I used this example: https://decibel.ni.com/content/docs/DOC-1128 . This worked fine for me, but it was with a really low sample rate and less samples. Hopefully it is useful to you.

 

Best regards,

 

Martijn

0 Kudos
Message 2 of 3
(3,983 Views)

I like the moving average you posted.  I wish I'd seen that a few years ago...

 

The moving average msmeulers posted can probably be adapted for an array of 200 samples instead of a single I16, but that may be pushing it for smaller FPGAs.  Honestly, any solution holding 200 samples of very many bits would be pushing it for smaller FPGAs.

 

One key point is that powers of 2 are your friend.  You can't easily average 10 or 10,000 samples in an FPGA because the FPGA can't divide (or at least it should be avoided when possible).  The FPGA can divide by a power of 2 (like 8 or 8192) by simply redefining where the binary decimal-point is, and that is free.  

 

However, if you need 10,000 samples and don't mind division in the PC or real-time processor outside the FPGA, go for it.

 

Watch your data types closely.  You may get away with integers bigger than you need, but that may also hit your FPGA's limits, so you may need to use Fixed-Point, and pick it exactly right.  The total needs to have more bits than the samples, and should have the same LSB position or you'll lose some accuracy.  If the sample is Fixed-Point:3.8 (11 bits, with 3 as integer) and you average 2^12 samples, you should have Fixed-Point:15.8 (23 bits, with 15 as integer) totals.

 

I'm sure you'll need to keep an array of 200 totals (256 may actually work better, but probably not) no matter what you do.  I suggest making an array that big, do something with it to make sure it doesn't get optimized away, and build the code to make sure it fits.

 

If you don't need a running average, you could total up values, then output the total and restart at 0 periodically.  The running average is great, but needs to save (200 x 2^N x <# of bits in samples> + 200 * (N+<# of bits in samples>) bits in the FIFO, which I doubt will fit in most FPGAs.

 

There are two approaches, and I'm not certain which will convert to VHDL (for the FPGA) better:

1. Each time you add, update the right element in the array (make sure to use an in-place structure).

2. Each time, rotate the array of totals, and update the 0th element in the array (still using in-place structure, but with index=0).

You should try both, and see which uses the smallest % of the FPGA.

 

Indexing an array is actually more work for an FPGA than rotating an array.  You could output then zero one total after every 1401 sub-samples through (so you output a different one each time).  With this trick, you need to (I think) divide by 1401 in the host CPU or PC.

___________________
CLD, CPI; User since rev 8.6.
0 Kudos
Message 3 of 3
(3,910 Views)