diff --git a/libraries/dsp/fft/src/vhdl/fft_pkg.vhd b/libraries/dsp/fft/src/vhdl/fft_pkg.vhd
index 05eaa1ffb226920d9127c5d69ea56bdd2ecacefe..84f1eef69fa088e941de3d1bef2e5d3c9e396d98 100644
--- a/libraries/dsp/fft/src/vhdl/fft_pkg.vhd
+++ b/libraries/dsp/fft/src/vhdl/fft_pkg.vhd
@@ -32,6 +32,14 @@ package fft_pkg is
 
   function fft_switch_new_seed(seed : std_logic_vector; offset : natural) return std_logic_vector;
 
+  -- The FFT gain for an real input sinus signal is 0.5, because a real input
+  -- sinus with amplitude A yields two subband phasors each with amplitude
+  -- A/2, one at -f_bin and one at +f_bin. The power stays the same, because
+  -- the power of an real input sinus is A**2 / 2 and the power of the f_bin
+  -- signal complex phasors is (A/2)**2 + (A/2)**2 = A**2 / 2.
+  CONSTANT c_fft_real_input_gain_w  : INTEGER := -1;
+  CONSTANT c_fft_real_input_gain    : REAL := 2.0**REAL(c_fft_real_input_gain_w);
+
   -- FFT parameters for pipelined FFT (fft_pipe), parallel FFT (fft_par) and wideband FFT (fft_wide)
   type t_fft is record
     use_reorder    : boolean;  -- = false for bit-reversed output, true for normal output
diff --git a/libraries/dsp/wpfb/src/vhdl/wpfb_pkg.vhd b/libraries/dsp/wpfb/src/vhdl/wpfb_pkg.vhd
index d87302058e1779ac79bba9a0542157a249cedcf7..2f47ccaf17a13d4b1ed4192e4e1d852c75ae8f26 100644
--- a/libraries/dsp/wpfb/src/vhdl/wpfb_pkg.vhd
+++ b/libraries/dsp/wpfb/src/vhdl/wpfb_pkg.vhd
@@ -21,6 +21,7 @@
 
 library ieee, common_lib, rTwoSDF_lib, fft_lib, filter_lib;
 use IEEE.std_logic_1164.all;
+use IEEE.math_real.all;
 use common_lib.common_pkg.all;
 use rTwoSDF_lib.rTwoSDFPkg.all;
 use fft_lib.fft_pkg.all; 
@@ -69,6 +70,46 @@ package wpfb_pkg is
     fil_pipeline      : t_fil_ppf_pipeline; -- Pipeline settings for the filter units     
   end record;
 
