-------------------------------------------------------------
-- Filename:  CPM_MSD5.VHD
-- Authors: 
--		Alain Zarembowitch / MSS
-- Version: Rev 0
-- Last modified: 9/1/17

-- Inheritance: 	N/A
--
-- Algorithm: multi-symbol detection over 5 symbols. Written specifically for L=2
-- This non-coherent detection method is to be used whenever the modulation index varies (for example PCM/FM with h = 0.5 to 0.8
-- For modulation indices associated with a fixed phase constellation of 2pi/n, use coherent detection in conjunction with 
-- the Viterbi algorithm instead for better BER performance.
-- Maximum symbol rate: fclk/4
--
-- Registers: 3557 
-- LUTs: 8584
-- DSP48: 10
-- 18Kb block RAM: 4
--    Minimum period: 5.806ns (Maximum Frequency: 172.236MHz)  Artix-7 speed grade -1

---------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.CPM_MF_PKG.all;	-- defines types for this interface

entity CPM_MSD5 is
    Port ( 
		--GLOBAL CLOCK, RESET
		CLK   : in  std_logic;
		SYNC_RESET: in std_logic;	
			-- synchronous reset
			-- must use SYNC_RESET after changing the modulation scheme
		
		-- INPUT SAMPLES
		-- matched filters complex samples
		-- MPOWERLMAX complex numbers. Aligned with SYMBOL_CLK_IN_D8. CPM_MF_NBITS precision on both I and Q
		MF_I_IN: in MF_TYPE;
		MF_Q_IN: in MF_TYPE;
		MF_SYMBOL_CLK_IN: in std_logic;

		-- CONTROLS
		-- TEST TEST TEST
		INDEX_SEL: in std_logic_vector(2 downto 0);	-- for test purposes only
		COS_PIH: in std_logic_vector(7 downto 0);
		SIN_PIH: in std_logic_vector(7 downto 0);
			-- cos(pi*h) and sin(pi*h) to be used by multi-symbol detector to rotate the matched filter outputs
		COS_2PIH: in std_logic_vector(7 downto 0);
		SIN_2PIH: in std_logic_vector(7 downto 0);
			-- cos(2pi*h) and sin(2pi*h) to be used by multi-symbol detector to rotate the matched filter outputs

		-- DEMODULATED BIT
		SAMPLE_CLK_OUT: out std_logic;
		DATA_OUT: out std_logic_vector(3 downto 0);
			-- soft-decision output
		
		-- MONITORING
		-- comscope trace
		CS1: out std_logic_vector(7 downto 0);	
		CS1_CLK: out std_logic
		);
end entity;


architecture Behavioral of CPM_MSD5 is
-----------------------------------------------------------------
-- COMPONENTS
-----------------------------------------------------------------
	COMPONENT POLAR3_DUALMAG
	PORT(
		CLK : IN std_logic;
		XA_IN: in std_logic_vector(11 downto 0);
		YA_IN: in std_logic_vector(11 downto 0);
		SAMPLEA_CLK_IN: in std_logic;
		XB_IN: in std_logic_vector(11 downto 0);
		YB_IN: in std_logic_vector(11 downto 0);
		SAMPLEB_CLK_IN: in std_logic;
		MAGNITUDEA_OUT : OUT std_logic_vector(13 downto 0);
		SAMPLEA_CLK_OUT : OUT std_logic;
		MAGNITUDEB_OUT : OUT std_logic_vector(13 downto 0);
		SAMPLEB_CLK_OUT : OUT std_logic
		);
	END COMPONENT;
--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
signal MF1_I: MF_TYPE := (others => (others => '0'));
signal MF2_I: MF_TYPE := (others => (others => '0'));
signal MF3_I: MF_TYPE := (others => (others => '0'));
signal MF4_I: MF_TYPE := (others => (others => '0'));
signal MF1_Q: MF_TYPE := (others => (others => '0'));
signal MF2_Q: MF_TYPE := (others => (others => '0'));
signal MF3_Q: MF_TYPE := (others => (others => '0'));
signal MF4_Q: MF_TYPE := (others => (others => '0'));
signal MF1_I_D5: MF_TYPE := (others => (others => '0'));
signal MF2_I_D5: MF_TYPE := (others => (others => '0'));
signal MF4_I_D5: MF_TYPE := (others => (others => '0'));
signal MF1_Q_D5: MF_TYPE := (others => (others => '0'));
signal MF2_Q_D5: MF_TYPE := (others => (others => '0'));
signal MF3_Q_D5: MF_TYPE := (others => (others => '0'));
signal MF4_Q_D5: MF_TYPE := (others => (others => '0'));
signal MF_SYMBOL_CLK_IN_SHIFT: std_logic_vector(22 downto 1) := (others => '0');

signal MULT1A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT2A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT3A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT4A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT5A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT6A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT7A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT8A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT9A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT10A: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal MULT1B: signed(7 downto 0) := (others => '0');
signal MULT2B: signed(7 downto 0) := (others => '0');
signal MULT3B: signed(7 downto 0) := (others => '0');
signal MULT4B: signed(7 downto 0) := (others => '0');
signal MULT5B: signed(7 downto 0) := (others => '0');
signal MULT6B: signed(7 downto 0) := (others => '0');
signal MULT7B: signed(7 downto 0) := (others => '0');
signal MULT8B: signed(7 downto 0) := (others => '0');
signal MULT9B: signed(7 downto 0) := (others => '0');
signal MULT10B: signed(7 downto 0) := (others => '0');
signal MULT1: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT2: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT3: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT4: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT5: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT6: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT7: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT8: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT9: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal MULT10: signed(CPM_MF_NBITS+7 downto 0) := (others => '0');
signal ROT1_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT2_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT3_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT4_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT5_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT6_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT7_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT8_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT9_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT10_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT11_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT12_I: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT1_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT2_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT3_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT4_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT5_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT6_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT7_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT8_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT9_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT10_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT11_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');
signal ROT12_Q: signed(CPM_MF_NBITS-1 downto 0) := (others => '0');

type SUM_TYPE is array (integer range 0 to 31) of signed((CPM_MF_NBITS+1) downto 0);
signal SUM_I: SUM_TYPE := (others => (others => '0'));
signal SUM_Q: SUM_TYPE := (others => (others => '0'));
signal SUM_I_D9: SUM_TYPE := (others => (others => '0'));
signal SUM_Q_D9: SUM_TYPE := (others => (others => '0'));

signal POLAR1A_X_IN: signed(11 downto 0) := (others => '0');
signal POLAR1A_Y_IN: signed(11 downto 0) := (others => '0');
signal POLAR1B_X_IN: signed(11 downto 0) := (others => '0');
signal POLAR1B_Y_IN: signed(11 downto 0) := (others => '0');
signal POLAR_SAMPLE_CLK_IN: std_logic := '0';
signal POLAR1A_M: std_logic_vector(13 downto 0) := (others => '0');
signal POLAR1B_M: std_logic_vector(13 downto 0) := (others => '0');
signal POLAR2A_X_IN: signed(11 downto 0) := (others => '0');
signal POLAR2A_Y_IN: signed(11 downto 0) := (others => '0');
signal POLAR2B_X_IN: signed(11 downto 0) := (others => '0');
signal POLAR2B_Y_IN: signed(11 downto 0) := (others => '0');
signal POLAR2A_M: std_logic_vector(13 downto 0) := (others => '0');
signal POLAR2B_M: std_logic_vector(13 downto 0) := (others => '0');
signal POLAR3A_X_IN: signed(11 downto 0) := (others => '0');
signal POLAR3A_Y_IN: signed(11 downto 0) := (others => '0');
signal POLAR3B_X_IN: signed(11 downto 0) := (others => '0');
signal POLAR3B_Y_IN: signed(11 downto 0) := (others => '0');
signal POLAR3A_M: std_logic_vector(13 downto 0) := (others => '0');
signal POLAR3B_M: std_logic_vector(13 downto 0) := (others => '0');
signal POLAR4A_X_IN: signed(11 downto 0) := (others => '0');
signal POLAR4A_Y_IN: signed(11 downto 0) := (others => '0');
signal POLAR4B_X_IN: signed(11 downto 0) := (others => '0');
signal POLAR4B_Y_IN: signed(11 downto 0) := (others => '0');
signal POLAR4A_M: std_logic_vector(13 downto 0) := (others => '0');
signal POLAR4B_M: std_logic_vector(13 downto 0) := (others => '0');

signal MAX1: std_logic_vector(13 downto 0) := (others => '0');
signal MAX2: std_logic_vector(13 downto 0) := (others => '0');
signal MAX3: std_logic_vector(13 downto 0) := (others => '0');
signal MAX4: std_logic_vector(13 downto 0) := (others => '0');
signal MAX5: std_logic_vector(13 downto 0) := (others => '0');
signal MAX6: std_logic_vector(13 downto 0) := (others => '0');
signal MAX7: std_logic_vector(13 downto 0) := (others => '0');
signal MAX8: std_logic_vector(13 downto 0) := (others => '0');
signal MAX1_INDEX: std_logic_vector(0 downto 0) := (others => '0');
signal MAX2_INDEX: std_logic_vector(0 downto 0) := (others => '0');
signal MAX3_INDEX: std_logic_vector(0 downto 0) := (others => '0');
signal MAX4_INDEX: std_logic_vector(0 downto 0) := (others => '0');
signal MAX5_INDEX: std_logic_vector(1 downto 0) := (others => '0');
signal MAX6_INDEX: std_logic_vector(1 downto 0) := (others => '0');
signal MAX7_INDEX: std_logic_vector(2 downto 0) := (others => '0');
signal MAX8_INDEX: std_logic_vector(4 downto 0) := (others => '0');

-- TEST TEST TEST
signal INDEX_SEL_INT: integer range 0 to 4 := 0;
--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin

-- generate all delayed versions of the symbol clock
SYMBOL_CLK_GEN_001: process(CLK)
begin
	if rising_edge(CLK) then
		MF_SYMBOL_CLK_IN_SHIFT <= MF_SYMBOL_CLK_IN_SHIFT(21 downto 1) & MF_SYMBOL_CLK_IN;
	end if;
end process;

-- Store the matched filters values for all 3 previous symbols
-- MF1 (oldest), MF2 (center), MF3 (most recent)
STORE_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN = '1') then
			-- valid from MF_SYMBOL_CLK_IN_D to MF_SYMBOL_CLK_IN_SHIFT(4) included 
			MF4_I <= MF_I_IN;
			MF3_I <= MF4_I;
			MF2_I <= MF3_I;
			MF1_I <= MF2_I;
			MF4_Q <= MF_Q_IN;
			MF3_Q <= MF4_Q;
			MF2_Q <= MF3_Q;
			MF1_Q <= MF2_Q;
		end if;
		
		-- extend the storage while we compute the various phase rotations
		-- (the next set of match filters outputs could arrive as soon as MF_SYMBOL_CLK_IN_SHIFT(4))
		if(MF_SYMBOL_CLK_IN_SHIFT(4) = '1') then
			-- valid from MF_SYMBOL_CLK_IN_D5 to MF_SYMBOL_CLK_IN_D8 included 
			MF4_I_D5 <= MF4_I;
			MF2_I_D5 <= MF2_I;
			MF1_I_D5 <= MF1_I;
			MF4_Q_D5 <= MF4_Q;
			MF3_Q_D5 <= MF3_Q;
			MF2_Q_D5 <= MF2_Q;
			MF1_Q_D5 <= MF1_Q;
		end if;
		
		
	end if;
