----------------------------------------------
-- MSS copyright 1999-2017
-- Filename: POLAR3.VHD
-- Authors: 	Alain Zarembowitch / MSS
-- 		Bengt Bengtsson / MSS
--		Adam Kwiatkowski / MSS
--		Poornima Sarvadevabahatla / MSS
-- Edit date:  4/29/17
-- Revision: 5
-- Inheritance: POLAR2.VHD
--
-- Returns the phase of the complex sample and the magnitude.
-- Latency is 5 CLKs.  Uses two 18Kbit RAMBLOCKs.
--
-- POLAR2.VHD Rev 0 AK 8-25-05
-- Replaced 4 RAMB4 by one RAMB16. 
-- One more precision bit on the output for phase and magnitude.
-- Independent phase/magnitude read as the memory is dual port.
-- POLAR3.VHD Rev 0 AK 10-24-05
-- Replaced 4 RAMB4 by two RAMB16. 
-- 4x the accuracy for both phase and magnitude.
-- Latency is now 5 CLKs.
--
-- POLAR3.VHD Rev 1 PS 07-05-06
-- MAGNITUDE_OUT is based on NO_OF_SHIFTS_D2 and MAGNITUDE_RANGE_0_175
-- instead of NO_OF_SHIFTS_D4 and MAGNITUDE_RANGE_0_175_D2
--
-- Synchronized with COM-1431 and stored in the common pool
-- \\c12\C\1software\source MSS\VHDL\Common Code Repository
-- Need to sync with atleast the following:
-- COM1229, COM1232, L3
-- and wherever POLAR3 rev 0 has been used
--
-- Rev2 AZ, 08/12/06
-- Removed an anomaly in magnitude table at address 0x7FF
-- Don't forget to update the magnitude simulation table accordingly: simulationRAMB16_S9MAG
-- Restore symmetry in the LUT_ADDR_GEN_001 address generation process.          
-- Corrected x2 scaling error in x_ABS_Q generation when NO_OF_SHIFTS = 0
--
-- Rev3 AZ 05/25/08 
-- Reversed previous change in 'anomaly in magnitude table at address 0x7FF'
-- Was causing serious perturbations in AGC when input saturates.     
--
-- Rev4 6/15/11 AZ
-- editorial: cleaned older references (RAMB16_S9PHASE, RAMB16_S9MAG) to separate simulation rambs. 
-- No longer needed since we use unisim.
--
-- Rev5 4/29/17 AZ
-- made portable using inferred ROM.
----------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
entity POLAR3 is port (  
		--// CLOCK, RESET
		CLK: in std_logic;
			-- Reference clock, synchronous design.

		--// INPUTS 
		X_IN: in std_logic_vector(11 downto 0);
		Y_IN: in std_logic_vector(11 downto 0);
			-- real and imaginary input sample
			-- 2's complement
		SAMPLE_CLK_IN: in std_logic;
			-- read input complex sample at rising_edge of CLK when SAMPLE_CLK_IN = '1'

		--// OUTPUTS
		PHASE_OUT: out std_logic_vector(10 downto 0) :="00000000000";
			-- phase expressed as 0 - 360 deg unsigned, 0.175 deg steps
		MAGNITUDE_OUT: out std_logic_vector(13 downto 0) := "00000000000000";
			-- 4 x the true magnitude in unsigned representation (if you want
			-- signed simply add a zero before the MSb because a magnitude
			-- is always positive). To get the true scale the divide this
			-- number by four (or simply chop off the two least significant
			-- bits). 
		SAMPLE_CLK_OUT: out std_logic := '0'
			-- read output at rising_edge of CLK when SAMPLE_CLK_OUT = '1'
			-- Latency is 5 CLKs.
 );
end entity;  

architecture Behavior of POLAR3 is
-----------------------------------------------------------------
-- COMPONENTS
-----------------------------------------------------------------
	COMPONENT POLAR3PHASEPROM
	PORT(
		CLKA : IN std_logic;
		CSA : IN std_logic;
		OEA : IN std_logic;
		ADDRA : IN std_logic_vector(10 downto 0);
		CLKB : IN std_logic;
		CSB : IN std_logic;
		OEB : IN std_logic;
		ADDRB : IN std_logic_vector(10 downto 0);          
		DOA : OUT std_logic_vector(8 downto 0);
		DOB : OUT std_logic_vector(8 downto 0)
		);
	END COMPONENT;
	
	COMPONENT POLAR3MAGPROM
	PORT(
		CLKA : IN std_logic;
		CSA : IN std_logic;
		OEA : IN std_logic;
		ADDRA : IN std_logic_vector(10 downto 0);
		CLKB : IN std_logic;
		CSB : IN std_logic;
		OEB : IN std_logic;
		ADDRB : IN std_logic_vector(10 downto 0);          
		DOA : OUT std_logic_vector(8 downto 0);
		DOB : OUT std_logic_vector(8 downto 0)
		);
	END COMPONENT;
	
-----------------------------------------------------------------
-- SIGNALS
-----------------------------------------------------------------
-- Suffix _E is for precision extended
-- Suffix _D for delay
signal X_IN11: std_logic := '0'; 
signal Y_IN11: std_logic := '0'; 
signal X_ABS: std_logic_vector(10  downto 0) := (others => '0');
signal Y_ABS: std_logic_vector(10  downto 0) := (others => '0');
signal X_SIGN: std_logic := '0';
signal Y_SIGN: std_logic := '0';
signal X_ABS_Q: std_logic_vector(5  downto 0) := (others => '0');
signal Y_ABS_Q: std_logic_vector(5  downto 0) := (others => '0');
signal X_SIGN_D: std_logic := '0';
signal Y_SIGN_D: std_logic := '0';
signal X_SIGN_D2: std_logic := '0';
signal Y_SIGN_D2: std_logic := '0';
signal X_ABS_Q_D: std_logic_vector(5  downto 0) := (others => '0');
signal X_ABS_Q_D2: std_logic_vector(5  downto 0) := (others => '0');
signal ADDR: std_logic_vector(10  downto 0) := (others => '0');
signal ANGLE_0_45DEG: std_logic_vector(8  downto 0) := (others => '0');
signal ANGLE_0_90DEG: std_logic_vector(10  downto 0) := (others => '0');
signal OFFSET_90: std_logic := '0';      
signal OFFSET_90_D: std_logic := '0';      

