
This module implements a hardware-efficient Moving Average Filter, a type of Finite Impulse Response (FIR) filter where all coefficients are equal. It is designed specifically for low-area applications such as Tiny Tapeout or FPGA-based sensor conditioning.
The filter effectively removes high-frequency noise by averaging the last $N$ samples, acting as a low-pass filter with a Sinc-shaped frequency response.
| Parameter | Value |
|---|---|
| Data Width | 12-bit |
| Tap Count (N) | 8 |
| Architecture | Recursive Accumulator |
| Multipliers | 0 (Shift-only scaling) |
| Latent Delay | $(N-1)/2$ cycles |
The design utilizes a Recursive Summation approach. Instead of summing all taps every cycle, the logic updates a running accumulator:
$Sum_{n} = Sum_{n-1} + x[n] - x[n-N]$
data_in.shift_reg[TAPS-1]) from the current sum.data_in to the sum.>> 3) to divide the 15-bit sum back down to 12-bit output.| Port | Direction | Width | Description |
|---|---|---|---|
clk |
Input | 1 | System clock (Sampling clock) |
rst_n |
Input | 1 | Active-low asynchronous reset |
data_in |
Input | 12 | Unsigned/Signed input data |
data_out |
Output | 12 | Filtered output data |
The filter provides deep nulls at integer multiples of $f_s / N$. For a 1kHz target, the sampling frequency and tap count should be tuned to align the first null with the primary noise component.
Data Injection: Program the MCU to generate the noisy sine wave values mathematically (similar to the Verilog testbench) and send them to your hardware via a parallel bus or a fast protocol like SPI.
Clocking: Ensure the MCU and your filter share a common ground.
Logic Analyzer: Use a low-cost USB Logic Analyzer to capture the 12-bit output pins. Most logic analyzer software can "plot" the bus values as a waveform, allowing you to see the filtered sine wave on your PC screen.
MCU or FPGA to provide input and to collect the output. Output may be displayed through logic analyzer.
| # | Input | Output | Bidirectional |
|---|---|---|---|
| 0 | data_in[0] | filter_out[0] | data_in[8] |
| 1 | data_in[1] | filter_out[1] | data_in[9] |
| 2 | data_in[2] | filter_out[2] | data_in[10] |
| 3 | data_in[3] | filter_out[3] | data_in[11] |
| 4 | data_in[4] | filter_out[4] | filter_out[8] |
| 5 | data_in[5] | filter_out[5] | filter_out[9] |
| 6 | data_in[6] | filter_out[6] | filter_out[10] |
| 7 | data_in[7] | filter_out[7] | filter_out[11] |