end process;

-- compute the rotated versions of the matched filters
-- MF1 (oldest): compute MF1(0)-2pi*h, MF1(1)+pi*h, MF1(2)-pi*h, MF1(3)+2pi*h
-- MF2 : compute MF2(0)-pi*h, MF2(3)+pi*h, MF2(1) and MF2(2) are not rotated
-- MF3 (not rotated)
-- MF4 (most recent): compute MF4(0)+pi*h, MF4(1)+pi*h,MF4(2)-pi*h, MF4(3)-pi*h
-- Since these 10 vector rotations have to be completed within 4 clocks, we need 10 multipliers
CMULT_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(1) = '1') then
			MULT1A <= signed(MF1_I(0));
			MULT1B <= signed(COS_2PIH);
			MULT2A <= signed(MF1_I(1));
			MULT2B <= signed(COS_PIH);
			MULT3A <= signed(MF1_I(2));
			MULT3B <= signed(COS_PIH);
			MULT4A <= signed(MF1_I(3));
			MULT4B <= signed(COS_2PIH);
			MULT5A <= signed(MF2_I(0));
			MULT5B <= signed(COS_PIH);
			MULT6A <= signed(MF2_I(3));
			MULT6B <= signed(COS_PIH);
			MULT7A <= signed(MF4_I(0));
			MULT7B <= signed(COS_PIH);
			MULT8A <= signed(MF4_I(1));
			MULT8B <= signed(COS_PIH);
			MULT9A <= signed(MF4_I(2));
			MULT9B <= signed(COS_PIH);
			MULT10A <= signed(MF4_I(3));
			MULT10B <= signed(COS_PIH);
		elsif(MF_SYMBOL_CLK_IN_SHIFT(2) = '1') then
			MULT1A <= signed(MF1_Q(0));
			MULT1B <= signed(SIN_2PIH);		-- MF1(00) -2pi*h
			MULT2A <= signed(MF1_Q(1));
			MULT2B <= -signed(SIN_PIH);		-- MF1(01) +pi*h
			MULT3A <= signed(MF1_Q(2));
			MULT3B <= signed(SIN_PIH);			-- MF1(10) -pi*h
			MULT4A <= signed(MF1_Q(3));
			MULT4B <= -signed(SIN_2PIH);		-- MF1(11) +2pi*h
			MULT5A <= signed(MF2_Q(0));
			MULT5B <= signed(SIN_PIH);			-- MF2(00) -pi*h
			MULT6A <= signed(MF2_Q(3));
			MULT6B <= -signed(SIN_PIH);		-- MF2(11) +pi*h
			MULT7A <= signed(MF4_Q(0));
			MULT7B <= -signed(SIN_PIH);		-- MF4(00) +pi*h
			MULT8A <= signed(MF4_Q(1));
			MULT8B <= -signed(SIN_PIH);		-- MF4(01) +pi*h
			MULT9A <= signed(MF4_Q(2));
			MULT9B <= signed(SIN_PIH);			-- MF4(10) -pi*h
			MULT10A <= signed(MF4_Q(3));
			MULT10B <= signed(SIN_PIH);		-- MF4(11) -pi*h
		elsif(MF_SYMBOL_CLK_IN_SHIFT(3) = '1') then
			MULT1A <= signed(MF1_I(0));
			MULT1B <= -signed(SIN_2PIH);		-- MF1(00) -2pi*h
			MULT2A <= signed(MF1_I(1));
			MULT2B <= signed(SIN_PIH);			-- MF1(01) +pi*h
			MULT3A <= signed(MF1_I(2));
			MULT3B <= -signed(SIN_PIH);		-- MF1(10) -pi*h
			MULT4A <= signed(MF1_I(3));
			MULT4B <= signed(SIN_2PIH);		-- MF1(11) +2pi*h
			MULT5A <= signed(MF2_I(0));
			MULT5B <= -signed(SIN_PIH);		-- MF2(00) -pi*h
			MULT6A <= signed(MF2_I(3));
			MULT6B <= signed(SIN_PIH);			-- MF2(11) +pi*h
			MULT7A <= signed(MF4_I(0));
			MULT7B <= signed(SIN_PIH);			-- MF4(00) +pi*h
			MULT8A <= signed(MF4_I(1));
			MULT8B <= signed(SIN_PIH);			-- MF4(01) +pi*h
			MULT9A <= signed(MF4_I(2));
			MULT9B <= -signed(SIN_PIH);		-- MF4(10) -pi*h
			MULT10A <= signed(MF4_I(3));
			MULT10B <= -signed(SIN_PIH);		-- MF4(11) -pi*h
		elsif(MF_SYMBOL_CLK_IN_SHIFT(4) = '1') then
			MULT1A <= signed(MF1_Q(0));
			MULT1B <= signed(COS_2PIH);		-- MF1(00) -2pi*h
			MULT2A <= signed(MF1_Q(1));
			MULT2B <= signed(COS_PIH);			-- MF1(01) +pi*h
			MULT3A <= signed(MF1_Q(2));
			MULT3B <= signed(COS_PIH);			-- MF1(10) -pi*h
			MULT4A <= signed(MF1_Q(3));
			MULT4B <= signed(COS_2PIH);		-- MF1(11) +2pi*h
			MULT5A <= signed(MF2_Q(0));
			MULT5B <= signed(COS_PIH);			-- MF2(00) -pi*h
			MULT6A <= signed(MF2_Q(3));
			MULT6B <= signed(COS_PIH);			-- MF2(11) +pi*h
			MULT7A <= signed(MF4_Q(0));
			MULT7B <= signed(COS_PIH);			-- MF4(00) +pi*h
			MULT8A <= signed(MF4_Q(1));
			MULT8B <= signed(COS_PIH);			-- MF4(01) +pi*h
			MULT9A <= signed(MF4_Q(2));
			MULT9B <= signed(COS_PIH);			-- MF4(10) -pi*h
			MULT10A <= signed(MF4_Q(3));
			MULT10B <= signed(COS_PIH);		-- MF4(11) -pi*h
		end if;
	end if;