signal MAG_DIFFER: std_logic_vector(6  downto 0) := (others => '0');
				   
signal SAMPLE_CLK_IN_D: std_logic := '0';      
signal SAMPLE_CLK_IN_D2: std_logic := '0';      
signal SAMPLE_CLK_IN_D3: std_logic := '0';      
signal SAMPLE_CLK_IN_D4: std_logic := '0';      

signal MAGNITUDE_RANGE_0_175: std_logic_vector(8  downto 0) := (others => '0');

signal NO_OF_SHIFTS: std_logic_vector(2  downto 0) := (others => '0');
signal NO_OF_SHIFTS_D: std_logic_vector(2  downto 0) := (others => '0');
signal NO_OF_SHIFTS_D2: std_logic_vector(2  downto 0) := (others => '0');

------------------------------------------------------
--			ATTRIBUTES
------------------------------------------------------  
--attribute INIT_00: string;
--attribute INIT_01: string;
--attribute INIT_02: string;
--attribute INIT_03: string;
--attribute INIT_04: string;
--attribute INIT_05: string;
--attribute INIT_06: string;
--attribute INIT_07: string;
--attribute INIT_08: string;
--attribute INIT_09: string;
--attribute INIT_0A: string;
--attribute INIT_0B: string;
--attribute INIT_0C: string;
--attribute INIT_0D: string;
--attribute INIT_0E: string;
--attribute INIT_0F: string;
--attribute INIT_10: string;
--attribute INIT_11: string;
--attribute INIT_12: string;
--attribute INIT_13: string;
--attribute INIT_14: string;
--attribute INIT_15: string;
--attribute INIT_16: string;
--attribute INIT_17: string;
--attribute INIT_18: string;
--attribute INIT_19: string;
--attribute INIT_1A: string;
--attribute INIT_1B: string;
--attribute INIT_1C: string;
--attribute INIT_1D: string;
--attribute INIT_1E: string;
--attribute INIT_1F: string;
--attribute INIT_20: string;
--attribute INIT_21: string;
--attribute INIT_22: string;
--attribute INIT_23: string;
--attribute INIT_24: string;
--attribute INIT_25: string;
--attribute INIT_26: string;
--attribute INIT_27: string;
--attribute INIT_28: string;
--attribute INIT_29: string;
--attribute INIT_2A: string;
--attribute INIT_2B: string;
--attribute INIT_2C: string;
--attribute INIT_2D: string;
--attribute INIT_2E: string;
--attribute INIT_2F: string;
--attribute INIT_30: string;
--attribute INIT_31: string;
--attribute INIT_32: string;
--attribute INIT_33: string;
--attribute INIT_34: string;
--attribute INIT_35: string;
--attribute INIT_36: string;
--attribute INIT_37: string;
--attribute INIT_38: string;
--attribute INIT_39: string;
--attribute INIT_3A: string;
--attribute INIT_3B: string;
--attribute INIT_3C: string;
--attribute INIT_3D: string;
--attribute INIT_3E: string;
--attribute INIT_3F: string;
--attribute INITP_00: string;
--attribute INITP_01: string;
--attribute INITP_02: string;
--attribute INITP_03: string;
--attribute INITP_04: string;
--attribute INITP_05: string;
--attribute INITP_06: string;						   	
--attribute INITP_07: string;
--
--
---- Phase bits 7:0 (upper half)			    
--attribute INIT_3F of PHASE_TABLE_001 : label is "0000000000000000000000000000000000000000000000000000000000000000";
--attribute INIT_3E of PHASE_TABLE_001 : label is "FD97503629201B171412100F0E0D0C0B0A0A0909080807070707060606060505";
--attribute INIT_3D of PHASE_TABLE_001 : label is "FB0097695040362E2924201E1B1917161413121110100F0E0E0D0D0C0C0B0B0B";
--attribute INIT_3C of PHASE_TABLE_001 : label is "F8FDD297755F50453C36312C292523201E1D1B1A181716151414131211111010";
--attribute INIT_3B of PHASE_TABLE_001 : label is "F5FB00C0977C695B5047403B36322E2B29262422201F1E1C1B1A191817161615";
--attribute INIT_3A of PHASE_TABLE_001 : label is "F3F8FDE2B697817063585049433E3A3633302D2B2927252322201F1E1D1C1B1A";
--attribute INIT_39 of PHASE_TABLE_001 : label is "F0F5FA00D2B0978475695F57504A45403C393633312E2C2A292725242322201F";
--attribute INIT_38 of PHASE_TABLE_001 : label is "EDF2F7FDEAC7AC9786796E645D56504B46423F3B383633312F2D2C2A29272625";
--attribute INIT_37 of PHASE_TABLE_001 : label is "EAEFF5FA00DCC0A997887C7269615B55504B4744403D3B38363432302E2D2B2A";
--attribute INIT_36 of PHASE_TABLE_001 : label is "E7ECF2F7FDEFD2BAA7978A7F756D655F5954504C4845423F3C3A38363432312F";
--attribute INIT_35 of PHASE_TABLE_001 : label is "E4E9EFF4FA00E2CAB6A5978B81787069635D5854504C494643403E3C3A383634";
--attribute INIT_34 of PHASE_TABLE_001 : label is "E1E6EBF1F7FDF2D9C4B3A4978C827A736C66615C5753504D494744423F3D3B39";
--attribute INIT_33 of PHASE_TABLE_001 : label is "DEE3E8EEF4FA00E7D2C0B0A3978D847C756F69645F5B5753504D4A474542403E";
--attribute INIT_32 of PHASE_TABLE_001 : label is "DBE0E5EBF0F7FDF4DECCBCAEA2978E857E77716B66625E5A5653504D4A484643";
--attribute INIT_31 of PHASE_TABLE_001 : label is "D7DDE2E7EDF3F900EAD7C7B9ACA1978E867F79736E6964605D595653504D4B48";
--attribute INIT_30 of PHASE_TABLE_001 : label is "D4D9DFE4EAF0F6FDF5E2D2C3B6ABA0978F87817B75706B67635F5C585552504D";
--
--attribute INIT_2F of PHASE_TABLE_001 : label is "D1D6DBE1E6ECF3F900EDDCCDC0B4A9A0978F88827C77726D6965615E5B585552";
--attribute INIT_2E of PHASE_TABLE_001 : label is "CED3D8DDE3E9EFF6FCF7E6D6C9BDB2A89F979089837D78736F6B6763605D5A57";
--attribute INIT_2D of PHASE_TABLE_001 : label is "CACFD4DAE0E5ECF2F900EFE0D2C5BAB0A79F97908A847F7A75716D6965625F5C";
--attribute INIT_2C of PHASE_TABLE_001 : label is "C7CCD1D6DCE2E8EEF5FCF8E8DACEC2B8AFA69E97918A85807B76726E6B676461";
--attribute INIT_2B of PHASE_TABLE_001 : label is "C3C8CDD3D8DEE4EBF2F900F0E2D6CAC0B6ADA59E97918B86817C7874706C6966";
--attribute INIT_2A of PHASE_TABLE_001 : label is "C0C5CACFD5DAE1E7EEF5FCF8EADDD2C7BDB4ACA59E97918C86827D7975716E6A";
--attribute INIT_29 of PHASE_TABLE_001 : label is "BCC1C6CBD1D7DDE3EAF1F800F2E5D9CEC4BBB3ABA49D97918C87827E7A76736F";
--attribute INIT_28 of PHASE_TABLE_001 : label is "B8BDC2C7CDD3D9DFE6EDF4FCF9ECE0D5CBC2B9B1AAA39D97928D88837F7B7774";
--attribute INIT_27 of PHASE_TABLE_001 : label is "B5B9BEC4C9CFD5DBE2E9F0F800F3E7DCD2C8C0B8B0A9A39D97928D8884807C78";
--attribute INIT_26 of PHASE_TABLE_001 : label is "B1B6BBC0C5CBD1D7DEE5ECF4FCFAEEE2D8CFC6BEB6AFA8A29D97928D8985817D";
--attribute INIT_25 of PHASE_TABLE_001 : label is "ADB2B7BCC1C7CDD3D9E0E8EFF700F4E9DED5CCC4BCB5AEA8A29C97928E898581";
--attribute INIT_24 of PHASE_TABLE_001 : label is "A9AEB3B8BDC2C8CFD5DCE3EBF3FCFAEFE4DBD2C9C2BAB3ADA7A19C97928E8A86";
--attribute INIT_23 of PHASE_TABLE_001 : label is "A5AAAFB3B9BEC4CAD1D7DFE6EEF700F5EAE1D7CFC7C0B9B2ACA6A19C97938E8A";
--attribute INIT_22 of PHASE_TABLE_001 : label is "A1A6AAAFB4BAC0C6CCD3DAE2EAF2FBFAF0E6DDD4CCC5BEB7B1ABA6A19C97938F";
--attribute INIT_21 of PHASE_TABLE_001 : label is "9DA2A6ABB0B6BBC1C8CED5DDE5EDF600F5ECE2DAD2CAC3BCB6B0ABA5A09C9793";
--attribute INIT_20 of PHASE_TABLE_001 : label is "999DA2A7ACB1B7BDC3C9D1D8E0E8F1FBFBF1E8DFD7CFC8C1BBB5AFAAA5A09B97";
--																							
---- Phase bits 7:0 (lower half)
--attribute INIT_1F of PHASE_TABLE_001 : label is "95999EA2A7ADB2B8BEC5CCD3DBE3ECF600F6EDE4DCD4CDC6C0BAB4AEA9A4A09B";
--attribute INIT_1E of PHASE_TABLE_001 : label is "9195999EA3A8ADB3B9C0C7CED6DEE7F0FBFBF2E9E1D9D2CBC4BEB8B3AEA9A49F";
--attribute INIT_1D of PHASE_TABLE_001 : label is "8D9195999EA3A9AEB4BBC1C9D0D9E2EBF500F7EEE6DED6CFC9C3BDB7B2ADA8A3";
--attribute INIT_1C of PHASE_TABLE_001 : label is "888C9095999EA4A9AFB5BCC3CBD3DCE5EFFAFBF3EAE2DBD4CDC7C1BBB6B1ACA8";
--attribute INIT_1B of PHASE_TABLE_001 : label is "84888C90959A9FA4AAB0B7BEC5CDD6E0EAF400F7EFE7E0D8D2CBC5C0BAB5B0AB";
--attribute INIT_1A of PHASE_TABLE_001 : label is "8083878B90959A9FA5ABB1B8C0C8D0DAE3EEFAFCF3EBE4DDD6D0CAC4BEB9B4AF";
--attribute INIT_19 of PHASE_TABLE_001 : label is "7B7F83878B90959A9FA5ACB2BAC2CAD3DDE8F300F8F0E8E1DAD4CEC8C2BDB8B3";
--attribute INIT_18 of PHASE_TABLE_001 : label is "777A7E82868B8F949AA0A6ADB4BCC4CDD7E1EDF9FCF4ECE5DED8D2CCC6C1BCB7";
--attribute INIT_17 of PHASE_TABLE_001 : label is "7276797D81858A8F949AA0A7AEB5BEC6D0DBE6F200F8F0E9E2DCD6D0CAC5C0BB";
--attribute INIT_16 of PHASE_TABLE_001 : label is "6E7174787C80858A8F949AA1A7AFB7C0C9D4DFEBF9FCF5EDE6E0DAD4CEC9C3BE";
--attribute INIT_15 of PHASE_TABLE_001 : label is "696C6F73777B7F84898E949AA1A8B0B9C2CCD7E4F100F8F1EAE4DDD7D2CCC7C2";
--attribute INIT_14 of PHASE_TABLE_001 : label is "64676B6E72767A7E83888E949AA2A9B2BBC5D0DCE9F8FCF5EEE8E1DBD5D0CBC6";
--attribute INIT_13 of PHASE_TABLE_001 : label is "5F6266696C7074797D82888D949BA2AAB3BDC8D4E1F000F9F2EBE5DFD9D4CEC9";
--attribute INIT_12 of PHASE_TABLE_001 : label is "5B5E6164676B6F73777C81878D949BA3ABB5C0CBD8E7F7FCF5EFE9E2DDD7D2CD";
--attribute INIT_11 of PHASE_TABLE_001 : label is "56595B5E6265696D71767B80868C939BA3ADB7C3CFDEEE00F9F2ECE6E0DBD5D0";
--attribute INIT_10 of PHASE_TABLE_001 : label is "515456595C6063676B6F74797F858C939BA4AEBAC6D4E4F6FDF6F0E9E4DED9D3";
--				
--attribute INIT_0F of PHASE_TABLE_001 : label is "4C4F5154575A5D6165696D72787E848B939CA5B0BCCADAEC00F9F3EDE7E1DCD7";
--attribute INIT_0E of PHASE_TABLE_001 : label is "474A4C4F5154575B5E62676B70767C838A939CA6B2C0CFE1F5FDF6F0EAE5DFDA";
--attribute INIT_0D of PHASE_TABLE_001 : label is "424447494C4E5155585C6064696E747A8189929CA8B5C4D5E900FAF3EEE8E2DD";
--attribute INIT_0C of PHASE_TABLE_001 : label is "3D3F414446494B4E5155595D61666C72788088929DA9B8C8DCF3FDF7F1EBE6E0";
--attribute INIT_0B of PHASE_TABLE_001 : label is "383A3C3E404345484B4E52555A5E63696F767E87919DABBBCEE500FAF4EEE9E3";
--attribute INIT_0A of PHASE_TABLE_001 : label is "333537393B3D3F4244474A4E52565B60666C747C86919EADC0D6F0FDF7F1ECE7";
--attribute INIT_09 of PHASE_TABLE_001 : label is "2E3031333537393B3E4043464A4E52575C6269717A84909FB0C5E000FAF4EFEA";
--attribute INIT_08 of PHASE_TABLE_001 : label is "292B2C2D2F31333537393C3F4245494E52585E656D77828FA0B4CDEDFDF7F2ED";
--attribute INIT_07 of PHASE_TABLE_001 : label is "24252628292B2C2E303235373A3D4044484D53596069737F8EA1B9D700FAF5EF";
--attribute INIT_06 of PHASE_TABLE_001 : label is "1F20212223252628292B2D2F3234373B3E42474D535B646F7C8DA3C0E7FDF8F2";
--attribute INIT_05 of PHASE_TABLE_001 : label is "1A1B1C1D1E1F2021232426282A2C2E3134383C40464C545D69788BA5CA00FAF5";
--attribute INIT_04 of PHASE_TABLE_001 : label is "1515161718191A1B1C1D1E20212325272A2D3034383D444B55617288A9DCFDF8";
--attribute INIT_03 of PHASE_TABLE_001 : label is "101011111212131415161718191A1C1E1F2224272A2E3339404A576984B000FB";
--attribute INIT_02 of PHASE_TABLE_001 : label is "0A0B0B0B0C0C0D0D0E0E0F10111213141516181A1C1F22262B323B475B7CC0FD";
--attribute INIT_01 of PHASE_TABLE_001 : label is "0505060606060607070708080809090A0B0B0C0D0E10111316191E242E406900";
--attribute INIT_00 of PHASE_TABLE_001 : label is "0000000000000000000000000000000000000000000000000000000000000000";
--
---- Phase bit 8 (upper half)  -- last entry in LUT adjusted to correct extreme case
--attribute INITP_07 of PHASE_TABLE_001 : label is "8000000000000000400000000000000020000000000000001000000000000000";
--attribute INITP_06 of PHASE_TABLE_001 : label is "0800000000000000040000000000000002000000000000000100000000000000";
--attribute INITP_05 of PHASE_TABLE_001 : label is "0080000000000000004000000000000000200000000000000010000000000000";
--attribute INITP_04 of PHASE_TABLE_001 : label is "0008000000000000000400000000000000020000000000000001000000000000";
--
---- Phase bit 8 (lower half)
--attribute INITP_03 of PHASE_TABLE_001 : label is "0000800000000000000040000000000000002000000000000000100000000000";
--attribute INITP_02 of PHASE_TABLE_001 : label is "0000080000000000000004000000000000000200000000000000010000000000";
--attribute INITP_01 of PHASE_TABLE_001 : label is "0000008000000000000000400000000000000020000000000000001000000000";
--attribute INITP_00 of PHASE_TABLE_001 : label is "0000000800000000000000040000000000000002000000000000000100000000";
--
---- Magnitude bits 7:0 (upper half)	  					
--attribute INIT_3F of MAG_TABLE_001 : label is "6508101820283038404850586068707880889098A0A8B0B8C0C8D0D8E0E8F0F8";
--attribute INIT_3E of MAG_TABLE_001 : label is "6209101820283038404850586068707880889098A0A8B0B8C0C8D0D8E0E8F0F8";
--attribute INIT_3D of MAG_TABLE_001 : label is "5F0B121921293139404850586068707880889098A0A8B0B8C0C8D0D8E0E8F0F8";
--attribute INIT_3C of MAG_TABLE_001 : label is "5C56141B222A3139414951596169717981899098A0A8B0B8C0C8D0D8E0E8F0F8";
--attribute INIT_3B of MAG_TABLE_001 : label is "5953171D242B333A424A52596169717981899199A1A9B1B9C1C9D1D9E1E9F1F9";
--attribute INIT_3A of MAG_TABLE_001 : label is "57514B1F262D343B434B525A626A727A82899199A1A9B1B9C1C9D1D9E1E9F1F9";
--attribute INIT_39 of MAG_TABLE_001 : label is "544E4822282F363D444C545B636B737A828A929AA2AAB2BAC1C9D1D9E1E9F1F9";
--attribute INIT_38 of MAG_TABLE_001 : label is "514B45402B31383F464D555C646C737B838B939BA2AAB2BAC2CAD2DAE2EAF2FA";
--attribute INIT_37 of MAG_TABLE_001 : label is "4F49433D2D333A40484F565E656D747C848C949BA3ABB3BBC3CBD2DAE2EAF2FA";
--attribute INIT_36 of MAG_TABLE_001 : label is "4C46403A34363C434950585F676E767D858D949CA4ACB4BBC3CBD3DBE3EBF3FB";
--attribute INIT_35 of MAG_TABLE_001 : label is "49433D3732393E454B525961686F777E868E959DA5ADB4BCC4CCD4DCE4EBF3FB";
--attribute INIT_34 of MAG_TABLE_001 : label is "47413B352F2941474E545B626A717880878F979EA6AEB5BDC5CDD5DCE4ECF4FC";
--attribute INIT_33 of MAG_TABLE_001 : label is "443E38322C26444A50575D646B737A818990989FA7AFB6BEC6CED5DDE5EDF5FD";
--attribute INIT_32 of MAG_TABLE_001 : label is "423B352F29231E4C52595F666D747B838A9299A1A8B0B8BFC7CFD6DEE6EEF6FD";
--attribute INIT_31 of MAG_TABLE_001 : label is "3F39332D27211B4F555B62686F767D848C939BA2AAB1B9C0C8D0D7DFE7EFF6FE";
--attribute INIT_30 of MAG_TABLE_001 : label is "3D36302A241E1812585E646B71787F868D959CA3ABB2BAC2C9D1D8E0E8F0F7FF";
--
--attribute INIT_2F of MAG_TABLE_001 : label is "3A342E28211B15105B60666D737A81888F969EA5ACB4BBC3CAD2DAE1E9F1F800";
--attribute INIT_2E of MAG_TABLE_001 : label is "38322B251F19130D0763696F767C838A91989FA7AEB5BDC4CCD3DBE2EAF2F901";
--attribute INIT_2D of MAG_TABLE_001 : label is "362F29221C16100A04666C72787E858C939AA1A8AFB7BEC6CDD5DCE4EBF3FB02";
--attribute INIT_2C of MAG_TABLE_001 : label is "332D26201A140D0702FC6E747A81878E959CA3AAB1B8C0C7CED6DDE5EDF4FC03";
--attribute INIT_2B of MAG_TABLE_001 : label is "312B241E17110B05FFF971777D838A90979EA5ACB3BAC1C9D0D7DFE6EEF5FD05";
--attribute INIT_2A of MAG_TABLE_001 : label is "2F28221B150E0802FCF6F07A80868C9299A0A7AEB5BCC3CAD2D9E0E8EFF7FE06";
--attribute INIT_29 of MAG_TABLE_001 : label is "2D261F19120C0600F9F4EE7C82888E959BA2A9B0B7BEC5CCD3DBE2E9F1F80007";
--attribute INIT_28 of MAG_TABLE_001 : label is "2B241D17100A03FDF7F1EBE5858B91979EA4ABB2B9C0C7CED5DCE3EBF2FA0109";
--attribute INIT_27 of MAG_TABLE_001 : label is "28221B140E0701FBF4EEE8E2888E949AA0A6ADB4BBC1C8D0D7DEE5ECF4FB020A";
--attribute INIT_26 of MAG_TABLE_001 : label is "261F19120B05FEF8F2ECE6E0DA90969CA2A9AFB6BDC4CAD1D8E0E7EEF5FD040B";
--attribute INIT_25 of MAG_TABLE_001 : label is "241D17100903FCF6EFE9E3DDD793999FA5ABB2B8BFC6CCD3DAE1E9F0F7FE060D";
--attribute INIT_24 of MAG_TABLE_001 : label is "221B140E0700FAF3EDE7E0DAD4CE9CA1A7AEB4BAC1C8CED5DCE3EAF1F900070E";
--attribute INIT_23 of MAG_TABLE_001 : label is "2019120C05FEF7F1EAE4DED8D2CC9EA4AAB0B6BDC3CAD1D7DEE5ECF3FA020910";
--attribute INIT_22 of MAG_TABLE_001 : label is "1E17100903FCF5EFE8E2DBD5CFC9C3A7ADB3B9BFC6CCD3DAE0E7EEF5FC030B12";
--attribute INIT_21 of MAG_TABLE_001 : label is "1C150E0701FAF3ECE6DFD9D3CCC6C0AAAFB5BBC2C8CED5DCE2E9F0F7FE050C14";
--attribute INIT_20 of MAG_TABLE_001 : label is "1B140C05FFF8F1EAE3DDD6D0CAC4BEB8B2B8BEC4CAD1D7DEE5EBF2F900070E15";
--																							
---- Magnitude bits 7:0 (lower half)
--attribute INIT_1F of MAG_TABLE_001 : label is "19120B04FDF6EFE8E1DBD4CEC7C1BBB5B5BBC1C7CDD3DAE0E7EDF4FB02091017";
--attribute INIT_1E of MAG_TABLE_001 : label is "17100902FBF4EDE6DFD8D2CBC5BFB8B2ADBEC3C9CFD6DCE2E9F0F6FD040B1219";
--attribute INIT_1D of MAG_TABLE_001 : label is "150E0700F9F2EBE4DDD6CFC9C2BCB6B0AAC0C6CCD2D8DEE5EBF2F9FF060D141B";
--attribute INIT_1C of MAG_TABLE_001 : label is "140C05FEF7F0E9E2DBD4CDC7C0BAB3ADA7A1C9CFD5DBE1E7EEF4FB01080F161D";
--attribute INIT_1B of MAG_TABLE_001 : label is "120B04FCF5EEE7E0D9D2CBC4BEB7B1ABA49ECCD1D7DDE3EAF0F6FD040A11181F";
--attribute INIT_1A of MAG_TABLE_001 : label is "110902FBF3ECE5DED7D0C9C2BBB5AEA8A29C96D4DAE0E6ECF2F9FF060C131A21";
--attribute INIT_19 of MAG_TABLE_001 : label is "0F0800F9F2EAE3DCD5CEC7C0B9B3ACA69F9993D7DDE3E9EFF5FB02080F151C23";
--attribute INIT_18 of MAG_TABLE_001 : label is "0E06FFF7F0E9E1DAD3CCC5BEB7B0AAA39D97908BDFE5EBF1F7FE040A11181E25";
--attribute INIT_17 of MAG_TABLE_001 : label is "0C05FDF6EEE7E0D9D1CAC3BCB5AEA8A19A948E88E2E8EEF4FA00060D131A2027";
--attribute INIT_16 of MAG_TABLE_001 : label is "0B03FCF4EDE6DED7D0C8C1BAB3ACA59F98928B857FEBF1F6FD03090F161C2329";
--attribute INIT_15 of MAG_TABLE_001 : label is "0A02FBF3EBE4DDD5CEC7BFB8B1AAA39C968F89837DEEF3F9FF050B12181E252C";
--attribute INIT_14 of MAG_TABLE_001 : label is "0801F9F2EAE3DBD4CCC5BEB6AFA8A19A948D86807A74F6FC02080E141A21272E";
--attribute INIT_13 of MAG_TABLE_001 : label is "0700F8F0E9E1DAD2CBC3BCB5AEA69F98918B847E7771F9FF040A10171D232A30";
--attribute INIT_12 of MAG_TABLE_001 : label is "06FEF7EFE7E0D8D1C9C2BAB3ACA59D968F89827B756F6901070D13191F262C32";
--attribute INIT_11 of MAG_TABLE_001 : label is "05FDF6EEE6DFD7CFC8C0B9B2AAA39C948D868079726C66040A10161C22282E35";
--attribute INIT_10 of MAG_TABLE_001 : label is "04FCF5EDE5DDD6CEC7BFB8B0A9A19A938C847E77706A635D0D12181E242B3137";
--				
--attribute INIT_0F of MAG_TABLE_001 : label is "03FBF4ECE4DCD5CDC5BEB6AFA7A098918A837C756E67615B10151B21272D333A";
--attribute INIT_0E of MAG_TABLE_001 : label is "02FAF3EBE3DBD4CCC4BDB5ADA69E978F88817A736C655E5852181E242A30363C";
--attribute INIT_0D of MAG_TABLE_001 : label is "01F9F2EAE2DAD3CBC3BBB4ACA49D958E867F78716A635C564F1B21262C32383F";
--attribute INIT_0C of MAG_TABLE_001 : label is "01F9F1E9E1D9D2CAC2BAB3ABA39C948C857E766F68615A534D4723292F353B41";
--attribute INIT_0B of MAG_TABLE_001 : label is "00F8F0E8E0D9D1C9C1B9B2AAA29A938B847C756D665F58514A44262C32383E44";
--attribute INIT_0A of MAG_TABLE_001 : label is "FFF7EFE7E0D8D0C8C0B8B1A9A199928A827B736C645D564F48423B2F343A4046";
--attribute INIT_09 of MAG_TABLE_001 : label is "FFF7EFE7DFD7CFC7BFB8B0A8A09891898179726A635B544D463F3931373D4349";
--attribute INIT_08 of MAG_TABLE_001 : label is "FEF6EEE6DED6CEC7BFB7AFA79F97908880787169615A524B443D36303A40464C";
--attribute INIT_07 of MAG_TABLE_001 : label is "FEF6EEE6DED6CEC6BEB6AEA69E978F877F7770686059514A423B342E3D42484E";
--attribute INIT_06 of MAG_TABLE_001 : label is "FDF5EDE5DDD5CDC5BEB6AEA69E968E867E766F675F5750484139322B25454B51";
--attribute INIT_05 of MAG_TABLE_001 : label is "FDF5EDE5DDD5CDC5BDB5ADA59D958D867E766E665E564F473F38302922484E54";
--attribute INIT_04 of MAG_TABLE_001 : label is "FDF5EDE5DDD5CDC5BDB5ADA59D958D857D756D655D564E463E362F27201A5156";
--attribute INIT_03 of MAG_TABLE_001 : label is "FCF4ECE4DCD4CCC4BCB4ACA49C948D857D756D655D554D453D352E261E175359";
--attribute INIT_02 of MAG_TABLE_001 : label is "FCF4ECE4DCD4CCC4BCB4ACA49C948C847C746C645C544C443D352D251D160E5C";
--attribute INIT_01 of MAG_TABLE_001 : label is "FCF4ECE4DCD4CCC4BCB4ACA49C948C847C746C645C544C443C342C241C140D5F";
--attribute INIT_00 of MAG_TABLE_001 : label is "FCF4ECE4DCD4CCC4BCB4ACA49C948C847C746C645C544C443C342C241C140C04";
--
---- Magnitude bit 8 (upper half)
--attribute INITP_07 of MAG_TABLE_001 : label is "800000008000000080000000C0000000C0000000E0000000E0000000F0000000";
--attribute INITP_06 of MAG_TABLE_001 : label is "F0000000F8000000F8000000FC000000FC000000FE000000FE000000FF000000";
--attribute INITP_05 of MAG_TABLE_001 : label is "FF000001FF800001FF800001FF800001FF000001FF000001FF000003FE000003";
--attribute INITP_04 of MAG_TABLE_001 : label is "FE000003FC000003FC000003FC000007F8000007F8000007F8000007F000000F";
--
---- Magnitude bit 8 (lower half)
--attribute INITP_03 of MAG_TABLE_001 : label is "F000000FF000000FF000000FE000001FE000001FE000001FE000003FC000003F";
--attribute INITP_02 of MAG_TABLE_001 : label is "C000007FC000007FC000007FC00000FFC00000FF800001FF800001FF800000FF";
--attribute INITP_01 of MAG_TABLE_001 : label is "800000FF8000007F8000007F8000003F8000003F0000001F0000001F0000000F";
--attribute INITP_00 of MAG_TABLE_001 : label is "0000000F00000007000000070000000300000003000000010000000100000000";

