diff --git a/libraries/dsp/carousel_correlator/hdllib.cfg b/libraries/dsp/carousel_correlator/hdllib.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..9d78e2cb3494e6c9de57b6166ef39d8b8cbc8acc
--- /dev/null
+++ b/libraries/dsp/carousel_correlator/hdllib.cfg
@@ -0,0 +1,14 @@
+hdl_lib_name = carousel_correlator
+hdl_library_clause_name = carousel_correlator_lib
+hdl_lib_uses = common dp
+hdl_lib_technology = 
+
+build_dir_sim = $HDL_BUILD_DIR
+build_dir_synth = $HDL_BUILD_DIR
+
+synth_files =
+    $SVN/RadioHDL/trunk/libraries/dsp/carousel_correlator/src/vhdl/carousel.vhd
+
+test_bench_files = 
+    $SVN/RadioHDL/trunk/libraries/dsp/carousel_correlator/tb/vhdl/tb_carousel.vhd
+
diff --git a/libraries/dsp/carousel_correlator/src/vhdl/carousel.vhd b/libraries/dsp/carousel_correlator/src/vhdl/carousel.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..5699eca8b31bf278f96357efb6ed574873006a6b
--- /dev/null
+++ b/libraries/dsp/carousel_correlator/src/vhdl/carousel.vhd
@@ -0,0 +1,119 @@
+--------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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/>.
+--
+--------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE common_lib.common_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+
+-- Purpose:
+-- . Outputs all unique pair permutations of the words at the inputs.
+-- Description:
+-- . Example permutations of [0,1,2]: [[0,0],[0,1],[0,2],[1,2],[1,1],[2,2]]
+-- . c_nof_permutations = g_nof_inputs*(g_nof_inputs+1)/2
+-- . Each permutation can be used to calculate one unique visibility.
+-- . snk_in_arr(0).valid is used to indicate validity of all inputs.
+-- Usage:
+-- . Determine g_nof_inputs; e.g. 3 
+-- . Calculate c_nof_permutations: e.g. 6
+--   . Note your output options, e.g.
+--     . 6 cycles * 1 output
+--     . 3 cycles * 2 outputs
+--     . 2 cycles * 3 outputs
+--     . 1 cycle  * 6 outputs
+-- . Set your g_nof_outputs accordingly.
+
+
+ENTITY carousel IS
+  GENERIC (
+    g_nof_inputs  : NATURAL := 8;
+    g_nof_outputs : NATURAL := 9
+  ); 
+  PORT (
+    rst         : IN  STD_LOGIC;
+    clk         : IN  STD_LOGIC;
+
+    snk_in_arr  : IN  t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0);
+    snk_out_arr : OUT t_dp_siso_arr(g_nof_inputs-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
+
+    src_out_arr : OUT t_dp_sosi_2arr_2(g_nof_outputs-1 DOWNTO 0) -- Array of pairs
+  );
+END carousel;
+
+ARCHITECTURE rtl OF carousel IS
+
+  CONSTANT c_nof_permutations : NATURAL := g_nof_inputs*(g_nof_inputs+1)/2;
+
+  SIGNAL nxt_reg_out_2arr_2   : t_dp_sosi_2arr_2(g_nof_inputs-1 DOWNTO 0);
+  SIGNAL reg_out_2arr_2       : t_dp_sosi_2arr_2(g_nof_inputs-1 DOWNTO 0);
+
+BEGIN
+
+  -----------------------------------------------------------------------------
+  -- Carousel register shifting
+  -- . 3-input example, carousel rotation is counter-clockwise:
+  --                                                ___ 
+  --                                               |   |
+  --   snk_in_arr[2]--->nxt_reg_out_2arr_2[2][1]->[1]--|---> reg_out_2arr_2[2][1]
+  --                \-->nxt_reg_out_2arr_2[2][0]---|->[0]--> reg_out_2arr_2[2][0]
+  --   snk_in_arr[1]--->nxt_reg_out_2arr_2[1][1]--[1]  | --> reg_out_2arr_2[1][1]
+  --                \-->nxt_reg_out_2arr_2[1][0]---|->[0]--> reg_out_2arr_2[1][0]
+  --   snk_in_arr[0]--->nxt_reg_out_2arr_2[0][1]->[1]  | --> reg_out_2arr_2[0][1]
+  --                \-->nxt_reg_out_2arr_2[0][0]---|->[0]--> reg_out_2arr_2[0][0]
+  --                                               |___|
+  -----------------------------------------------------------------------------
+  p_carousel: PROCESS(snk_in_arr, reg_out_2arr_2)
+  BEGIN
+    IF snk_in_arr(0).valid = '1' THEN -- Take fresh set of input data
+      FOR i IN 0 TO g_nof_inputs-1 LOOP
+        nxt_reg_out_2arr_2(i)(0) <= snk_in_arr(i);
+        nxt_reg_out_2arr_2(i)(1) <= snk_in_arr(i);
+      END LOOP;
+    ELSE -- Shift around the current data; keep producing new permutations
+      -- Top of carousel, shift left 
+      nxt_reg_out_2arr_2(g_nof_inputs-1)(1) <= reg_out_2arr_2(g_nof_inputs-1)(0);
+      -- Left column of carousel, shift down
+      FOR i IN 0 TO g_nof_inputs-2 LOOP
+        nxt_reg_out_2arr_2(i)(1) <= reg_out_2arr_2(i+1)(1);
+      END LOOP;
+      -- Right column of carousel, shift up
+      FOR i IN 1 TO g_nof_inputs-1 LOOP
+        nxt_reg_out_2arr_2(i)(0) <= reg_out_2arr_2(i-1)(0);
+      END LOOP;
+      -- Bottom of carousel, shift right
+      nxt_reg_out_2arr_2(0)(0) <= reg_out_2arr_2(0)(1);
+    END IF;
+  END PROCESS;
+
+  -----------------------------------------------------------------------------
+  -- Registers
+  -----------------------------------------------------------------------------
+  p_clk: PROCESS(clk, rst)
+  BEGIN
+    IF rst='1' THEN
+      reg_out_2arr_2 <= (OTHERS=>(OTHERS=>c_dp_sosi_rst));
+    ELSIF rising_edge(clk) THEN
+      reg_out_2arr_2 <= nxt_reg_out_2arr_2;
+    END IF;
+  END PROCESS;
+
+END rtl;
diff --git a/libraries/dsp/carousel_correlator/tb/vhdl/tb_carousel.vhd b/libraries/dsp/carousel_correlator/tb/vhdl/tb_carousel.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..5a31005e2be523182a04b46ba92a0b154f0b43ae
--- /dev/null
+++ b/libraries/dsp/carousel_correlator/tb/vhdl/tb_carousel.vhd
@@ -0,0 +1,88 @@
+--------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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/>.
+--
+--------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE common_lib.common_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+--USE dp_lib.tb_dp_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+
+ENTITY tb_carousel IS
+  GENERIC (
+    g_nof_inputs  : NATURAL := 8;
+    g_nof_outputs : NATURAL := 9
+  );
+END tb_carousel;
+
+ARCHITECTURE tb OF tb_carousel IS
+
+  CONSTANT c_clk_period                   : TIME := 10 ns;
+  CONSTANT c_data_w                       : NATURAL := 32;
+  CONSTANT c_nof_permutations             : NATURAL := (g_nof_inputs*(g_nof_inputs+1))/2;
+  CONSTANT c_nof_clk_cycles_per_input_val : NATURAL := c_nof_permutations/g_nof_outputs;
+
+  SIGNAL tb_end         : STD_LOGIC := '0';
+  SIGNAL clk            : STD_LOGIC := '1';
+  SIGNAL rst            : STD_LOGIC;
+
+  SIGNAL carousel_snk_in_arr     : t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0);
+  SIGNAL carousel_src_out_2arr_2 : t_dp_sosi_2arr_2(g_nof_outputs-1 DOWNTO 0);  
+
+BEGIN
+
+  clk <= NOT clk OR tb_end AFTER c_clk_period/2;
+  rst <= '1', '0' AFTER c_clk_period*7;
+
+  u_carousel : ENTITY work.carousel
+  GENERIC MAP (
+    g_nof_inputs  => g_nof_inputs,
+    g_nof_outputs => g_nof_outputs
+  )
+  PORT MAP (
+    rst         => rst,
+    clk         => clk,
+    snk_in_arr  => carousel_snk_in_arr,
+    src_out_arr => carousel_src_out_2arr_2
+  );  
+
+  p_stimuli: PROCESS
+  BEGIN
+    WAIT UNTIL rst = '0';
+    WAIT FOR 100 ns;
+    FOR i IN 0 TO 10-1 LOOP
+      FOR j IN 0 TO g_nof_inputs-1 LOOP
+        -- Feed the carousel. Use the stream index as data word
+        carousel_snk_in_arr(j).data(c_data_w-1 DOWNTO 0) <= TO_UVEC(j, c_data_w);
+        carousel_snk_in_arr(j).valid <= '1';
+      END LOOP;
+      WAIT FOR c_clk_period;
+      FOR j IN 0 TO g_nof_inputs-1 LOOP
+        -- Let the carousel do its thing
+        carousel_snk_in_arr(j).data <= (OTHERS=>'0');
+        carousel_snk_in_arr(j).valid <= '0';
+      END LOOP;
+    WAIT FOR (c_nof_clk_cycles_per_input_val-1)*c_clk_period;
+    END LOOP;
+  END PROCESS;
+
+END tb;