end process;

MULT1 <= MULT1A * MULT1B;
MULT2 <= MULT2A * MULT2B;
MULT3 <= MULT3A * MULT3B;
MULT4 <= MULT4A * MULT4B;
MULT5 <= MULT5A * MULT5B;
MULT6 <= MULT6A * MULT6B;
MULT7 <= MULT7A * MULT7B;
MULT8 <= MULT8A * MULT8B;
MULT9 <= MULT9A * MULT9B;
MULT10 <= MULT10A * MULT10B;

CMULT_002: process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(2) = '1') then
			ROT1_I <= MULT1(CPM_MF_NBITS+6 downto 7);		-- MF1(00) -2pi*h
			ROT2_I <= MULT2(CPM_MF_NBITS+6 downto 7);		-- MF1(01) +pi*h
			ROT3_I <= MULT3(CPM_MF_NBITS+6 downto 7);		-- MF1(10) -pi*h
			ROT4_I <= MULT4(CPM_MF_NBITS+6 downto 7);		-- MF1(11) +2pi*h
			ROT5_I <= MULT5(CPM_MF_NBITS+6 downto 7);		-- MF2(00) -pi*h
			ROT6_I <= MULT6(CPM_MF_NBITS+6 downto 7);		-- MF2(11) +pi*h
			ROT7_I <= MULT7(CPM_MF_NBITS+6 downto 7);		-- MF4(00) +pi*h
			ROT8_I <= MULT8(CPM_MF_NBITS+6 downto 7);		-- MF4(01) +pi*h
			ROT9_I <= MULT9(CPM_MF_NBITS+6 downto 7);		-- MF4(10) -pi*h
			ROT10_I <= MULT10(CPM_MF_NBITS+6 downto 7);	-- MF4(11) -pi*h
		elsif(MF_SYMBOL_CLK_IN_SHIFT(3) = '1') then
			ROT1_I <= ROT1_I + MULT1(CPM_MF_NBITS+6 downto 7);
			ROT2_I <= ROT2_I + MULT2(CPM_MF_NBITS+6 downto 7);
			ROT3_I <= ROT3_I + MULT3(CPM_MF_NBITS+6 downto 7);
			ROT4_I <= ROT4_I + MULT4(CPM_MF_NBITS+6 downto 7);
			ROT5_I <= ROT5_I + MULT5(CPM_MF_NBITS+6 downto 7);
			ROT6_I <= ROT6_I + MULT6(CPM_MF_NBITS+6 downto 7);
			ROT7_I <= ROT7_I + MULT7(CPM_MF_NBITS+6 downto 7);
			ROT8_I <= ROT8_I + MULT8(CPM_MF_NBITS+6 downto 7);
			ROT9_I <= ROT9_I + MULT9(CPM_MF_NBITS+6 downto 7);
			ROT10_I <= ROT10_I + MULT10(CPM_MF_NBITS+6 downto 7);
		elsif(MF_SYMBOL_CLK_IN_SHIFT(6) = '1') then
			-- some MF1 rotations are just delayed versions of the previous symbol MF2
			ROT11_I <= ROT5_I;	-- MF1(00) -pi*h
			ROT12_I <= ROT6_I;	-- MF1(11) +pi*h
		end if;
		if(MF_SYMBOL_CLK_IN_SHIFT(4) = '1') then
			ROT1_Q <= MULT1(CPM_MF_NBITS+6 downto 7);
			ROT2_Q <= MULT2(CPM_MF_NBITS+6 downto 7);
			ROT3_Q <= MULT3(CPM_MF_NBITS+6 downto 7);
			ROT4_Q <= MULT4(CPM_MF_NBITS+6 downto 7);
			ROT5_Q <= MULT5(CPM_MF_NBITS+6 downto 7);
			ROT6_Q <= MULT6(CPM_MF_NBITS+6 downto 7);
			ROT7_Q <= MULT7(CPM_MF_NBITS+6 downto 7);
			ROT8_Q <= MULT8(CPM_MF_NBITS+6 downto 7);
			ROT9_Q <= MULT9(CPM_MF_NBITS+6 downto 7);
			ROT10_Q <= MULT10(CPM_MF_NBITS+6 downto 7);
		elsif(MF_SYMBOL_CLK_IN_SHIFT(5) = '1') then
			ROT1_Q <= ROT1_Q + MULT1(CPM_MF_NBITS+6 downto 7);
			ROT2_Q <= ROT2_Q + MULT2(CPM_MF_NBITS+6 downto 7);
			ROT3_Q <= ROT3_Q + MULT3(CPM_MF_NBITS+6 downto 7);
			ROT4_Q <= ROT4_Q + MULT4(CPM_MF_NBITS+6 downto 7);
			ROT5_Q <= ROT5_Q + MULT5(CPM_MF_NBITS+6 downto 7);
			ROT6_Q <= ROT6_Q + MULT6(CPM_MF_NBITS+6 downto 7);
			ROT7_Q <= ROT7_Q + MULT7(CPM_MF_NBITS+6 downto 7);
			ROT8_Q <= ROT8_Q + MULT8(CPM_MF_NBITS+6 downto 7);
			ROT9_Q <= ROT9_Q + MULT9(CPM_MF_NBITS+6 downto 7);
			ROT10_Q <= ROT10_Q + MULT10(CPM_MF_NBITS+6 downto 7);
		elsif(MF_SYMBOL_CLK_IN_SHIFT(8) = '1') then
			-- some MF1 rotations are just delayed versions of the previous symbol MF2
			ROT11_Q <= ROT5_Q;	-- MF1(00) -pi*h
			ROT12_Q <= ROT6_Q;	-- MF1(11) +pi*h
		end if;
	end if;