-----------------------------------------------------------------
-- IMPLEMENTATION
-----------------------------------------------------------------
begin 

-- separate sign and magnitude. 
-- Compute the absolute value. Beware of the special case of 1000000000 in 2's complement.
ABS_GEN_001: process(CLK)
begin
	if rising_edge(CLK) then
		X_IN11 <= X_IN(11);

		if(X_IN(11) = '0') then
			-- positive
			X_ABS <= X_IN(10 downto 0);
	  	elsif (X_IN /= "100000000000") then
			-- negative, but not the most negative (special case)
			X_ABS <= not(X_IN(10 downto 0)) + 1;
		else
			X_ABS <= "11111111111";
		end if;
	end if;
end process;

ABS_GEN_002: process(CLK)
begin
	if rising_edge(CLK) then
		Y_IN11 <= Y_IN(11);

		if(Y_IN(11) = '0') then
			-- positive
			Y_ABS <= Y_IN(10 downto 0);
	  	elsif (Y_IN /= "100000000000") then
			-- negative, but not the most negative (special case)
			Y_ABS <= not(Y_IN(10 downto 0)) + 1;
		else
			Y_ABS <= "11111111111";
		end if;
	end if;
end process;


-- size the input 'usable' magnitude (keep the 6 most significant bits of the magnitude)
-- This limits the size of the look-up table to 11 (5/6 real + 5/6 imaginary) input bits.
MAGNITUDE_ADJUSTMENT: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE_CLK_IN_D <= SAMPLE_CLK_IN;
		SAMPLE_CLK_IN_D2 <= SAMPLE_CLK_IN_D;
		SAMPLE_CLK_IN_D3 <= SAMPLE_CLK_IN_D2;
		SAMPLE_CLK_IN_D4 <= SAMPLE_CLK_IN_D3;
		SAMPLE_CLK_OUT <= SAMPLE_CLK_IN_D4;

		NO_OF_SHIFTS_D <= NO_OF_SHIFTS;
		NO_OF_SHIFTS_D2 <= NO_OF_SHIFTS_D;

		if(SAMPLE_CLK_IN_D = '1') then
			X_SIGN <= X_IN11;
			Y_SIGN <= Y_IN11;
			-- go down the concentric circle from the maximum amplitude downwards.
			if(X_ABS(10) = '1') or (Y_ABS(10) = '1') then
				X_ABS_Q <= X_ABS(10 downto 5);
				Y_ABS_Q <= Y_ABS(10 downto 5);
				NO_OF_SHIFTS <= "110";
			elsif(X_ABS(9) = '1') or (Y_ABS(9) = '1') then
				X_ABS_Q <= X_ABS(9 downto 4);
				Y_ABS_Q <= Y_ABS(9 downto 4);
				NO_OF_SHIFTS <= "101";
			elsif(X_ABS(8) = '1') or (Y_ABS(8) = '1') then
				X_ABS_Q <= X_ABS(8 downto 3);
				Y_ABS_Q <= Y_ABS(8 downto 3);
				NO_OF_SHIFTS <= "100";
			elsif(X_ABS(7) = '1') or (Y_ABS(7) = '1') then
				X_ABS_Q <= X_ABS(7 downto 2);
				Y_ABS_Q <= Y_ABS(7 downto 2);
				NO_OF_SHIFTS <= "011";
			elsif(X_ABS(6) = '1') or (Y_ABS(6) = '1') then
				X_ABS_Q <= X_ABS(6 downto 1);
				Y_ABS_Q <= Y_ABS(6 downto 1);
				NO_OF_SHIFTS <= "010";
			elsif(X_ABS(5) = '1') or (Y_ABS(5) = '1') then
				X_ABS_Q <= X_ABS(5 downto 0);
				Y_ABS_Q <= Y_ABS(5 downto 0);
				NO_OF_SHIFTS <= "001";
			else
				X_ABS_Q <= X_ABS(4 downto 0) & '1';
				Y_ABS_Q <= Y_ABS(4 downto 0) & '1';
				NO_OF_SHIFTS <= "000";
			end if;
	  	end if;
	end if;
