Added K IIR lpf filter
This commit is contained in:
64
rtl/core/lpf_iir_q15_k.v
Normal file
64
rtl/core/lpf_iir_q15_k.v
Normal file
@@ -0,0 +1,64 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
// =============================================================================
|
||||
// Low-Pass IIR Filter (Q1.15)
|
||||
// Simple first-order infinite impulse response filter, equivalent to an
|
||||
// exponential moving average. Provides an adjustable smoothing factor based
|
||||
// on parameter K.
|
||||
//
|
||||
// Implements:
|
||||
// Y[n+1] = Y[n] + (X[n] - Y[n]) / 2^K
|
||||
//
|
||||
// This is a purely digital one-pole low-pass filter whose time constant
|
||||
// approximates that of an analog RC filter, where alpha = 1 / 2^K.
|
||||
//
|
||||
// The larger K is, the slower the filter responds (stronger smoothing).
|
||||
// The smaller K is, the faster it reacts to changes.
|
||||
//
|
||||
// parameters:
|
||||
// -- K : filter shift factor (integer, 4..14 typical)
|
||||
// cutoff frequency ≈ Fs / (2π * 2^K)
|
||||
// larger K → lower cutoff
|
||||
//
|
||||
// inout:
|
||||
// -- clk : input clock
|
||||
// -- rst_n : active-low reset
|
||||
// -- x_q15 : signed 16-bit Q1.15 input sample (e.g., 0..0x7FFF)
|
||||
// -- y_q15 : signed 16-bit Q1.15 filtered output
|
||||
//
|
||||
// Notes:
|
||||
// - The arithmetic right shift implements division by 2^K.
|
||||
// - Internal arithmetic is Q1.15 fixed-point with saturation
|
||||
// to [0, 0x7FFF] (for non-negative signals).
|
||||
// - Useful for smoothing noisy ADC / sigma-delta data streams
|
||||
// or modeling an RC envelope follower.
|
||||
// =============================================================================
|
||||
module lpf_iir_q15_k #(
|
||||
parameter integer K = 10 // try 8..12; bigger = more smoothing
|
||||
)(
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
input wire signed [15:0] x_q15, // Q1.15 input (e.g., 0..0x7FFF)
|
||||
output reg signed [15:0] y_q15 // Q1.15 output
|
||||
);
|
||||
wire signed [15:0] e_q15 = x_q15 - y_q15;
|
||||
wire signed [15:0] delta_q15 = e_q15 >>> K; // arithmetic shift
|
||||
wire signed [15:0] y_next = y_q15 + delta_q15; // clamp to [0, 0x7FFF] (handy if your signal is non-negative)
|
||||
|
||||
function signed [15:0] clamp01;
|
||||
input signed [15:0] v;
|
||||
begin
|
||||
if (v < 16'sd0)
|
||||
clamp01 = 16'sd0;
|
||||
else if (v > 16'sh7FFF)
|
||||
clamp01 = 16'sh7FFF;
|
||||
else
|
||||
clamp01 = v;
|
||||
end
|
||||
endfunction
|
||||
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) y_q15 <= 16'sd0;
|
||||
else y_q15 <= clamp01(y_next);
|
||||
end
|
||||
endmodule
|
||||
Reference in New Issue
Block a user