end process;

-- sum coherently for all 32 (5-bit) combinations
-- The 5-bit index represents the received bits hypothesis from earlier (bit0) to the latest(bit3)
-- Bits 0 & 1 are associated with the matched filter MF1
-- Bits 1 & 2 are associated with the matched filter MF2
-- Bits 2 & 3 are associated with the matched filter MF3
-- Bits 3 & 4 are associated with the matched filter MF4
CSUM_I_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(4) = '1') then
			SUM_I(0) <= resize(signed(MF3_I(0)),CPM_MF_NBITS+2) + ROT1_I;
			SUM_I(1) <= resize(signed(MF3_I(0)),CPM_MF_NBITS+2) + ROT1_I;
			SUM_I(2) <= resize(signed(MF3_I(1)),CPM_MF_NBITS+2) + ROT1_I;
			SUM_I(3) <= resize(signed(MF3_I(1)),CPM_MF_NBITS+2) + ROT1_I;
			SUM_I(4) <= resize(signed(MF3_I(2)),CPM_MF_NBITS+2) + ROT11_I; 
			SUM_I(5) <= resize(signed(MF3_I(2)),CPM_MF_NBITS+2) + ROT11_I;  
			SUM_I(6) <= resize(signed(MF3_I(3)),CPM_MF_NBITS+2) + ROT11_I; 
			SUM_I(7) <= resize(signed(MF3_I(3)),CPM_MF_NBITS+2) + ROT11_I; 
			SUM_I(8) <= resize(signed(MF3_I(0)),CPM_MF_NBITS+2) + resize(signed(MF1_I(1)),CPM_MF_NBITS+2);
			SUM_I(9) <= resize(signed(MF3_I(0)),CPM_MF_NBITS+2) + resize(signed(MF1_I(1)),CPM_MF_NBITS+2); 
			SUM_I(10) <= resize(signed(MF3_I(1)),CPM_MF_NBITS+2) + resize(signed(MF1_I(1)),CPM_MF_NBITS+2);
			SUM_I(11) <= resize(signed(MF3_I(1)),CPM_MF_NBITS+2) + resize(signed(MF1_I(1)),CPM_MF_NBITS+2);
			SUM_I(12) <= resize(signed(MF3_I(2)),CPM_MF_NBITS+2) + ROT2_I;
			SUM_I(13) <= resize(signed(MF3_I(2)),CPM_MF_NBITS+2) + ROT2_I;
			SUM_I(14) <= resize(signed(MF3_I(3)),CPM_MF_NBITS+2) + ROT2_I;
			SUM_I(15) <= resize(signed(MF3_I(3)),CPM_MF_NBITS+2) + ROT2_I;
			SUM_I(16) <= resize(signed(MF3_I(0)),CPM_MF_NBITS+2) + ROT3_I;
			SUM_I(17) <= resize(signed(MF3_I(0)),CPM_MF_NBITS+2) + ROT3_I;
			SUM_I(18) <= resize(signed(MF3_I(1)),CPM_MF_NBITS+2) + ROT3_I;
			SUM_I(19) <= resize(signed(MF3_I(1)),CPM_MF_NBITS+2) + ROT3_I;
			SUM_I(20) <= resize(signed(MF3_I(2)),CPM_MF_NBITS+2) + resize(signed(MF1_I(2)),CPM_MF_NBITS+2);
			SUM_I(21) <= resize(signed(MF3_I(2)),CPM_MF_NBITS+2) + resize(signed(MF1_I(2)),CPM_MF_NBITS+2);
			SUM_I(22) <= resize(signed(MF3_I(3)),CPM_MF_NBITS+2) + resize(signed(MF1_I(2)),CPM_MF_NBITS+2);
			SUM_I(23) <= resize(signed(MF3_I(3)),CPM_MF_NBITS+2) + resize(signed(MF1_I(2)),CPM_MF_NBITS+2);
			SUM_I(24) <= resize(signed(MF3_I(0)),CPM_MF_NBITS+2) + ROT12_I; 
			SUM_I(25) <= resize(signed(MF3_I(0)),CPM_MF_NBITS+2) + ROT12_I; 
			SUM_I(26) <= resize(signed(MF3_I(1)),CPM_MF_NBITS+2) + ROT12_I; 
			SUM_I(27) <= resize(signed(MF3_I(1)),CPM_MF_NBITS+2) + ROT12_I; 
			SUM_I(28) <= resize(signed(MF3_I(2)),CPM_MF_NBITS+2) + ROT4_I; 
			SUM_I(29) <= resize(signed(MF3_I(2)),CPM_MF_NBITS+2) + ROT4_I;
			SUM_I(30) <= resize(signed(MF3_I(3)),CPM_MF_NBITS+2) + ROT4_I;
			SUM_I(31) <= resize(signed(MF3_I(3)),CPM_MF_NBITS+2) + ROT4_I;
		elsif(MF_SYMBOL_CLK_IN_SHIFT(5) = '1') then
			SUM_I(0) <= SUM_I(0) + ROT5_I;
			SUM_I(1) <= SUM_I(1) + ROT5_I;
			SUM_I(2) <= SUM_I(2) + ROT5_I;
			SUM_I(3) <= SUM_I(3) + ROT5_I;
			SUM_I(4) <= SUM_I(4) + resize(signed(MF2_I_D5(1)),12);
			SUM_I(5) <= SUM_I(5) + resize(signed(MF2_I_D5(1)),12);
			SUM_I(6) <= SUM_I(6) + resize(signed(MF2_I_D5(1)),12);
			SUM_I(7) <= SUM_I(7) + resize(signed(MF2_I_D5(1)),12);
			SUM_I(8) <= SUM_I(8) + resize(signed(MF2_I_D5(2)),12);
			SUM_I(9) <= SUM_I(9) + resize(signed(MF2_I_D5(2)),12);
			SUM_I(10) <= SUM_I(10) + resize(signed(MF2_I_D5(2)),12);
			SUM_I(11) <= SUM_I(11) + resize(signed(MF2_I_D5(2)),12);
			SUM_I(12) <= SUM_I(12) + ROT6_I;
			SUM_I(13) <= SUM_I(13) + ROT6_I;
			SUM_I(14) <= SUM_I(14) + ROT6_I; 
			SUM_I(15) <= SUM_I(15) + ROT6_I; 
			SUM_I(16) <= SUM_I(16) + ROT5_I; 
			SUM_I(17) <= SUM_I(17) + ROT5_I; 
			SUM_I(18) <= SUM_I(18) + ROT5_I; 
			SUM_I(19) <= SUM_I(19) + ROT5_I; 
			SUM_I(20) <= SUM_I(20) + resize(signed(MF2_I_D5(1)),12); 
			SUM_I(21) <= SUM_I(21) + resize(signed(MF2_I_D5(1)),12); 
			SUM_I(22) <= SUM_I(22) + resize(signed(MF2_I_D5(1)),12); 
			SUM_I(23) <= SUM_I(23) + resize(signed(MF2_I_D5(1)),12); 
			SUM_I(24) <= SUM_I(24) + resize(signed(MF2_I_D5(2)),12);
			SUM_I(25) <= SUM_I(25) + resize(signed(MF2_I_D5(2)),12); 
			SUM_I(26) <= SUM_I(26) + resize(signed(MF2_I_D5(2)),12); 
			SUM_I(27) <= SUM_I(27) + resize(signed(MF2_I_D5(2)),12); 
			SUM_I(28) <= SUM_I(28) + ROT6_I; 
			SUM_I(29) <= SUM_I(29) + ROT6_I; 
			SUM_I(30) <= SUM_I(30) + ROT6_I; 
			SUM_I(31) <= SUM_I(31) + ROT6_I; 
		elsif(MF_SYMBOL_CLK_IN_SHIFT(6) = '1') then
			SUM_I(0) <= SUM_I(0) + ROT7_I;
			SUM_I(1) <= SUM_I(1) + ROT8_I;
			SUM_I(2) <= SUM_I(2) + resize(signed(MF4_I_D5(2)),12); 
			SUM_I(3) <= SUM_I(3) + resize(signed(MF4_I_D5(3)),12); 
			SUM_I(4) <= SUM_I(4) + resize(signed(MF4_I_D5(0)),12); 
			SUM_I(5) <= SUM_I(5) + resize(signed(MF4_I_D5(1)),12); 
			SUM_I(6) <= SUM_I(6) + ROT9_I;
			SUM_I(7) <= SUM_I(7) + ROT10_I;
			SUM_I(8) <= SUM_I(8) + ROT7_I;
			SUM_I(9) <= SUM_I(9) + ROT8_I;
			SUM_I(10) <= SUM_I(10) + resize(signed(MF4_I_D5(2)),12); 
			SUM_I(11) <= SUM_I(11) + resize(signed(MF4_I_D5(3)),12); 
			SUM_I(12) <= SUM_I(12) + resize(signed(MF4_I_D5(0)),12); 
			SUM_I(13) <= SUM_I(13) + resize(signed(MF4_I_D5(1)),12); 
			SUM_I(14) <= SUM_I(14) + ROT9_I;
			SUM_I(15) <= SUM_I(15) + ROT10_I;
			SUM_I(16) <= SUM_I(16) + ROT7_I;
			SUM_I(17) <= SUM_I(17) + ROT8_I;
			SUM_I(18) <= SUM_I(18) + resize(signed(MF4_I_D5(2)),12); 
			SUM_I(19) <= SUM_I(19) + resize(signed(MF4_I_D5(3)),12); 
			SUM_I(20) <= SUM_I(20) + resize(signed(MF4_I_D5(0)),12); 
			SUM_I(21) <= SUM_I(21) + resize(signed(MF4_I_D5(1)),12); 
			SUM_I(22) <= SUM_I(22) + ROT9_I;
			SUM_I(23) <= SUM_I(23) + ROT10_I;
			SUM_I(24) <= SUM_I(24) + ROT7_I;
			SUM_I(25) <= SUM_I(25) + ROT8_I;
			SUM_I(26) <= SUM_I(26) + resize(signed(MF4_I_D5(2)),12); 
			SUM_I(27) <= SUM_I(27) + resize(signed(MF4_I_D5(3)),12); 
			SUM_I(28) <= SUM_I(28) + resize(signed(MF4_I_D5(0)),12); 
			SUM_I(29) <= SUM_I(29) + resize(signed(MF4_I_D5(1)),12); 
			SUM_I(30) <= SUM_I(30) + ROT9_I; 
			SUM_I(31) <= SUM_I(31) + ROT10_I;
		end if;
		if(MF_SYMBOL_CLK_IN_SHIFT(8) = '1') then
			for I in 0 to 31 loop
				SUM_I_D9(I) <= SUM_I(I);
			end loop;
		end if;
	end if;