end process;		    

MAG_DIFFER <= ('0' & Y_ABS_Q) - ('0' & X_ABS_Q);

-- Generate address for LUTs
LUT_ADDR_GEN_001: process(CLK)
begin
	if rising_edge(CLK) then
		OFFSET_90_D <= OFFSET_90; 

		if(SAMPLE_CLK_IN_D2 = '1') then
			if(MAG_DIFFER > 0) then
				OFFSET_90 <= '1';		-- need to invert angle later
				if(Y_ABS_Q(0) = '1') then
					ADDR <= not(X_ABS_Q & Y_ABS_Q(5 downto 1));
				else
					ADDR <= (X_ABS_Q & Y_ABS_Q(5 downto 1));
				end if;
 			elsif(MAG_DIFFER = 0) then
				OFFSET_90 <= '0';
				if(X_ABS_Q(0) = '1') then
					ADDR <= not(Y_ABS_Q & X_ABS_Q(5 downto 1)) - 1; -- minor adjustment at 45deg indicies
				else
					ADDR <= Y_ABS_Q & X_ABS_Q(5 downto 1);
				end if;
			else
				OFFSET_90 <= '0';
				if(X_ABS_Q(0) = '1') then
					ADDR <= not(Y_ABS_Q & X_ABS_Q(5 downto 1));
				else
					ADDR <= Y_ABS_Q & X_ABS_Q(5 downto 1);
				end if;
			end if;
	  	end if;
	end if;
