From ee5879add65e469eeac9fe7b64c593394f277c8f Mon Sep 17 00:00:00 2001 From: Abraxas3d Date: Fri, 15 May 2026 15:32:21 -0700 Subject: [PATCH] Gate EMA accumulator updates on data_ena Previously, all internal state (alpha_signed, alpha_m, data_signed, mult_data, mult_sum, average) updated unconditionally each clock, treating data_ena only as a passthrough strobe to average_ena. This is correct for streaming inputs where every clock has valid data, but incorrect for multiplexed inputs where data_ena selects which clocks to integrate. This change wraps the EMA math in 'if data_ena = 1' so that the accumulator only advances on valid samples. average_ena remains outside the gate to faithfully mark output validity. Backward compatibility: for streaming inputs with data_ena tied high, behavior is unchanged. --- src/lowpass_ema.vhd | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/lowpass_ema.vhd b/src/lowpass_ema.vhd index 9f1aad5..adb92c4 100644 --- a/src/lowpass_ema.vhd +++ b/src/lowpass_ema.vhd @@ -162,18 +162,19 @@ BEGIN average <= (OTHERS => '0'); average_ena <= '0'; ELSE + IF data_ena = '1' THEN + alpha_signed <= signed(alpha); + alpha_m <= alpha_max - alpha_signed; - alpha_signed <= signed(alpha); - alpha_m <= alpha_max - alpha_signed; + data_signed <= signed(data); - data_signed <= signed(data); + -- ema[n] = ( alpha*16*x[n]*16 + [1-alpha]*ema[n-1] ) / 256 - -- ema[n] = ( alpha*16*x[n]*16 + [1-alpha]*ema[n-1] ) / 256 + mult_data <= resize(data_signed * alpha_signed, PROD_W); + mult_sum <= resize(sum_shift * alpha_m , PROD_W); - mult_data <= resize(data_signed * alpha_signed, PROD_W); - mult_sum <= resize(sum_shift * alpha_m , PROD_W); - - average <= std_logic_vector(resize(shift_right(sum, AVG_SHIFT), DATA_W)); + average <= std_logic_vector(resize(shift_right(sum, AVG_SHIFT), DATA_W)); + END IF; average_ena <= data_ena; END IF;