end process;


CSUM_Q_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(6) = '1') then
			SUM_Q(0) <= resize(signed(MF3_Q_D5(0)),CPM_MF_NBITS+2) + ROT1_Q;
			SUM_Q(1) <= resize(signed(MF3_Q_D5(0)),CPM_MF_NBITS+2) + ROT1_Q;
			SUM_Q(2) <= resize(signed(MF3_Q_D5(1)),CPM_MF_NBITS+2) + ROT1_Q;
			SUM_Q(3) <= resize(signed(MF3_Q_D5(1)),CPM_MF_NBITS+2) + ROT1_Q;
			SUM_Q(4) <= resize(signed(MF3_Q_D5(2)),CPM_MF_NBITS+2) + ROT11_Q; 
			SUM_Q(5) <= resize(signed(MF3_Q_D5(2)),CPM_MF_NBITS+2) + ROT11_Q;  
			SUM_Q(6) <= resize(signed(MF3_Q_D5(3)),CPM_MF_NBITS+2) + ROT11_Q; 
			SUM_Q(7) <= resize(signed(MF3_Q_D5(3)),CPM_MF_NBITS+2) + ROT11_Q; 
			SUM_Q(8) <= resize(signed(MF3_Q_D5(0)),CPM_MF_NBITS+2) + resize(signed(MF1_Q_D5(1)),CPM_MF_NBITS+2);
			SUM_Q(9) <= resize(signed(MF3_Q_D5(0)),CPM_MF_NBITS+2) + resize(signed(MF1_Q_D5(1)),CPM_MF_NBITS+2); 
			SUM_Q(10) <= resize(signed(MF3_Q_D5(1)),CPM_MF_NBITS+2) + resize(signed(MF1_Q_D5(1)),CPM_MF_NBITS+2);
			SUM_Q(11) <= resize(signed(MF3_Q_D5(1)),CPM_MF_NBITS+2) + resize(signed(MF1_Q_D5(1)),CPM_MF_NBITS+2);
			SUM_Q(12) <= resize(signed(MF3_Q_D5(2)),CPM_MF_NBITS+2) + ROT2_Q;
			SUM_Q(13) <= resize(signed(MF3_Q_D5(2)),CPM_MF_NBITS+2) + ROT2_Q;
			SUM_Q(14) <= resize(signed(MF3_Q_D5(3)),CPM_MF_NBITS+2) + ROT2_Q;
			SUM_Q(15) <= resize(signed(MF3_Q_D5(3)),CPM_MF_NBITS+2) + ROT2_Q;
			SUM_Q(16) <= resize(signed(MF3_Q_D5(0)),CPM_MF_NBITS+2) + ROT3_Q;
			SUM_Q(17) <= resize(signed(MF3_Q_D5(0)),CPM_MF_NBITS+2) + ROT3_Q;
			SUM_Q(18) <= resize(signed(MF3_Q_D5(1)),CPM_MF_NBITS+2) + ROT3_Q;
			SUM_Q(19) <= resize(signed(MF3_Q_D5(1)),CPM_MF_NBITS+2) + ROT3_Q;
			SUM_Q(20) <= resize(signed(MF3_Q_D5(2)),CPM_MF_NBITS+2) + resize(signed(MF1_Q_D5(2)),CPM_MF_NBITS+2);
			SUM_Q(21) <= resize(signed(MF3_Q_D5(2)),CPM_MF_NBITS+2) + resize(signed(MF1_Q_D5(2)),CPM_MF_NBITS+2);
			SUM_Q(22) <= resize(signed(MF3_Q_D5(3)),CPM_MF_NBITS+2) + resize(signed(MF1_Q_D5(2)),CPM_MF_NBITS+2);
			SUM_Q(23) <= resize(signed(MF3_Q_D5(3)),CPM_MF_NBITS+2) + resize(signed(MF1_Q_D5(2)),CPM_MF_NBITS+2);
			SUM_Q(24) <= resize(signed(MF3_Q_D5(0)),CPM_MF_NBITS+2) + ROT12_Q; 
			SUM_Q(25) <= resize(signed(MF3_Q_D5(0)),CPM_MF_NBITS+2) + ROT12_Q; 
			SUM_Q(26) <= resize(signed(MF3_Q_D5(1)),CPM_MF_NBITS+2) + ROT12_Q; 
			SUM_Q(27) <= resize(signed(MF3_Q_D5(1)),CPM_MF_NBITS+2) + ROT12_Q; 
			SUM_Q(28) <= resize(signed(MF3_Q_D5(2)),CPM_MF_NBITS+2) + ROT4_Q; 
			SUM_Q(29) <= resize(signed(MF3_Q_D5(2)),CPM_MF_NBITS+2) + ROT4_Q;
			SUM_Q(30) <= resize(signed(MF3_Q_D5(3)),CPM_MF_NBITS+2) + ROT4_Q;
			SUM_Q(31) <= resize(signed(MF3_Q_D5(3)),CPM_MF_NBITS+2) + ROT4_Q;
		elsif(MF_SYMBOL_CLK_IN_SHIFT(7) = '1') then
			SUM_Q(0) <= SUM_Q(0) + ROT5_Q;
			SUM_Q(1) <= SUM_Q(1) + ROT5_Q;
			SUM_Q(2) <= SUM_Q(2) + ROT5_Q;
			SUM_Q(3) <= SUM_Q(3) + ROT5_Q;
			SUM_Q(4) <= SUM_Q(4) + resize(signed(MF2_Q_D5(1)),12);
			SUM_Q(5) <= SUM_Q(5) + resize(signed(MF2_Q_D5(1)),12);
			SUM_Q(6) <= SUM_Q(6) + resize(signed(MF2_Q_D5(1)),12);
			SUM_Q(7) <= SUM_Q(7) + resize(signed(MF2_Q_D5(1)),12);
			SUM_Q(8) <= SUM_Q(8) + resize(signed(MF2_Q_D5(2)),12);
			SUM_Q(9) <= SUM_Q(9) + resize(signed(MF2_Q_D5(2)),12);
			SUM_Q(10) <= SUM_Q(10) + resize(signed(MF2_Q_D5(2)),12);
			SUM_Q(11) <= SUM_Q(11) + resize(signed(MF2_Q_D5(2)),12);
			SUM_Q(12) <= SUM_Q(12) + ROT6_Q;
			SUM_Q(13) <= SUM_Q(13) + ROT6_Q;
			SUM_Q(14) <= SUM_Q(14) + ROT6_Q; 
			SUM_Q(15) <= SUM_Q(15) + ROT6_Q; 
			SUM_Q(16) <= SUM_Q(16) + ROT5_Q; 
			SUM_Q(17) <= SUM_Q(17) + ROT5_Q; 
			SUM_Q(18) <= SUM_Q(18) + ROT5_Q; 
			SUM_Q(19) <= SUM_Q(19) + ROT5_Q; 
			SUM_Q(20) <= SUM_Q(20) + resize(signed(MF2_Q_D5(1)),12); 
			SUM_Q(21) <= SUM_Q(21) + resize(signed(MF2_Q_D5(1)),12); 
			SUM_Q(22) <= SUM_Q(22) + resize(signed(MF2_Q_D5(1)),12); 
			SUM_Q(23) <= SUM_Q(23) + resize(signed(MF2_Q_D5(1)),12); 
			SUM_Q(24) <= SUM_Q(24) + resize(signed(MF2_Q_D5(2)),12);
			SUM_Q(25) <= SUM_Q(25) + resize(signed(MF2_Q_D5(2)),12); 
			SUM_Q(26) <= SUM_Q(26) + resize(signed(MF2_Q_D5(2)),12); 
			SUM_Q(27) <= SUM_Q(27) + resize(signed(MF2_Q_D5(2)),12); 
			SUM_Q(28) <= SUM_Q(28) + ROT6_Q; 
			SUM_Q(29) <= SUM_Q(29) + ROT6_Q; 
			SUM_Q(30) <= SUM_Q(30) + ROT6_Q; 
			SUM_Q(31) <= SUM_Q(31) + ROT6_Q; 
		elsif(MF_SYMBOL_CLK_IN_SHIFT(8) = '1') then
			SUM_Q_D9(0) <= SUM_Q(0) + ROT7_Q;
			SUM_Q_D9(1) <= SUM_Q(1) + ROT8_Q;
			SUM_Q_D9(2) <= SUM_Q(2) + resize(signed(MF4_Q_D5(2)),12); 
			SUM_Q_D9(3) <= SUM_Q(3) + resize(signed(MF4_Q_D5(3)),12); 
			SUM_Q_D9(4) <= SUM_Q(4) + resize(signed(MF4_Q_D5(0)),12); 
			SUM_Q_D9(5) <= SUM_Q(5) + resize(signed(MF4_Q_D5(1)),12); 
			SUM_Q_D9(6) <= SUM_Q(6) + ROT9_Q;
			SUM_Q_D9(7) <= SUM_Q(7) + ROT10_Q;
			SUM_Q_D9(8) <= SUM_Q(8) + ROT7_Q;
			SUM_Q_D9(9) <= SUM_Q(9) + ROT8_Q;
			SUM_Q_D9(10) <= SUM_Q(10) + resize(signed(MF4_Q_D5(2)),12); 
			SUM_Q_D9(11) <= SUM_Q(11) + resize(signed(MF4_Q_D5(3)),12); 
			SUM_Q_D9(12) <= SUM_Q(12) + resize(signed(MF4_Q_D5(0)),12); 
			SUM_Q_D9(13) <= SUM_Q(13) + resize(signed(MF4_Q_D5(1)),12); 
			SUM_Q_D9(14) <= SUM_Q(14) + ROT9_Q;
			SUM_Q_D9(15) <= SUM_Q(15) + ROT10_Q;
			SUM_Q_D9(16) <= SUM_Q(16) + ROT7_Q;
			SUM_Q_D9(17) <= SUM_Q(17) + ROT8_Q;
			SUM_Q_D9(18) <= SUM_Q(18) + resize(signed(MF4_Q_D5(2)),12); 
			SUM_Q_D9(19) <= SUM_Q(19) + resize(signed(MF4_Q_D5(3)),12); 
			SUM_Q_D9(20) <= SUM_Q(20) + resize(signed(MF4_Q_D5(0)),12); 
			SUM_Q_D9(21) <= SUM_Q(21) + resize(signed(MF4_Q_D5(1)),12); 
			SUM_Q_D9(22) <= SUM_Q(22) + ROT9_Q;
			SUM_Q_D9(23) <= SUM_Q(23) + ROT10_Q;
			SUM_Q_D9(24) <= SUM_Q(24) + ROT7_Q;
			SUM_Q_D9(25) <= SUM_Q(25) + ROT8_Q;
			SUM_Q_D9(26) <= SUM_Q(26) + resize(signed(MF4_Q_D5(2)),12); 
			SUM_Q_D9(27) <= SUM_Q(27) + resize(signed(MF4_Q_D5(3)),12); 
			SUM_Q_D9(28) <= SUM_Q(28) + resize(signed(MF4_Q_D5(0)),12); 
			SUM_Q_D9(29) <= SUM_Q(29) + resize(signed(MF4_Q_D5(1)),12); 
			SUM_Q_D9(30) <= SUM_Q(30) + ROT9_Q; 
			SUM_Q_D9(31) <= SUM_Q(31) + ROT10_Q;
		end if;
	end if;