end process;

POLAR3PHASEPROM_001: POLAR3PHASEPROM PORT MAP(
	CLKA => CLK,
	CSA => '1',
	OEA => '1',
	ADDRA => ADDR,
	DOA => ANGLE_0_45DEG(8 downto 0),
	CLKB => '0',
	CSB => '0',
	OEB => '0',
	ADDRB => (others => '0'),
	DOB => open
);

POLAR3MAGPROM_001: POLAR3MAGPROM PORT MAP(
	CLKA => CLK,
	CSA => '1',
	OEA => '1',
	ADDRA => ADDR,
	DOA => MAGNITUDE_RANGE_0_175(8 downto 0),
	CLKB => '0',
	CSB => '0',
	OEB => '0',
	ADDRB => (others => '0'),
	DOB => open
);

-- using 45 deg symmetry, angle range is [0 - 90[. 90 is sort of excluded.
PHASE_OUT_ADJUST: process(ANGLE_0_45DEG, OFFSET_90_D)
begin
	if(OFFSET_90_D = '1') then
		ANGLE_0_90DEG <= 512 - ("00" & (ANGLE_0_45DEG));
	else
		ANGLE_0_90DEG <= "00" & (ANGLE_0_45DEG);
	end if;
end process;

-- reclock
RECLOCK_001: process(CLK)
begin
	if rising_edge(CLK) then
		X_SIGN_D <= X_SIGN;
		Y_SIGN_D <= Y_SIGN;
		X_SIGN_D2 <= X_SIGN_D;
		Y_SIGN_D2 <= Y_SIGN_D;

		X_ABS_Q_D <= X_ABS_Q;
		X_ABS_Q_D2 <= X_ABS_Q_D;
	end if;
end process;



PHASE_GEN: process(CLK)
begin
	if rising_edge(CLK) then

		if(SAMPLE_CLK_IN_D4 = '1') then
			if(X_SIGN_D2 = '0') and (Y_SIGN_D2 = '0') and (X_ABS_Q_D2 /= "00000") then
				-- case [0-90[ deg
				PHASE_OUT <= ANGLE_0_90DEG;
			elsif(X_SIGN_D2 = '1') and (Y_SIGN_D2 = '0') and (X_ABS_Q_D2 /= "00000") then
				-- case ]90-180] deg
				PHASE_OUT <= "10000000001" + not(ANGLE_0_90DEG);
			elsif(X_SIGN_D2 = '1') and (Y_SIGN_D2 = '1') and (X_ABS_Q_D2 /= "00000") then
				-- case [180-270[ deg
				PHASE_OUT <= "10000000000" + ANGLE_0_90DEG;
			elsif(X_SIGN_D2 = '0') and (Y_SIGN_D2 = '1') and (X_ABS_Q_D2 /= "00000") then
				-- case [270 - 360[ deg
				PHASE_OUT <= not(ANGLE_0_90DEG) + "00000000001";
			elsif(Y_SIGN_D2 = '0') then
				-- case 90 deg
				PHASE_OUT <= "01000000000";
			else
				-- case 270 deg
				PHASE_OUT <= "11000000000";
			end if;				
	  	end if;
	end if;
end process;

--------------------------------------------------------------------------
-- MAGNITUDE LOOK-UP CODE STARTS HERE
--------------------------------------------------------------------------
-- Undo the shifts that were performed earlier (see the generation of
-- the signals X_ABS_Q and Y_ABS_Q above). Set the lower bits in the 
-- middle i.e. to round((2^noOfBits)/2). This gives a better average SNR 
-- than simply zero-padding.
UNSHIFT_001: process(CLK)
begin
	if rising_edge(CLK) then
		 
		if(SAMPLE_CLK_IN_D4 = '1') then

			case NO_OF_SHIFTS_D2 is
				when "000" => 
					MAGNITUDE_OUT(13 downto 8) <= (others => '0');
					MAGNITUDE_OUT(7 downto 0) <= MAGNITUDE_RANGE_0_175(8 downto 1);
		
				when "001" => 
					MAGNITUDE_OUT(13 downto 9) <= (others => '0');
					MAGNITUDE_OUT(8 downto 0) <= MAGNITUDE_RANGE_0_175;
		
				when "010" => 
					MAGNITUDE_OUT(13 downto 10) <= (others => '0');
					MAGNITUDE_OUT(9 downto 1) <= MAGNITUDE_RANGE_0_175;
					MAGNITUDE_OUT(0 downto 0) <= "0";
		
				when "011" => 
					MAGNITUDE_OUT(13 downto 11) <= (others => '0');
					MAGNITUDE_OUT(10 downto 2) <= MAGNITUDE_RANGE_0_175;
					MAGNITUDE_OUT(1 downto 0) <= "01";
		
				when "100" => 
					MAGNITUDE_OUT(13 downto 12) <= (others => '0');
					MAGNITUDE_OUT(11 downto 3) <= MAGNITUDE_RANGE_0_175;
					MAGNITUDE_OUT(2 downto 0) <= "011";
		
				when "101" => 
					MAGNITUDE_OUT(13) <= '0';
					MAGNITUDE_OUT(12 downto 4) <= MAGNITUDE_RANGE_0_175;
					MAGNITUDE_OUT(3 downto 0) <= "0111";
		
				when others => -- "110"
					MAGNITUDE_OUT(13 downto 5) <= MAGNITUDE_RANGE_0_175;
					MAGNITUDE_OUT(4 downto 0) <= "01111";
		
			end case;
		end if;
	end if;
end process;

end Behavior;