+  -----------------------------------------------------------------------------
+  -- LOFAR2 subband filter
+  -----------------------------------------------------------------------------
+
+  -- Fsub settings:
+  -- . Settings used until at least March 2022
+  constant c_wpfb_lofar2_subbands_2021 : t_wpfb := (1, 1024, 0, 6,
+                                                    16, 0, 14, 17, 16,
+                                                    true, false, true, 17, 18, 0, 22, 1, true, 54, 2, 195313,
+                                                    c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
+
+  constant c_wpfb_lofar2_subbands_2022 : t_wpfb := (1, 1024, 0, 6,
+                                                    16, 1, 14, 0, 16,
+                                                    true, false, true, 0, 19, 1, 24, 1, true, 56, 2, 195313,
+                                                    c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
+
+  constant c_wpfb_lofar2_subbands      : t_wpfb := c_wpfb_lofar2_subbands_2022;
+
+  -- DC gain of WPFB FIR filter with Coeffs16384Kaiser-quant.dat used in LOFAR1.
+  -- . Calculated with applications/lofar2/model/run_pfir_coef.m using application = 'lofar_subband'
+  -- . Not used in RTL, only used in test benches to verify expected subband levels
+  constant c_wpfb_lofar1_fir_filter_dc_gain    : real := 0.994817;
+
+  -- The FFT output has more bits to be able to preserve the sensitivity of
+  -- the processing gain of the FFT. The FFT has a processing gain of
+  -- sqrt(N_sub = N_fft / 2 = 512), so 4.5 bits. Therefore choose
+  -- fft_out_dat_w = fil_in_dat_w + 5 = 14 + 5 = 19b. Using fft_out_gain_w =
+  -- 1 compensates for the fil_backoff_w = 1. The func_wpfb_subband_scale_w
+  -- then thus returns 19 + 1 - (14 + 1) = 5 bits.
+  function func_wpfb_subband_scale_w(wpfb : t_wpfb) return natural;
+
+  -- The WPFB subband gain is the expected factor between subband amplitude
+  -- and real signal input amplitude. The WPFB subband gain consists of:
+  -- . the FFT gain for a real input and
+  -- . the extra bits to preserve the sensitivity of the FFT processing gain.
+  -- For example:
+  -- . func_wpfb_subband_gain() =  8 for c_wpfb_lofar2_subbands_2021
+  -- . func_wpfb_subband_gain() = 16 for c_wpfb_lofar2_subbands_2022
+  function func_wpfb_subband_gain(wpfb : t_wpfb) return real;
+
   -----------------------------------------------------------------------------
   -- Apertif application specfic settings
   -----------------------------------------------------------------------------
@@ -143,7 +184,7 @@ package wpfb_pkg is
   --   apertif_unb1_correlator_vis_offload
   -- . fft_out_dat_w = 18, because in there is a separate dp_requantize to get from 18b --> 9b in
   --   node_apertif_unb1_correlator_processing, this dp_requantize uses symmertical clipping.
-  CONSTANT c_wpfb_apertif_channels : t_wpfb := (1, 64, 1, 12,
+  constant c_wpfb_apertif_channels : t_wpfb := (1, 64, 1, 12,
                                                 8, 0, 8, 16, 9,
                                                 false, false, false, 16, 18, 0, c_dsp_mult_w, 2, true, 56, 2, 12500,
                                                 c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
@@ -168,7 +209,7 @@ package wpfb_pkg is
   -- . Using fft_out_dat_w = 12 instead of 9 and fft_out_gain_w = 2 instead of 0 created 12 - 9 - 2 = 1 bit more
   --   dynamic range. Therefore it may not be necessary to use fine channel symmetrical clipping using an external
   --   dp_requantize, like in Apertif X.
-  CONSTANT c_wpfb_arts_channels_sc4 : t_wpfb  := (1, 64, 1, 12,
+  constant c_wpfb_arts_channels_sc4 : t_wpfb  := (1, 64, 1, 12,
                                                   8, 0, 8, 16, 9,
                                                   true, true, false, 16, 12, 2, c_dsp_mult_w, 2, true, 56, 2, 12500,
                                                   c_fft_pipeline, c_fft_pipeline, c_fil_ppf_pipeline);
@@ -184,12 +225,22 @@ package wpfb_pkg is
   
   -- Estimate maximum number of blocks of latency between WPFB input and output
   function func_wpfb_maximum_sop_latency(wpfb : t_wpfb) return natural;
-  function func_wpfb_set_nof_block_per_sync(wpfb : t_wpfb; nof_block_per_sync : NATURAL) return t_wpfb;
+  function func_wpfb_set_nof_block_per_sync(wpfb : t_wpfb; nof_block_per_sync : natural) return t_wpfb;
 
 end package wpfb_pkg;
 
 package body wpfb_pkg is
 
+  function func_wpfb_subband_scale_w(wpfb : t_wpfb) return natural is
+  begin
+    return wpfb.fft_out_dat_w + wpfb.fft_out_gain_w - (wpfb.fil_in_dat_w + wpfb.fil_backoff_w);
+  end;
+
+  function func_wpfb_subband_gain(wpfb : t_wpfb) return real is
+  begin
+    return c_fft_real_input_gain * 2.0**real(func_wpfb_subband_scale_w(wpfb));
+  end;
+
   function func_wpfb_maximum_sop_latency(wpfb : t_wpfb) return natural is
     constant c_nof_channels : natural := 2**wpfb.nof_chan;
     constant c_block_size   : natural := c_nof_channels * wpfb.nof_points / wpfb.wb_factor;
@@ -208,7 +259,7 @@ package body wpfb_pkg is
   end func_wpfb_maximum_sop_latency;
   
   -- Overwrite nof_block_per_sync field in wpfb (typically for faster simulation)
-  function func_wpfb_set_nof_block_per_sync(wpfb : t_wpfb; nof_block_per_sync : NATURAL) return t_wpfb is
+  function func_wpfb_set_nof_block_per_sync(wpfb : t_wpfb; nof_block_per_sync : natural) return t_wpfb is
     variable v_wpfb : t_wpfb;
   begin
     v_wpfb := wpfb;