end process;

-- Input mux before magnitude lut
MAG_MUX_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(9) = '1') then
			POLAR1A_X_IN <= resize(SUM_I_D9(0),12);
			POLAR1A_Y_IN <= resize(SUM_Q_D9(0),12);
			POLAR1B_X_IN <= resize(SUM_I_D9(1),12);
			POLAR1B_Y_IN <= resize(SUM_Q_D9(1),12);
			POLAR2A_X_IN <= resize(SUM_I_D9(2),12);
			POLAR2A_Y_IN <= resize(SUM_Q_D9(2),12);
			POLAR2B_X_IN <= resize(SUM_I_D9(3),12);
			POLAR2B_Y_IN <= resize(SUM_Q_D9(3),12);
			POLAR3A_X_IN <= resize(SUM_I_D9(4),12);
			POLAR3A_Y_IN <= resize(SUM_Q_D9(4),12);
			POLAR3B_X_IN <= resize(SUM_I_D9(5),12);
			POLAR3B_Y_IN <= resize(SUM_Q_D9(5),12);
			POLAR4A_X_IN <= resize(SUM_I_D9(6),12);
			POLAR4A_Y_IN <= resize(SUM_Q_D9(6),12);
			POLAR4B_X_IN <= resize(SUM_I_D9(7),12);
			POLAR4B_Y_IN <= resize(SUM_Q_D9(7),12);
		elsif(MF_SYMBOL_CLK_IN_SHIFT(10) = '1') then
			POLAR1A_X_IN <= resize(SUM_I_D9(8),12);
			POLAR1A_Y_IN <= resize(SUM_Q_D9(8),12);
			POLAR1B_X_IN <= resize(SUM_I_D9(9),12);
			POLAR1B_Y_IN <= resize(SUM_Q_D9(9),12);
			POLAR2A_X_IN <= resize(SUM_I_D9(10),12);
			POLAR2A_Y_IN <= resize(SUM_Q_D9(10),12);
			POLAR2B_X_IN <= resize(SUM_I_D9(11),12);
			POLAR2B_Y_IN <= resize(SUM_Q_D9(11),12);
			POLAR3A_X_IN <= resize(SUM_I_D9(12),12);
			POLAR3A_Y_IN <= resize(SUM_Q_D9(12),12);
			POLAR3B_X_IN <= resize(SUM_I_D9(13),12);
			POLAR3B_Y_IN <= resize(SUM_Q_D9(13),12);
			POLAR4A_X_IN <= resize(SUM_I_D9(14),12);
			POLAR4A_Y_IN <= resize(SUM_Q_D9(14),12);
			POLAR4B_X_IN <= resize(SUM_I_D9(15),12);
			POLAR4B_Y_IN <= resize(SUM_Q_D9(15),12);
		elsif(MF_SYMBOL_CLK_IN_SHIFT(11) = '1') then
			POLAR1A_X_IN <= resize(SUM_I_D9(16),12);
			POLAR1A_Y_IN <= resize(SUM_Q_D9(16),12);
			POLAR1B_X_IN <= resize(SUM_I_D9(17),12);
			POLAR1B_Y_IN <= resize(SUM_Q_D9(17),12);
			POLAR2A_X_IN <= resize(SUM_I_D9(18),12);
			POLAR2A_Y_IN <= resize(SUM_Q_D9(18),12);
			POLAR2B_X_IN <= resize(SUM_I_D9(19),12);
			POLAR2B_Y_IN <= resize(SUM_Q_D9(19),12);
			POLAR3A_X_IN <= resize(SUM_I_D9(20),12);
			POLAR3A_Y_IN <= resize(SUM_Q_D9(20),12);
			POLAR3B_X_IN <= resize(SUM_I_D9(21),12);
			POLAR3B_Y_IN <= resize(SUM_Q_D9(21),12);
			POLAR4A_X_IN <= resize(SUM_I_D9(22),12);
			POLAR4A_Y_IN <= resize(SUM_Q_D9(22),12);
			POLAR4B_X_IN <= resize(SUM_I_D9(23),12);
			POLAR4B_Y_IN <= resize(SUM_Q_D9(23),12);
		elsif(MF_SYMBOL_CLK_IN_SHIFT(12) = '1') then
			POLAR1A_X_IN <= resize(SUM_I_D9(24),12);
			POLAR1A_Y_IN <= resize(SUM_Q_D9(24),12);
			POLAR1B_X_IN <= resize(SUM_I_D9(25),12);
			POLAR1B_Y_IN <= resize(SUM_Q_D9(25),12);
			POLAR2A_X_IN <= resize(SUM_I_D9(26),12);
			POLAR2A_Y_IN <= resize(SUM_Q_D9(26),12);
			POLAR2B_X_IN <= resize(SUM_I_D9(27),12);
			POLAR2B_Y_IN <= resize(SUM_Q_D9(27),12);
			POLAR3A_X_IN <= resize(SUM_I_D9(28),12);
			POLAR3A_Y_IN <= resize(SUM_Q_D9(28),12);
			POLAR3B_X_IN <= resize(SUM_I_D9(29),12);
			POLAR3B_Y_IN <= resize(SUM_Q_D9(29),12);
			POLAR4A_X_IN <= resize(SUM_I_D9(30),12);
			POLAR4A_Y_IN <= resize(SUM_Q_D9(30),12);
			POLAR4B_X_IN <= resize(SUM_I_D9(31),12);
			POLAR4B_Y_IN <= resize(SUM_Q_D9(31),12);
		end if;
	end if;
