diff --git a/libraries/dsp/carousel_correlator/hdllib.cfg b/libraries/dsp/carousel_correlator/hdllib.cfg index 9d78e2cb3494e6c9de57b6166ef39d8b8cbc8acc..bebbe9fa76d1ce8972bd173d62ee0261009aae3f 100644 --- a/libraries/dsp/carousel_correlator/hdllib.cfg +++ b/libraries/dsp/carousel_correlator/hdllib.cfg @@ -7,8 +7,8 @@ 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 + $SVN/RadioHDL/trunk/libraries/dsp/carousel_correlator/src/vhdl/permutator.vhd test_bench_files = - $SVN/RadioHDL/trunk/libraries/dsp/carousel_correlator/tb/vhdl/tb_carousel.vhd + $SVN/RadioHDL/trunk/libraries/dsp/carousel_correlator/tb/vhdl/tb_permutator.vhd diff --git a/libraries/dsp/carousel_correlator/src/vhdl/permutator.vhd b/libraries/dsp/carousel_correlator/src/vhdl/permutator.vhd new file mode 100644 index 0000000000000000000000000000000000000000..b5f5859467f64f50b2bbb2f8fc4a38fd32c30006 --- /dev/null +++ b/libraries/dsp/carousel_correlator/src/vhdl/permutator.vhd @@ -0,0 +1,159 @@ +-------------------------------------------------------------------------------- +-- +-- 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 +-- 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 permutator 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_2arr : OUT t_dp_sosi_2arr_2(g_nof_outputs-1 DOWNTO 0) -- Array of pairs + ); +END permutator; + +ARCHITECTURE rtl OF permutator IS + + CONSTANT c_nof_permutations : NATURAL := g_nof_inputs*(g_nof_inputs+1)/2; + CONSTANT c_nof_cycles : NATURAL := ceil_div(c_nof_permutations,g_nof_outputs); + + TYPE t_permu_in_2arr IS ARRAY(g_nof_inputs-1 DOWNTO 0) OF t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); + SIGNAL permu_in_2arr : t_permu_in_2arr; + SIGNAL permu_out_2arr : t_dp_sosi_2arr_2(g_nof_outputs-1 DOWNTO 0); + +BEGIN + + ----------------------------------------------------------------------------- + -- Input wiring: copy the inputs g_nof_inputs times + ----------------------------------------------------------------------------- + gen_input: FOR i IN 0 TO g_nof_inputs-1 GENERATE + gen_input: FOR j IN 0 TO g_nof_inputs-1 GENERATE + permu_in_2arr(i)(j) <= snk_in_arr(i); + END GENERATE; + END GENERATE; + + ----------------------------------------------------------------------------- + -- Permutation wiring, 4-input example: + -- + -- 0 1 2 3 4 5 6 7 8 9 <-- permu_out_2arr[g_nof_outputs][2] + -- _ | | | | | | | | | | + -- |0|0-->[0] | | | | | | | | | + -- | |1------->[0] | | | | | | | | + -- | |2---------|-->[0] | | | | | | | + -- |_|3---------|----|-->[0] | | | | | | + -- |1|0------->[1] | | | | | | | | + -- | |1--------------|----|-->[1] | | | | | + -- | |2--------------|----|------->[1] | | | | + -- |_|3--------------|----|---------|-->[1] | | | + -- |2|0------------>[2] | | | | | | + -- | |1-------------------|------->[2] | | | | + -- | |2-------------------|--------------|-->[2] | | + -- |_|3-------------------|--------------|------->[2] | + -- |3|0----------------->[3] | | | + -- | |1-------------------------------->[3] | | + -- | |2------------------------------------------>[3] | + -- |_|3----------------------------------------------->[3] + -- ^ + -- | + -- permu_in_2arr[g_nof_inputs][g_nof_inputs] + -- + -- Observe the following: + -- . Inverse indexing: E.g. permutation[5], pair index 1 gets assigned + -- indices opposite to those of pair index 0: + -- . permu_out_2arr(5)(0) <= permu_in_arr(1)(2); + -- permu_out_2arr(5)(1) <= permu_in_arr(2)(1); + -- . The number of inputs that carry duplicates increments by one + -- for each input increment (only pair index 0 shown): + -- . permu_out_2arr(0)(0) <= permu_in_arr(0)(0); --permu_in_arr(0): 0 duplicates + -- permu_out_2arr(1)(0) <= permu_in_arr(0)(1); + -- permu_out_2arr(2)(0) <= permu_in_arr(0)(2); + -- permu_out_2arr(3)(0) <= permu_in_arr(0)(3); + -- -- Duplicate permu_in_arr(1)(0); --permu_in_arr(1): 1 duplicate + -- permu_out_2arr(4)(0) <= permu_in_arr(1)(1); + -- permu_out_2arr(5)(0) <= permu_in_arr(1)(2); + -- permu_out_2arr(6)(0) <= permu_in_arr(1)(3); + -- -- Duplicate permu_in_arr(2)(0); --permu_in_arr(2): 2 duplicates + -- -- Duplicate permu_in_arr(2)(1); + -- permu_out_2arr(7)(0) <= permu_in_arr(2)(2); + -- permu_out_2arr(8)(0) <= permu_in_arr(2)(3); + -- -- Duplicate permu_in_arr(3)(0); --permu_in_arr(3): 3 duplicates + -- -- Duplicate permu_in_arr(3)(1); + -- -- Duplicate permu_in_arr(3)(2); + -- permu_out_2arr(9)(0) <= permu_in_arr(3)(3); + ----------------------------------------------------------------------------- + p_permu_wires: PROCESS(permu_in_2arr) + VARIABLE v_out_index : NATURAL; + VARIABLE v_duplicates : NATURAL; + BEGIN + v_out_index := 0; + v_duplicates := 0; + FOR i IN 0 TO g_nof_inputs-1 LOOP + v_duplicates := i; + FOR j IN 0 TO g_nof_inputs-1 LOOP + permu_out_2arr(v_out_index)(0) <= permu_in_2arr(i)(j); + permu_out_2arr(v_out_index)(1) <= permu_in_2arr(j)(i); + IF v_duplicates = 0 THEN + -- We assigned a unique pair. Keep incrementing the index. + v_out_index := v_out_index+1; + ELSE + -- We just assigned a duplicate. Don't increment v_out_index so + -- that output will get re-assigned in the next loop iteration. + v_duplicates := v_duplicates-1; + END IF; + END LOOP; + END LOOP; + END PROCESS; + + ----------------------------------------------------------------------------- + -- Output wiring + ----------------------------------------------------------------------------- + src_out_2arr <= permu_out_2arr; + + + +END rtl; diff --git a/libraries/dsp/carousel_correlator/tb/vhdl/tb_permutator.vhd b/libraries/dsp/carousel_correlator/tb/vhdl/tb_permutator.vhd new file mode 100644 index 0000000000000000000000000000000000000000..6195750538749f3bf1f0d353f82719cfc1723eb3 --- /dev/null +++ b/libraries/dsp/carousel_correlator/tb/vhdl/tb_permutator.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_permutator IS + GENERIC ( + g_nof_inputs : NATURAL := 4; + g_nof_outputs : NATURAL := 10 + ); +END tb_permutator; + +ARCHITECTURE tb OF tb_permutator 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 permutator_snk_in_arr : t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); + SIGNAL permutator_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_permutator : ENTITY work.permutator + GENERIC MAP ( + g_nof_inputs => g_nof_inputs, + g_nof_outputs => g_nof_outputs + ) + PORT MAP ( + rst => rst, + clk => clk, + snk_in_arr => permutator_snk_in_arr, + src_out_2arr => permutator_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 permutator. Use the stream index as data word + permutator_snk_in_arr(j).data(c_data_w-1 DOWNTO 0) <= TO_UVEC(j, c_data_w); + permutator_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 permutator do its thing + permutator_snk_in_arr(j).data <= (OTHERS=>'0'); + permutator_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;