diff --git a/libraries/dsp/rTwoSDF/tb/vhdl/tb_rTwoSDF.vhd b/libraries/dsp/rTwoSDF/tb/vhdl/tb_rTwoSDF.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ffa1d2a7a28296e130b9ce06577c815ee711b9ac
--- /dev/null
+++ b/libraries/dsp/rTwoSDF/tb/vhdl/tb_rTwoSDF.vhd
@@ -0,0 +1,395 @@
+-- Author: Raj Thilak Rajan : rajan at astron.nl: Nov 2009
+--------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+--------------------------------------------------------------------------------
+
+--
+-- Purpose: Test bench for the rTwoSDF pipelined radix 2 FFT
+--
+-- Description: ASTRON-RP-755
+--   The testbench can simulate (via g_use_uniNoise_file):
+--
+--   a) complex uniform noise input from a file generated by testFFT_input.m
+--   b) impulse input from a manually created file
+--
+--   Stimuli b) are useful for visual interpretation of the FFT output, because
+--   an impulse at the real input and zero at the imaginary inpu will result
+--   in DC and zero if the pulse occurs at the first sample or in sinus and
+--   cosinus wave if the impulse occurs at a later sample. However because the
+--   imaginary input is zero this does not cover all internals of the PFT 
+--   implementation. Therefore stimuli a) are needed to fully verify the PFT.
+--
+--   The rTwoSDF output can be verified in two ways:
+--
+--   1) The MATLAB testFFT_output.m can calculate the floating point FFT and
+--      compare it with the rTwoSDF implementation output file result.
+--   2) The rTwoSDF implementation output file is also kept in SVN as golden
+--      reference result to allow verification using a file diff command like
+--      e.g. WinMerge. This then avoids the need to run MATLAB to verify.
+--
+--   The tb asserts an error when the output does not match the expected output
+--   that is read from the golden reference file. The output is also written
+--   to a default output file to support offline analysis.     
+--
+-- Usage:
+--   > vsim -vopt -voptargs=+acc work.tb_rtwosdf (double click tb_rtwosdf icon)
+--   > do wave_rTwoSDF.do
+--   > run -all
+--     . it may be necessary to rescale the analogue formats in the Wave
+--       window after running the simulation.
+--
+-- Remarks:
+-- . The tb uses LRM 1076-1987 style for file IO. This implies that only
+--   simulator start and quit can open and close the file. The output file
+--   can be read in a file editor, but the SVN file icon indicates that the
+--   file is modified even if the contents is not changed. Only after closing
+--   the simulation (> quit -sim) does the SVN file icon indicate the true
+--   state. Next time we better use LRM 1076-1993 style for file IO.
+--
+-- . The generic g_post_sim can be used to switch between functional simulation
+--   and timing simulation. Note that the entity name of the timing model from
+--   the .vho file must be changed to rTwoSDF_t.
+
+library ieee, common_lib;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+use IEEE.std_logic_textio.all;
+use STD.textio.all;
+use common_lib.common_pkg.all;
+use common_lib.common_lfsr_sequences_pkg.all;
+use common_lib.tb_common_pkg.all;
+use work.rTwoSDFPkg.all;
+use work.twiddlesPkg.all;
+
+
+entity tb_rTwoSDF is
+  generic(
+    -- generics for tb
+    g_use_uniNoise_file : boolean  := true;
+    g_in_en             : natural  := 1;     -- 1 = always active, others = random control
+    g_post_sim          : boolean  := false;
+    -- generics for rTwoSDF
+    g_use_reorder       : boolean  := true;
+    g_nof_points        : natural  := 1024;
+    g_in_dat_w          : natural  := 8;   
+    g_out_dat_w         : natural  := 14;   
+    g_guard_w           : natural  := 2;     -- guard bits are used to avoid overflow in single FFT stage.   
+
+    -- Internal pipeline settings for rTwoSDF
+    g_pipeline : t_fft_pipeline := (1, 1, 3, 1, 1, 0, 0, 1)  -- type t_rtwo_sdf_stage_pipeline is record
+                                                             --   -- generics for rTwoSDFStage
+                                                             --   stage_lat      : natural;  -- = 1
+                                                             --   weight_lat     : natural;  -- = 1
+                                                             --   mul_lat        : natural;  -- = 3
+                                                             --   -- generics for rTwoBFStage
+                                                             --   bf_lat         : natural;  -- = 1
+                                                             --   -- generics for rTwoBF
+                                                             --   bf_use_zdly    : natural;  -- = 1
+                                                             --   bf_in_a_zdly   : natural;  -- = 0
+                                                             --   bf_out_d_zdly  : natural;  -- = 0
+                                                             --   sep_lat        : natural;  -- = 1
+                                                             -- end record;
+  );
+end entity tb_rTwoSDF;
+
+
+architecture tb of tb_rTwoSDF is
+
+  constant c_clk_period : time    := 20 ns;      
+  
+  
+  
+  -- input/output data width
+  constant c_stage_dat_w : natural := sel_a_b(g_out_dat_w > c_dsp_mult_w, g_out_dat_w, c_dsp_mult_w); -- number of bits used between the stages
+
+  -- input/output files
+  constant c_file_len   : natural := 8*g_nof_points;
+  constant c_repeat     : natural := 2;  -- >= 2 to have sufficent frames for c_outputFile evaluation by testFFT_output.m
+
+  -- input from uniform noise file created automatically by MATLAB testFFT_input.m
+  constant c_noiseInputFile    : string := "../../../tb/data/test/in/uniNoise_p"  & natural'image(g_nof_points)& "_b"& natural'image(g_in_dat_w) &"_in.txt";
+  constant c_noiseGoldenFile   : string := "../../../tb/data/test/out/uniNoise_p" & natural'image(g_nof_points)& "_in"& natural'image(g_in_dat_w) &"_out"&natural'image(g_out_dat_w) &"_out.txt";
+  constant c_noiseOutputFile   : string := "../../../tb/data/test/out/uniNoise_out.txt";
+
+  -- input from manually created file
+  constant c_impulseInputFile  : string := "../../../tb/data/test/in/impulse_p"   & natural'image(g_nof_points)& "_b"& natural'image(g_in_dat_w)& "_in.txt";
+  constant c_impulseGoldenFile : string := "../../../tb/data/test/out/impulse_p"  & natural'image(g_nof_points)& "_b"& natural'image(g_in_dat_w)& "_out.txt";
+  constant c_impulseOutputFile : string := "../../../tb/data/test/out/impulse_out.txt";
+
+  -- determine active stimuli and result files
+  constant c_inputFile  : string := sel_a_b(g_use_uniNoise_file, c_noiseInputFile,  c_impulseInputFile);
+  constant c_goldenFile : string := sel_a_b(g_use_uniNoise_file, c_noiseGoldenFile, c_impulseGoldenFile);
+  constant c_outputFile : string := sel_a_b(g_use_uniNoise_file, c_noiseOutputFile, c_impulseOutputFile);
+
+  -- signal definitions
+  signal tb_end         : std_logic := '0';
+  signal clk            : std_logic := '0';
+  signal rst            : std_logic := '0';
+  signal enable         : std_logic := '1';
+  signal random         : std_logic_vector(15 downto 0) := (others=>'0');  -- use different lengths to have different random sequences
+  signal in_en          : std_logic := '0';
+
+  signal in_re          : std_logic_vector(g_in_dat_w-1 downto 0);
+  signal in_im          : std_logic_vector(g_in_dat_w-1 downto 0);
+  signal in_sync        : std_logic:= '0';
+  signal in_val         : std_logic:= '0';
+
+  signal out_re         : std_logic_vector(g_out_dat_w-1 downto 0);
+  signal out_im         : std_logic_vector(g_out_dat_w-1 downto 0);
+  signal out_sync       : std_logic:= '0';
+  signal out_val        : std_logic:= '0';
+
+  signal in_file_data   : t_integer_matrix(0 to c_file_len-1, 1 to 2) := (others=>(others=>0));  -- [re, im]
+  signal in_file_sync   : std_logic_vector(0 to c_file_len-1):= (others=>'0');
+  signal in_file_val    : std_logic_vector(0 to c_file_len-1):= (others=>'0');
+
+  signal in_index       : natural := 0;
+  signal in_repeat      : natural := 0;
+
+  signal gold_file_data : t_integer_matrix(0 to c_file_len-1, 1 to 2) := (others=>(others=>0));  -- [re, im]
+  signal gold_file_sync : std_logic_vector(0 to c_file_len-1):= (others=>'0');
+  signal gold_file_val  : std_logic_vector(0 to c_file_len-1):= (others=>'0');
+  
+  signal gold_index     : natural;
+  signal gold_sync      : std_logic;
+  signal gold_re        : integer;
+  signal gold_im        : integer;
+  
+begin
+
+  clk <= (not clk) or tb_end after c_clk_period/2;
+  rst <= '1', '0' after c_clk_period*7;
+  enable <= '0', '1' after c_clk_period*23;
+  random <= func_common_random(random) when rising_edge(clk);
+  in_en <= '1' when g_in_en=1 else random(random'HIGH);
+  
+
+  p_read_input_file : process
+    file v_input : TEXT open READ_MODE is c_inputFile;  -- this is LRM 1076-1987 style and implies that only simulator start and quit can open and close the file
+    variable v_log_line    : LINE;
+    variable v_input_line  : LINE;
+    variable v_index       : integer :=0;
+    variable v_comma       : character;
+    variable v_sync        : std_logic_vector(0 to c_file_len-1):=(others=>'0');
+    variable v_val         : std_logic_vector(0 to c_file_len-1):=(others=>'0');
+    variable v_data        : t_integer_matrix(0 to c_file_len-1, 1 to 2) := (others=>(others=>0));
+  begin
+    -- wait 1 clock cycle to avoid that the output messages in the transcript window get lost in the 0 ps start up messages 
+    proc_common_wait_some_cycles(clk, 1);
+    -- combinatorially read the file into the array
+    write(v_log_line, string'("reading stimuli file : "));
+    write(v_log_line, c_inputFile);
+    writeline(output, v_log_line);
+    loop
+      exit when endfile(v_input);
+      readline(v_input, v_input_line);
+
+      read(v_input_line, v_sync(v_index));    -- sync
+      read(v_input_line, v_comma);
+
+      read(v_input_line, v_val(v_index));     -- valid
+      read(v_input_line, v_comma);
+
+      read(v_input_line, v_data(v_index,1));  -- real
+      read(v_input_line, v_comma);
+
+      read(v_input_line, v_data(v_index,2));  -- imag
+      v_index := v_index + 1;
+    end loop;
+    write(v_log_line, string'("finished reading stimuli file"));
+    writeline(output, v_log_line);
+
+    in_file_data <= v_data;
+    in_file_sync <= v_sync;
+    in_file_val  <= v_val;
+    wait;
+  end process;
+
+  p_in_stimuli : process(clk, rst)
+  begin
+    if rst='1' then
+      in_re   <= (others=>'0');
+      in_im   <= (others=>'0');
+      in_sync <= '0';
+      in_val  <= '0';
+
+      in_index  <=  0;
+      in_repeat <=  0;
+    elsif rising_edge(clk) then
+
+      in_sync <= '0';
+      in_val  <= '0';
+
+      -- start stimuli some arbitrary time after rst release to ensure that the proper behaviour of the DUT does not depend on that time
+      if enable='1' then
+        -- use always active input (the in_file contents may still contain blocks with in_val='0') or use random active input
+        if in_en='1' then
+          if in_index<c_file_len-1 then
+            in_index <= in_index+1;
+          else
+            in_index <= 0;
+            in_repeat <= in_repeat + 1;
+          end if;
+    
+          if in_repeat < c_repeat then
+            in_re   <= std_logic_vector(to_signed(in_file_data(in_index, 1), g_in_dat_w));
+            in_im   <= std_logic_vector(to_signed(in_file_data(in_index, 2), g_in_dat_w));
+            in_sync <= std_logic(in_file_sync(in_index));
+            in_val  <= std_logic(in_file_val(in_index));
+          end if;
+          
+          if in_repeat > c_repeat then
+            tb_end <= '1';
+          end if;
+        end if;
+      end if;
+      
+    end if;
+  end process;
+
+
+  gen_func_dut : if g_post_sim = FALSE generate 
+    -- DUT = Device Under Test
+    u_rTwoSDF : entity work.rTwoSDF
+    generic map(
+      -- generics for the FFT
+      g_use_reorder => g_use_reorder,
+      g_in_dat_w    => g_in_dat_w,
+      g_out_dat_w   => g_out_dat_w, 
+      g_stage_dat_w => c_stage_dat_w,
+      g_guard_w     => g_guard_w,
+      g_nof_points  => g_nof_points,
+      -- generics for rTwoSDFStage
+      g_pipeline    => g_pipeline
+    )
+    port map(
+      clk       => clk,
+      rst       => rst,
+      in_re     => in_re,
+      in_im     => in_im,
+      in_val    => in_val,
+      out_re    => out_re,
+      out_im    => out_im,
+      out_val   => out_val
+    );   
+  end generate; 
+
+-- In case a timing simulation should be made the next code 
+-- should be un-commented. And the name of the timing varina entity
+-- in the .vho file must be renamed to rTwoSDF_t.
+  
+--  gen_time_dut : if g_post_sim = TRUE generate   
+--    -- DUT = Device Under Test
+--    u_rTwoSDF_t : entity work.rTwoSDF_t
+--    port map(
+--      clk       => clk,
+--      rst       => rst,
+--      in_re     => in_re,
+--      in_im     => in_im,
+--      in_val    => in_val,
+--      out_re    => out_re,
+--      out_im    => out_im,
+--      out_val   => out_val
+--    );
+--  end generate;
+
+  -- Read golden file with the expected DUT output
+  p_read_golden_file : process
+    file v_golden : TEXT open READ_MODE is c_goldenFile;  -- this is LRM 1076-1987 style and implies that only simulator start and quit can open and close the file
+    variable v_log_line    : LINE;
+    variable v_golden_line : LINE;
+    variable v_index       : integer :=0;
+    variable v_comma       : character;
+    variable v_sync        : std_logic_vector(0 to c_file_len-1):=(others=>'0');
+    variable v_val         : std_logic_vector(0 to c_file_len-1):=(others=>'0');
+    variable v_data        : t_integer_matrix(0 to c_file_len-1, 1 to 2) := (others=>(others=>0));
+  begin
+    -- wait 1 clock cycle to avoid that the output messages in the transcript window get lost in the 0 ps start up messages 
+    proc_common_wait_some_cycles(clk, 1);
+    -- combinatorially read the file into the array
+    write(v_log_line, string'("reading golden file : "));
+    write(v_log_line, c_goldenFile);
+    writeline(output, v_log_line);
+    loop
+      exit when endfile(v_golden);
+      readline(v_golden, v_golden_line);
+
+      read(v_golden_line, v_sync(v_index));    -- sync
+      read(v_golden_line, v_comma);
+
+      read(v_golden_line, v_val(v_index));     -- valid
+      read(v_golden_line, v_comma);
+
+      read(v_golden_line, v_data(v_index,1));  -- real
+      read(v_golden_line, v_comma);
+
+      read(v_golden_line, v_data(v_index,2));  -- imag
+      v_index := v_index + 1;
+    end loop;
+    write(v_log_line, string'("finished reading golden file"));
+    writeline(output, v_log_line);
+
+    gold_file_data <= v_data;
+    gold_file_sync <= v_sync;
+    gold_file_val  <= v_val;
+    wait;
+  end process;
+  
+  -- Show read data in Wave Window for debug purposes
+  gold_index <= gold_index + 1 when rising_edge(clk) and out_val='1';
+  gold_sync  <= gold_file_sync(gold_index);
+  gold_re    <= gold_file_data(gold_index,1);
+  gold_im    <= gold_file_data(gold_index,2);
+    
+  -- Verify the output of the DUT with the expected output from the golden reference file
+  p_verify_output : process(clk)
+  begin
+    -- Compare
+    if rising_edge(clk) then
+      if out_val='1' then
+        -- only write when out_val='1', because then the file is independent of cycles with invalid out_dat
+        assert out_sync        = gold_sync report "Output sync error"      severity error;
+        assert TO_SINT(out_re) = gold_re   report "Output real data error" severity error;
+        assert TO_SINT(out_im) = gold_im   report "Output imag data error" severity error;
+      end if;
+    end if;
+  end process;
+  
+  -- Write to default output file, this allows using command line diff or graphical diff viewer to compare it with the golden result file
+  p_write_output_file : process(clk)
+    file     v_output : TEXT open WRITE_MODE is c_outputFile;  -- this is LRM 1076-1987 style and implies that only simulator start and quit can open and close the file
+    variable v_line   : LINE;
+  begin
+    if rising_edge(clk) then
+      if out_val='1' then
+        -- only write when out_val='1', because then the file is independent of cycles with invalid out_dat
+        write(v_line, out_sync);
+        write(v_line, string'(","));
+        write(v_line, out_val);
+        write(v_line, string'(","));
+        write(v_line, to_integer(signed(out_re)));
+        write(v_line, string'(","));
+        write(v_line, to_integer(signed(out_im)));
+        writeline(v_output, v_line);
+      end if;
+    end if;
+  end process;
+
+end tb;