end process;

-- Complex/Real input to magnitude
-- Latency: 5 CLK
POLAR_SAMPLE_CLK_IN <= MF_SYMBOL_CLK_IN_SHIFT(10) or MF_SYMBOL_CLK_IN_SHIFT(11) or MF_SYMBOL_CLK_IN_SHIFT(12) or MF_SYMBOL_CLK_IN_SHIFT(13);
POLAR3_DUALMAG_001: POLAR3_DUALMAG PORT MAP(
	CLK => CLK,
	XA_IN => std_logic_vector(POLAR1A_X_IN),
	YA_IN => std_logic_vector(POLAR1A_Y_IN),
	SAMPLEA_CLK_IN => POLAR_SAMPLE_CLK_IN,
	XB_IN => std_logic_vector(POLAR1B_X_IN),
	YB_IN => std_logic_vector(POLAR1B_Y_IN),
	SAMPLEB_CLK_IN => POLAR_SAMPLE_CLK_IN,
	MAGNITUDEA_OUT => POLAR1A_M,	-- sqrt(X_IN(13:0)^2 + Y_IN(13:0)^2)
	SAMPLEA_CLK_OUT => open, 
	MAGNITUDEB_OUT => POLAR1B_M,	-- sqrt(X_IN(13:0)^2 + Y_IN(13:0)^2)
	SAMPLEB_CLK_OUT => open 
);

POLAR3_DUALMAG_002: POLAR3_DUALMAG PORT MAP(
	CLK => CLK,
	XA_IN => std_logic_vector(POLAR2A_X_IN),
	YA_IN => std_logic_vector(POLAR2A_Y_IN),
	SAMPLEA_CLK_IN => POLAR_SAMPLE_CLK_IN,
	XB_IN => std_logic_vector(POLAR2B_X_IN),
	YB_IN => std_logic_vector(POLAR2B_Y_IN),
	SAMPLEB_CLK_IN => POLAR_SAMPLE_CLK_IN,
	MAGNITUDEA_OUT => POLAR2A_M,	-- sqrt(X_IN(13:0)^2 + Y_IN(13:0)^2)
	SAMPLEA_CLK_OUT => open, 
	MAGNITUDEB_OUT => POLAR2B_M,	-- sqrt(X_IN(13:0)^2 + Y_IN(13:0)^2)
	SAMPLEB_CLK_OUT => open 
);

POLAR3_DUALMAG_003: POLAR3_DUALMAG PORT MAP(
	CLK => CLK,
	XA_IN => std_logic_vector(POLAR3A_X_IN),
	YA_IN => std_logic_vector(POLAR3A_Y_IN),
	SAMPLEA_CLK_IN => POLAR_SAMPLE_CLK_IN,
	XB_IN => std_logic_vector(POLAR3B_X_IN),
	YB_IN => std_logic_vector(POLAR3B_Y_IN),
	SAMPLEB_CLK_IN => POLAR_SAMPLE_CLK_IN,
	MAGNITUDEA_OUT => POLAR3A_M,	-- sqrt(X_IN(13:0)^2 + Y_IN(13:0)^2)
	SAMPLEA_CLK_OUT => open, 
	MAGNITUDEB_OUT => POLAR3B_M,	-- sqrt(X_IN(13:0)^2 + Y_IN(13:0)^2)
	SAMPLEB_CLK_OUT => open 
);

POLAR3_DUALMAG_004: POLAR3_DUALMAG PORT MAP(
	CLK => CLK,
	XA_IN => std_logic_vector(POLAR4A_X_IN),
	YA_IN => std_logic_vector(POLAR4A_Y_IN),
	SAMPLEA_CLK_IN => POLAR_SAMPLE_CLK_IN,
	XB_IN => std_logic_vector(POLAR4B_X_IN),
	YB_IN => std_logic_vector(POLAR4B_Y_IN),
	SAMPLEB_CLK_IN => POLAR_SAMPLE_CLK_IN,
	MAGNITUDEA_OUT => POLAR4A_M,	-- sqrt(X_IN(13:0)^2 + Y_IN(13:0)^2)
	SAMPLEA_CLK_OUT => open, 
	MAGNITUDEB_OUT => POLAR4B_M,	-- sqrt(X_IN(13:0)^2 + Y_IN(13:0)^2)
	SAMPLEB_CLK_OUT => open 
);

-- find the max magnitude and the associated 5-bit sequence. Pipeline for speed.
-- Best of two
MAX_001:  process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(18 downto 15) /= "0000") then
			if(POLAR1A_M > POLAR1B_M) then
				MAX1 <= POLAR1A_M;
				MAX1_INDEX <= "0";
			else
				MAX1 <= POLAR1B_M;
				MAX1_INDEX <= "1";
			end if;
			if(POLAR2A_M > POLAR2B_M) then
				MAX2 <= POLAR2A_M;
				MAX2_INDEX <= "0";
			else
				MAX2 <= POLAR2B_M;
				MAX2_INDEX <= "1";
			end if;
			if(POLAR3A_M > POLAR3B_M) then
				MAX3 <= POLAR3A_M;
				MAX3_INDEX <= "0";
			else
				MAX3 <= POLAR3B_M;
				MAX3_INDEX <= "1";
			end if;
			if(POLAR4A_M > POLAR4B_M) then
				MAX4 <= POLAR4A_M;
				MAX4_INDEX <= "0";
			else
				MAX4 <= POLAR4B_M;
				MAX4_INDEX <= "1";
			end if;
		end if;
	end if;
end process;

-- best of 4
MAX_002:  process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(19 downto 16) /= "0000") then
			if(MAX1 > MAX2) then
				MAX5 <= MAX1;
				MAX5_INDEX <= "0" & MAX1_INDEX;
			else
				MAX5 <= MAX2;
				MAX5_INDEX <= "1" & MAX2_INDEX;
			end if;
			if(MAX3 > MAX4) then
				MAX6 <= MAX3;
				MAX6_INDEX <= "0" & MAX3_INDEX;
			else
				MAX6 <= MAX4;
				MAX6_INDEX <= "1" & MAX4_INDEX;
			end if;
		end if;
	end if;
end process;

-- best of 8
MAX_003:  process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(20 downto 17) /= "0000") then
			if(MAX5 > MAX6) then
				MAX7 <= MAX5;
				MAX7_INDEX <= "0" & MAX5_INDEX;
			else
				MAX7 <= MAX6;
				MAX7_INDEX <= "1" & MAX6_INDEX;
			end if;
		end if;
	end if;
end process;

-- best of 32
MAX_004: process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(18) = '1') then
			MAX8 <= MAX7;
			MAX8_INDEX <= "00" & MAX7_INDEX;
		elsif(MF_SYMBOL_CLK_IN_SHIFT(19) = '1') and (MAX7 > MAX8) then
			MAX8 <= MAX7;
			MAX8_INDEX <= "01" & MAX7_INDEX;
		elsif(MF_SYMBOL_CLK_IN_SHIFT(20) = '1') and (MAX7 > MAX8) then
			MAX8 <= MAX7;
			MAX8_INDEX <= "10" & MAX7_INDEX;
		elsif(MF_SYMBOL_CLK_IN_SHIFT(21) = '1') and (MAX7 > MAX8) then
			MAX8 <= MAX7;
			MAX8_INDEX <= "11" & MAX7_INDEX;
		end if;
	end if;
end process;

-- Select demodulated bit
INDEX_SEL_INT <= to_integer(unsigned(INDEX_SEL));	-- TEST TEST TEST




DEMOD_BIT_GEN_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(MF_SYMBOL_CLK_IN_SHIFT(22) = '1') then
			SAMPLE_CLK_OUT <= '1';
			DATA_OUT(3) <= MAX8_INDEX(INDEX_SEL_INT);	-- demodulated bit
				-- best index is 2 (TBC THROUGH BER TESTING)
			-- soft decision. Best quality when MAX8 > 4096
			if(unsigned(MAX8) > 4096) then
				DATA_OUT(2 downto 0) <= (others => MAX8_INDEX(INDEX_SEL_INT));
			elsif(MAX8_INDEX(INDEX_SEL_INT) = '0') then
				DATA_OUT(2 downto 0) <= not MAX8(11 downto 9);
			else
				DATA_OUT(2 downto 0) <= MAX8(11 downto 9);
			end if;
		else
			SAMPLE_CLK_OUT <= '0';
		end if;
	end if;
end process;


-- Monitoring 
-- Comscope trace
COMSCOPE_001: process(CLK)
begin
	if rising_edge(CLK) then
		CS1_CLK <= MF_SYMBOL_CLK_IN_SHIFT(22);

		if(MF_SYMBOL_CLK_IN_SHIFT(22) = '1') then
			CS1 <= MAX8(12 downto 5);
		end if;
	end if;
end process;
end Behavioral;
