-------------------------------------------------------------
-- MSS copyright 2013-2017
--	Filename:  DSSS_DEMOD_TDRSS.VHD
-- Author: Alain Zarembowitch / MSS
--	Version: 8
--	Date last modified: 4/11/17
-- Inheritance: 	DSSS_DEMOD2 rev12 6/26/14, COM-1418 DSSS_DEMOD3/20/10,  COM-1018 rev5 3-5-05, COM1011 DEMOD.VHD
--
-- description:  Direct-Sequence Spread-Spectrum demodulator customized for TDRSS.
-- Input: complex samples
-- Variable decimation, half-band filter, optional raised cos filter, parallel I code acquisition,
-- independent symbol timing loops for I and Q channels
--
-- Rev 0b 9/30/14 AZ Vivado tools misunderstood the statement (something = 'X') as true
-- had to work around it.
-- 
-- Rev 1 2/13/15 AZ
-- less frequency phase tracking correction in the case of very low symbol rates (Kbps)
--
-- Rev 2 4/13/15 AZ
-- adjusted signal presence detection threshold FFTM_THRESHOLD
--
-- Rev 3 
-- improve code detection for SQPN (use both codes)
-- inverted frequency errors (now reporting errors instead of corrections)
--
-- Rev 4 2/2/16 AZ
-- AGC18 magnitude target adjusted so that DATA151_I nominal magnitude is 512 
-- Additional accurate SNR measurement.
--
-- Rev 5 3/6/16
-- Added alternating I/Q modulation mode and 1/2 symbol Q modulation delay
-- Corrected bug with fast frequency detection (new rev)
--
-- Rev6 6/6/16 AZ
-- 2 distinct SNR measurements for I and Q channels. 
--
-- Rev 7 8/4/16 AZ
-- Upgraded AGC18 (larger dynamic range, faster response)
-- account for 1/2 chip Q-code delay during parallel acquisition (previously only done during despreading/tracking phase)
--
-- Rev 8 4/11/17 AZ
-- Simplification. Symbol tracking NCOs at 2x (previously x4). Adjusted ST loop gain accordingly.
-- Corrected NCO32X anomaly at 122Kbps and 61Kbps.
-- 
---------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;

entity DSSS_DEMOD_TDRSS is
	generic (
		SIMULATION: std_logic := '0'
			-- 1 during simulation. 
	 );
    port ( 
		-- RESET, CLOCK
		CLK: in std_logic;	-- master clock. Typically the input signal ADC sampling rate.
		SYNC_RESET: in std_logic;
		SYMBOL_CLK: out std_logic;
			-- time reference related to the modulation bandwidth. Originates from the demodulator. 
			-- used by the AGC and bias removal circuitry to avoid tracking the modulation.
			-- Ambiguous terminology: this is really the chip clock 

		--// Input samples
		DATA_I_IN: in std_logic_vector(13 downto 0);
		DATA_Q_IN: in std_logic_vector(13 downto 0);
		SAMPLE_CLK_IN: in std_logic;
			-- input samples, 14-bit precision, 2's complement 
			-- read at rising edge of CLK when SAMPLE_CLK_IN='1'
			-- Unused LSBs are pulled low.
			-- Input sampling rate MUST be >2 but < 8 samples/symbol

		--// Settings
		NOMINAL_CHIP_RATE: in std_logic_vector(31 downto 0);
			-- = fchip rate / fclk * 2^32. Always 3.077799479166
		NOMINAL_SYMBOL_RATE1: in std_logic_vector(31 downto 0);
		NOMINAL_SYMBOL_RATE2: in std_logic_vector(31 downto 0);
			-- = fsymbol rate / fclk * 2^32 = nominal chip rate / spreading factor
			-- 1 for I channel, 2 for Q channel
	 	SPREADING_FACTOR1: in std_logic_vector(12 downto 0);
	 	SPREADING_FACTOR2: in std_logic_vector(12 downto 0);
			-- spreading factor. Valid range 3 - 8191 = nominal chip rate / nominal symbol rate
			-- Not necessarily equal to the spreading code period.
			-- Channel1/I spreading factor is always less than channel2/Q.
			-- IMPORTANT!!!!
			-- KEY ASSUMPTION: the number of parallel circuits NACQ MUST be less (or equal) than the number of 
			-- CLKs in half a symbol period.
			-- IMPORTANT!!!!   Adjust the NACQ constant within accordingly.
		LFSRA_INIT: in std_logic_vector(10 downto 0);
		LFSRC_INIT: in std_logic_vector(10 downto 0);
			-- LFSR initialization. see definition in Space network interoperable pn code libraries, Appendix A
		CODE_MODE: in std_logic;
			-- 0 = forward command link Gold codes
			-- 1 = return mode 2 link Gold codes
		FREQ_SCAN_N_COARSE_STEPS: in std_logic_vector(7 downto 0);
			-- number of frequency acquisition steps in each direction
			-- total number of frequencies is thus 2*N_STEPS+1
			-- Coarse scan step size is (symbol rate/4)


		--// Controls
	   CONTROL: in std_logic_vector(15 downto 0);
			-- bit 0: spectrum inversion off (0), on (1)
			-- bit 1: BPSK (0) vs SQPN(1)
			-- bit 2: independent symbol rates on I/Q (0),or identical synchronized symbol rates on I/Q(1)
			-- bits 3-5: encoding
			--     0 = NRZ-L
			--     1 = NRZ-M
			-- 	 2 = NRZ-S
			-- 	 4 = Biphase-L
			-- bit 6: 1/2 symbol Q delay
			-- bit 7: alternating I/Q bits (yes = 1, no = 0)
			-- bit 9 reserved for output selection
		RESET_DEMOD_IN_FALSE_LOCK: in std_logic;
			-- 1 CLK wide pulse to reset frequency scanning, carrier tracking and symbol timing loops, but not the AGC
			-- justification: a more reliable assessment of the demod lock status is generally available at 
			-- components further down the receiver (FEC decoder, HDLC deframing, etc).

		--// Demodulator serial output
		DATA_I_OUT: out std_logic_vector(3 downto 0);
		DATA_Q_OUT: out std_logic_vector(3 downto 0);
			-- 4 bit soft-quantized demodulator output
			-- Read at rising edge of CLK when SAMPLE_CLK_OUT = '1';
			-- 4-bit sample format:
			-- 0000 most negative, 1111 most positive, with no zero representation 
		SAMPLE_I_CLK_OUT: out std_logic;
		SAMPLE_Q_CLK_OUT: out std_logic;
			-- one CLK-wide pulse
			-- IMPORTANT: both valid signals are aligned EXACTLY when using the same symbol rate on both I and Q
			-- even when the 1/2 symbol Q channel delay is enabled.
			-- This is important when reconstructing the alternating I/Q data stream
		CODE_START_OUT: out std_logic;
			-- 1 CLK pulse indicating the 1st chip in the periodic code replica.
			-- Can be used for round-trip delay measurement.

		-- Monitoring Information
		CARRIER_LOCK_OUT: out std_logic;
		CODE_LOCK_OUT: out std_logic;
		SIGNAL_PRESENT_OUT: out std_logic;
		CARRIER_FREQUENCY_ERROR1: out std_logic_vector(31 downto 0);
            -- report the frequency error in two parts (different units, simpler to do the aggregation outside in a micro)
            -- Center frequency error1: offset with respect to the nominal carrier frequency. 
            -- 32-bit signed integer (2's complement) expressed as cfe1 * 2^32  / fclk. 
		CARRIER_FREQUENCY_ERROR2: out std_logic_vector(31 downto 0);
            -- Center frequency error2: offset with respect to the nominal carrier frequency. 
            -- 32-bit signed integer (2's complement) expressed as cfe2 * 2^31  / fchiprate. 
		POWER_S_AVERAGE_OUT: out std_logic_vector(17 downto 0);
		POWER_N_AVERAGE_OUT: out std_logic_vector(17 downto 0);
			-- averaged on-time signal and noise power. 
			-- Units are irrelevant because of the many AGCs. 
		SNR1_LOCKED_OUT: out std_logic_vector(17 downto 0);
		SNR2_LOCKED_OUT: out std_logic_vector(17 downto 0);
			-- SNR when demod is code-locked. Format 16.2
			-- can be different on each channel

		DESPREAD1_I_OUT: out std_logic_vector(13 downto 0);
		DESPREAD1_Q_OUT: out std_logic_vector(13 downto 0);
		DESPREAD1_SAMPLE_CLK: out std_logic;
		-- digital representation of the analog complex sigals after despreading 
		-- 2's complement. Baseband samples (zero center frequency). 
		-- Sampled at 2 samples/chip 
		
		-- COMSCOPE test points
		-- CS1: spread I-channel after AFC, resampling and channel LPF filter
		-- CS2: despread I-channel after coherent I&D
		-- CS3: despread Q-channel after coherent I&D
		-- CS4: demodulated I
		-- CS5: demodulated Q
		-- CS6: AGC18 scaling gain
		-- CS7: code replica
		-- CS8: accumulated code tracking phase correction (8 MSbs)
		-- CS9: carrier NCO phase (8 MSBs)
		-- CS10: accumulated symbol timing phase correction (8 MSbs)
		-- CS11: 2(S+N)/N, valid only if code lock. Linear, not in dBs.
		-- T1: start of code replica
		-- T2: code lock (1-bit). assessed once per code-sweep period
		CS1: out std_logic_vector(7 downto 0); 
		CS1_CLK: out std_logic;
		CS2: out std_logic_vector(7 downto 0); 
		CS2_CLK: out std_logic;
		CS3: out std_logic_vector(7 downto 0);	
		CS3_CLK: out std_logic;
		CS4: out std_logic_vector(7 downto 0); 
		CS4_CLK: out std_logic;
		CS5: out std_logic_vector(7 downto 0);
		CS5_CLK: out std_logic;
		CS6: out std_logic_vector(7 downto 0);
		CS6_CLK: out std_logic;
		CS7: out std_logic_vector(7 downto 0);
		CS7_CLK: out std_logic;
		CS8: out std_logic_vector(7 downto 0); 
		CS8_CLK: out std_logic;
		CS9: out std_logic_vector(7 downto 0); 
		CS9_CLK: out std_logic;
		CS10: out std_logic_vector(7 downto 0); 
		CS10_CLK: out std_logic;
		CS11: out std_logic_vector(7 downto 0); 
		CS11_CLK: out std_logic;
		T1: out std_logic;	
		T1_CLK: out std_logic;
		T2: out std_logic;	
		T2_CLK: out std_logic;
		
		-- Test Points
		TP: out std_logic_vector(20 downto 1)
			-- bit 1: recovered carrier frequency (coarse)
			-- bit 2: carrier lock
			-- bit 3: code lock
			-- bit 4: signal presence
			-- bit 5: recovered chip clock
			-- bit 6: recovered I-channel symbol clock
			-- bit 7: start of I-code replica
			-- bit 8: I-code replica used for despreading
			-- bit 9: received signal (I-channel, MSB) before despreading (compare with code replica above)
			-- bit 10: demodulated I bit
			-- bit 11: demodulated Q bit
			-- bit 12: saturation1 AGC18
			-- bit 13: saturation2 frequency translation
			-- bit 14: saturation on-time correlation
			-- bit 15: saturation AGC1
			-- bit 16: FFT overflow
			-- bit 17: saturation151 frequency translation
			);
end entity;

architecture behavioral of DSSS_DEMOD_TDRSS is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------

	COMPONENT DIGITAL_DC2
	PORT(
		CLK : IN std_logic;
		DATA_I_IN : IN std_logic_vector(11 downto 0);
		DATA_Q_IN : IN std_logic_vector(11 downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		PHASE_ROTATION : IN std_logic_vector(11 downto 0);          
		DATA_I_OUT : OUT std_logic_vector(11 downto 0);
		DATA_Q_OUT : OUT std_logic_vector(11 downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		SATURATION : OUT std_logic
		);
	END COMPONENT;

--	COMPONENT FREQ_SCAN
--	PORT(
--		CLK : IN std_logic;
--		SYNC_RESET : IN std_logic;
--		FREQUENCY_STEP : IN std_logic_vector(31 downto 0);
--		N_STEPS : IN std_logic_vector(7 downto 0);
--		STEP_TRIGGER : IN std_logic;          
--		FREQUENCY_OUT : OUT std_logic_vector(31 downto 0)
--		);
--	END COMPONENT;

	COMPONENT RESAMPLING2
	 Generic(
		NBITS: integer
	 );
	PORT(
		CLK : IN std_logic;
		DATA_I_IN : IN std_logic_vector((NBITS-1) downto 0);
		DATA_Q_IN : IN std_logic_vector((NBITS-1) downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		NOMINAL_RESAMPLING_RATE : IN std_logic_vector(31 downto 0);
		NCO_OFFSET : IN std_logic_vector(31 downto 0);
		NCO_OFFSET_SAMPLE_CLK : IN std_logic;          
		DATA_I_OUT : OUT std_logic_vector((NBITS-1) downto 0);
		DATA_Q_OUT : OUT std_logic_vector((NBITS-1) downto 0);
		SAMPLE_CLK_OUT : OUT std_logic
		);
	END COMPONENT;

	COMPONENT FIRHALFBAND3
	PORT(
		CLK : IN std_logic;
		SAMPLE_CLK_IN : IN std_logic;
		DATA_IN : IN std_logic_vector(13 downto 0);          
		SAMPLE_CLK_OUT : OUT std_logic;
		DATA_OUT : OUT std_logic_vector(13 downto 0)
		);
	END COMPONENT;

--	COMPONENT RAISED_COS2_40
--	PORT(
--		CLK : IN std_logic;
--		SAMPLE_CLK_IN : IN std_logic;
--		DATA0_IN : IN std_logic_vector(13 downto 0);
--		DATA180_IN : IN std_logic_vector(13 downto 0);          
--		SAMPLE_CLK_OUT : OUT std_logic;
--		DATA0_OUT : OUT std_logic_vector(13 downto 0);
--		DATA180_OUT : OUT std_logic_vector(13 downto 0)
--		);
--	END COMPONENT;

    COMPONENT CODEGEN3
    PORT(
         CLK : IN  std_logic;
         BIT_CLK_REQ : IN  std_logic;
         SYNC_RESET : IN  std_logic;
         LFSRA_INIT : IN  std_logic_vector(10 downto 0);
         LFSRC_INIT : IN  std_logic_vector(10 downto 0);
			CODE_MODE: in std_logic;
         BIT_CLK_OUT : OUT  std_logic;
         CODE_START : OUT  std_logic;
         CODE_I_BIT : OUT  std_logic;
         CODE_Q_BIT : OUT  std_logic;
         BIT_COUNT_OUT : OUT  std_logic_vector(10 downto 0)
        );
    END COMPONENT;

	COMPONENT DESPREAD_ID
	 Generic(
		NBITS: integer
	 );
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA_I_IN : IN std_logic_vector((NBITS-1) downto 0);
		DATA_Q_IN : IN std_logic_vector((NBITS-1) downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		CODE_I: in std_logic;
		CODE_Q: in std_logic;
		SOID: in std_logic;
		TRUNCATE_OBITS: in integer;
		BPSK0_SQPN1: in std_logic;
		DATA_I_OUT : OUT std_logic_vector((NBITS-1) downto 0);
		DATA_Q_OUT : OUT std_logic_vector((NBITS-1) downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		SATURATION: out std_logic
		);
	END COMPONENT;

	COMPONENT FAST_FREQUENCY_DETECTION
	generic (
		NID_MAX_LOG2: integer;	
		SIMULATION: std_logic 
	);
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA_I_IN : IN std_logic_vector(17 downto 0);
		DATA_Q_IN : IN std_logic_vector(17 downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		ENABLE: in std_logic;
		NID: in integer range 1 to 2**NID_MAX_LOG2 -1; 
		NID_LOG2: in integer range 0 to 31;	
		FFTM: out std_logic_vector(13 downto 0);
		FFTM2: out std_logic_vector(13 downto 0); 
		FFTM_AVRG: out std_logic_vector(13 downto 0);
		FFTF: out std_logic_vector(10 downto 0);
		FFTP: out std_logic_vector(10 downto 0);
		FFT_READY: out std_logic;
		SATURATION: out std_logic;
		CS1: out std_logic_vector(7 downto 0); 
        CS1_CLK: out std_logic;
		TP : OUT std_logic_vector(10 downto 1)
		);
	END COMPONENT;

	COMPONENT MULT18X18SIGNED
	PORT(
		A : IN std_logic_vector(17 downto 0);
		B : IN std_logic_vector(17 downto 0);          
		P : OUT std_logic_vector(35 downto 0)
		);
	END COMPONENT;

    COMPONENT DIVIDER
	 Generic(
		NBITS: integer
	 );
    PORT(
         CLK : IN  std_logic;
         NUM : IN  std_logic_vector((NBITS-1) downto 0);
         DENOM : IN  std_logic_vector((NBITS-1) downto 0);
         SAMPLE_CLK_IN : IN  std_logic;
         QUOTIENT : OUT  std_logic_vector((NBITS-1) downto 0);
         REMAINDER : OUT  std_logic_vector((NBITS-1) downto 0);
         SAMPLE_CLK_OUT : OUT  std_logic
        );
    END COMPONENT;
	
	COMPONENT CODE_TRACKING2
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA_EARLY : IN std_logic_vector(13 downto 0);
		DATA_LATE : IN std_logic_vector(13 downto 0);
		SAMPLE_CLK : IN std_logic;
		FREEZE_CODE_TRACKING : IN std_logic;          
		LOOP_GAIN: in std_logic_vector(1 downto 0);
		NCO_TIMING_CONTROL : OUT std_logic_vector(31 downto 0);
		NCO_TIMING_CONTROL_CLK : OUT std_logic;
		CS1 : OUT std_logic_vector(7 downto 0);
		CS1_CLK : OUT std_logic
		);
	END COMPONENT;

	COMPONENT AGC18
	 Generic(
		AVERAGING_LENGTH: integer;
		SIMULATION: std_logic
	 );
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA_I_IN : IN std_logic_vector(13 downto 0);
		DATA_Q_IN : IN std_logic_vector(13 downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		MTARGET : IN std_logic_vector(13 downto 0);
		CONTROL : IN std_logic_vector(0 to 0);
		SYMBOLx2_CLK_IN : IN std_logic;          
		DATA_I_OUT : OUT std_logic_vector(13 downto 0);
		DATA_Q_OUT : OUT std_logic_vector(13 downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		SATURATION : OUT std_logic;
		DATA_M : OUT std_logic_vector(13 downto 0);
		SAMPLE_M_CLK : OUT std_logic;
		TP : OUT std_logic_vector(10 downto 1);
		CS1 : OUT std_logic_vector(7 downto 0);
		CS1_CLK : OUT std_logic
		);
	END COMPONENT;

	COMPONENT SYMBOL_TIMING_LOOP5X2CH
	generic (
		SIMULATION: std_logic 
	);
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		SYMBOL_CLK_IN : IN std_logic;
		SYMBOL_CLKx2_IN : IN std_logic;
		DATA_I_IN : IN std_logic_vector(17 downto 0);
		DATA_Q_IN : IN std_logic_vector(17 downto 0);
		FREEZE_SYMBOL_TIMING : IN std_logic;
		ACCELERATED_STLOOP_RESPONSE : IN std_logic;    
		NCO_TIMING_CONTROL : OUT std_logic_vector(31 downto 0);
		NCO_TIMING_CONTROL_CLK : OUT std_logic;
		CS1 : OUT std_logic_vector(7 downto 0);
		CS1_CLK : OUT std_logic
		);
	END COMPONENT;

	COMPONENT NCO32X
	generic (
        SIMULATION: std_logic 
    );
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		NOMINAL_FREQUENCY : IN std_logic_vector(31 downto 0);
		PHASE_OFFSET : IN std_logic_vector(31 downto 0);
		PHASE_OFFSET_SAMPLE_CLK : IN std_logic;          
		PHASE : OUT std_logic_vector(32 downto 0);
		SAMPLE_CLK_OUT : OUT std_logic
		);
	END COMPONENT;

	COMPONENT CARRIER_TRACKING2
	generic (
        SIMULATION: std_logic 
    );
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		OPTIMUM_SAMPLING_CLK : IN std_logic;
		PHASE_ERROR : IN std_logic_vector(10 downto 0);
        NOMINAL_SYMBOL_RATE: in std_logic_vector(31 downto 0);
		LOOP_GAIN1 : IN std_logic_vector(1 downto 0);
		LOOP_GAIN2 : IN std_logic_vector(1 downto 0);
		ACCELERATED_CT_RESPONSE : IN std_logic;
		LOCK_THRESHOLD : IN std_logic_vector(3 downto 0);          
		NCO_CONTROL : OUT std_logic_vector(31 downto 0);
	    NCO_CONTROL_SAMPLE_CLK: out std_logic;
        FREQ_ERROR: out std_logic_vector(31 downto 0);
		CARRIER_LOCK : OUT std_logic;
		CS1 : OUT std_logic_vector(7 downto 0);
		CS1_CLK : OUT std_logic;
		CS2 : OUT std_logic_vector(7 downto 0);
		CS2_CLK : OUT std_logic;
		CS3 : OUT std_logic_vector(7 downto 0);
		CS3_CLK : OUT std_logic
		);
	END COMPONENT;

	COMPONENT POWER_MEASUREMENT
	generic (
		  REAL_COMPLEXn: std_logic;
        SIMULATION: std_logic 
    );
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		SAMPLE_CLK_IN : IN std_logic;
		DATA_I_IN : IN std_logic_vector(17 downto 0);
		DATA_Q_IN : IN std_logic_vector(17 downto 0);          
		SAMPLE_CLK_OUT : OUT std_logic;
		POWER_OUT : OUT std_logic_vector(23 downto 0)
		);
	END COMPONENT;

	component SIM2OUTFILE is
		 Generic (
			FILENAME: string
		 );
		 Port ( 
			--// CLK, RESET
			CLK: in std_logic;
				-- Reference clock
			DATA1: in std_logic_vector(11 downto 0);
			DATA2: in std_logic_vector(11 downto 0);
			DATA3: in std_logic_vector(11 downto 0);
			SAMPLE_CLK_IN: in std_logic
				-- DATA_IN is read at the rising edge of CLK when SAMPLE_CLK_IN = '1'

	);
	END COMPONENT;

--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
-- Suffix _D indicates a one CLK delayed version of the net with the same name
-- Suffix _E indicates an extended precision version of the net with the same name
-- Suffix _N indicates an inverted version of the net with the same name

--constant NACQ: integer := 30;	--number of parallel code acquisition circuits
constant NACQ: integer := 120;	--number of parallel code acquisition circuits
	-- Always an even number.
	-- KEY ASSUMPTION: the number of parallel circuits NACQ MUST be less (or equal) than the number of 
	-- CLKs in 0.37*symbol period. IMPORTANT!!!!   Adjust the NACQ constant within accordingly.
	-- (why 0.37?  75% of 1/2 a symbol period. See SOID generation).
	
-- Trade-off acquisition time vs Eb/No threshold	
constant N_NCID: integer := 50;		-- appropriate for Eb/No > 5dB approximately
--constant N_NCID: integer := 100;		-- appropriate for Eb/No > 3.9 approximately
--constant N_NCID: integer := 200;	-- appropriate for Eb/No > 2dB approximately
	-- non-coherent I&D period = number of successive coherent I&D results accumulated non-coherently (power-wise)
	-- to improve SNR before making a detection decision.
	-- Range 1 - 255
constant N_NCID_LOG2: integer:= 6;	-- when N_NCID = 50
--constant N_NCID_LOG2: integer:= 7;	-- when N_NCID = 100
--constant N_NCID_LOG2: integer:= 8;	-- when N_NCID = 200
	-- ceiling of log2(N_NCID) = number bits to extend precision in non-coherent accumulators (and conversely to truncate at output)

--// AGC ----------------------	
signal DATA1_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA1_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE1_CLK: std_logic := '0';
signal SATURATION1: std_logic := '0';
	
--//-- FREQUENCY TRANSLATION 1 (UNDER FREQUENCY SCANNING CONTROL) -------------------------------
signal DATA2_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA2_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE2_CLK: std_logic := '0';
signal SATURATION2: std_logic := '0';
signal CCF_PHASE1: std_logic_vector(31 downto 0) := (others => '0');
signal CF_NCO_CONTROL1: std_logic_vector(31 downto 0) := (others => '0');
signal CF_NCO_CONTROL1a: std_logic_vector(31 downto 0) := (others => '0');
signal CF_NCO_CONTROL1b: std_logic_vector(31 downto 0) := (others => '0');
--signal FREQ_SCAN1_FREQUENCY_STEP: std_logic_vector(31 downto 0) := (others => '0');

----// Carrier Center Frequency NCO
--signal CCF_PHASE: std_logic_vector(31 downto 0) := (others => '0');
--signal CCF_PHASE2: std_logic_vector(31 downto 0) := (others => '0');

--//-- RESAMPLING --------------------------
signal NOMINAL_RESAMPLING_RATE: std_logic_vector(31 downto 0) := (others => '0');
signal DATA3_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA3_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE3_CLK: std_logic := '0';
signal SAMPLE3_CNTR: std_logic_vector(0 downto 0) := (others => '0');

--//-- HALF-BAND FILTERS --------------------------
signal SAMPLE3A_CLK: std_logic := '0';
signal DATA4_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA4_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE4_CLK: std_logic := '0';
signal SAMPLE4_CNTR: std_logic_vector(1 downto 0) := (others => '0');
signal DATA5_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA5_Q: std_logic_vector(13 downto 0) := (others => '0');
signal DATA5_I_D: std_logic_vector(13 downto 0) := (others => '0');
signal DATA5_Q_D: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE5_CLK: std_logic := '0';
signal SAMPLE5A_CLK: std_logic := '0';
signal SYMBOL5_CLK: std_logic := '0';

--//-- RAISED COSINE FILTER  --------------------
signal SAMPLE5_SHIFT: std_logic_vector(4 downto 0) := (others => '0');

signal DATA6A_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA6B_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA6_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA6_Q: std_logic_vector(13 downto 0) := (others => '0');
signal DATA6A_Q: std_logic_vector(13 downto 0) := (others => '0');
signal DATA6B_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE6_CLK_E: std_logic := '0';
signal SAMPLE6_CLK: std_logic := '0';
signal SYMBOL6_CLK_E: std_logic := '0';
signal SYMBOL6_CLK: std_logic := '0';

--//-- SPREADING CODE REPLICA (1/2)--------------------

constant CODE_PERIOD: std_logic_vector(15 downto 0):= x"07FF";	-- always 2047
signal CODE_PERIODx2: std_logic_vector(15 downto 0) := (others => '0');
signal CODE_PERIOD_X: std_logic_vector(23 downto 0) := (others => '0');
signal CODE6A_START: std_logic := '0';
signal CODE61A: std_logic_vector((NACQ-1) downto 0) := (others => '0');
signal CODE62A: std_logic_vector((NACQ-1) downto 0) := (others => '0');
signal CODE62A_E: std_logic := '0';
signal CHIPA_CLK_REQ: std_logic := '0';
signal CHIPA_CLK_REQ_MASK: std_logic := '0';
signal SKIP_CNTR_A: integer range 0 to NACQ := 0;	--number of parallel code acquisition circuits
signal CHIP_SKIP_CNTR: std_logic_vector(15 downto 0) := (others => '0');
signal FREQ_SCAN1_STEP_TRIGGER: std_logic := '0';
signal CODE61A_CNTR: std_logic_vector(16 downto 0) := (others => '0');

--//-- SPREADING CODE REPLICA (2/2)--------------------
signal CHIPB_CLK_REQ: std_logic := '0';
signal CHIPB_CLK_REQ_MASK: std_logic := '0';
signal SKIP_CNTR_B: integer range 0 to NACQ := 0;	--number of parallel code acquisition circuits
signal CODE6B_START: std_logic := '0';
signal CODE61B: std_logic_vector(2 downto 0) := (others => '0');
signal CODE62B: std_logic_vector(2 downto 0) := (others => '0');
signal CODE62B_E: std_logic := '0';
signal CODE6B_CNTR: std_logic_vector(16 downto 0) := (others => '0');
signal CODE61AB_CNTR_DIFF: std_logic_vector(16 downto 0) := (others => '0');
signal CODE61AB_CNTR_DIFF_D: std_logic_vector(16 downto 0) := (others => '0');

--//-- CODE ACQUISITION --------------------
signal STATE_ACQ: integer range 0 to 3 := 0;
signal SOID: std_logic := '0';
signal TRUNCATE_OBITS: integer range 0 to 13 := 0;
signal COHERENT_ID_CNTR: std_logic_vector(SPREADING_FACTOR1'left downto 0) := (others => '0');
signal N_CID: std_logic_vector(SPREADING_FACTOR1'left downto 0) := (others => '0');
type SLV14xNACQtype is array (integer range 0 to (NACQ-1)) of std_logic_vector(13 downto 0);
signal DATA7_I: SLV14xNACQtype := (others => (others => '0'));
signal DATA7_Q: SLV14xNACQtype := (others => (others => '0'));
signal SAMPLE7_CLK: std_logic_vector((NACQ-1) downto 0) := (others => '0');
signal SATURATION: std_logic_vector((NACQ-1) downto 0) := (others => '0');
signal SAMPLE7_STAGGERED_CLK: std_logic_vector((NACQ+5) downto 0) := (others => '0');
signal A: std_logic_vector(17 downto 0) := (others => '0');
signal B: std_logic_vector(17 downto 0) := (others => '0');
signal A_D: std_logic_vector(17 downto 0) := (others => '0');
signal B_D: std_logic_vector(17 downto 0) := (others => '0');
signal A_SQUARE: std_logic_vector(35 downto 0) := (others => '0');
signal B_SQUARE: std_logic_vector(35 downto 0) := (others => '0');
signal A_SQUARE_D: std_logic_vector(13 downto 0) := (others => '0');
signal B_SQUARE_D: std_logic_vector(13 downto 0) := (others => '0');
signal AB_SQUARE_D: std_logic_vector(13 downto 0) := (others => '0');

type SLVPOWERACCxNACQtype is array (integer range 0 to (NACQ-1)) of std_logic_vector((13+N_NCID_LOG2) downto 0);
signal POWER_ACC_X: SLVPOWERACCxNACQtype := (others => (others => '0'));
signal POWER_ACC: std_logic_vector(17 downto 0) := (others => '0');
signal POWER_ACC_E: std_logic_vector(17 downto 0) := (others => '0');
signal POWER_ACC_SAMPLE_CLK: std_logic := '0';
signal POWER_ACC_SAMPLE_CLK_E: std_logic := '0';
signal POWER_ACC_SAMPLE_CLK_D: std_logic := '0';
signal POWER_ACC_SAMPLE_CLK_D2: std_logic := '0';
signal POWER_ACC_SAMPLE_CLK_D3: std_logic := '0';
signal NONCOHERENT_ID_CNTR: std_logic_vector((N_NCID_LOG2-1) downto 0) := (others => '0');
signal NONCOHERENT_ID_CNTR_D: std_logic_vector((N_NCID_LOG2-1) downto 0) := (others => '0');
signal NONCOHERENT_ID_CNTR_D2: std_logic_vector((N_NCID_LOG2-1) downto 0) := (others => '0');
signal NONCOHERENT_ID_CNTR_D3: std_logic_vector((N_NCID_LOG2-1) downto 0) := (others => '0');
signal POWER_ACC_MAX: std_logic_vector(17 downto 0) := (others => '0');
signal IMAX: integer range 0 to (NACQ-1) := 0;
signal IMAX_PTR: integer range 1 to NACQ := 1;
signal POWER_ACC_SAMPLE_CNTR: std_logic_vector(15 downto 0) := (others => '0');
signal EPOCH: integer range 0 to (NACQ-1) := 0;
signal POWER_ACC_MAX_SAMPLE_CLK: std_logic := '0';
signal POWER_AVERAGE_X: std_logic_vector(23 downto 0) := x"000000";	-- 18bit + 6 for 64 sample running average
signal POWER_AVERAGE: std_logic_vector(17 downto 0) := (others => '0');	
signal POWER_AVERAGE_D: std_logic_vector(17 downto 0) := (others => '0');
signal DETECT_THRESHOLD: std_logic_vector(19 downto 0) := (others => '0');
signal DETECT: std_logic := '0';
signal DETECT_D: std_logic := '0';
signal NODETECT: std_logic := '0';
signal DETECT_FL2: std_logic := '0';
signal FIRST_ACC_ONTIME_REF_FLAG: std_logic := '0';

--//-- SNR (when code lock is achieved) -------------------------------------
signal SNR_DENOM: std_logic_vector(17 downto 0) := (others => '0');
signal SNR_LOCKED: std_logic_vector(17 downto 0) := (others => '0');
signal SNR_LOCKED_SAMPLE_CLK: std_logic := '0';

--//-- FALSE LOCK DETECTION --------------------
signal IMAX_FL: integer range 0 to (NACQ-4) := 0;
signal POWER_FL_BIN: integer range 0 to (NACQ-3) := 0;
signal POWER_ACC_MAX_FL: std_logic_vector(17 downto 0) := (others => '0');
signal POWER_ACC_MAX_FL_SAMPLE_CLK: std_logic := '0';
signal DETECT_THRESHOLD_FL: std_logic_vector(19 downto 0) := (others => '0');
signal DETECT_FL: std_logic := '0';
signal NODETECT_FL: std_logic := '0';
signal EPOCH_FL: integer range 0 to (NACQ-1) := 0;
signal POWER_ACC_ONTIME_REF: std_logic_vector(17 downto 0) := (others => '0');
signal POWER_ACC_ONTIME_REF_SAMPLE_CLK: std_logic := '0';

--//-- DESPREADING --------------------
signal DATA81_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA81_Q: std_logic_vector(13 downto 0) := (others => '0');
signal DATA82_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA82_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE8_CLK: std_logic := '0';

--//-- CODE TRACKING --------------------
signal FREEZE_CODE_TRACKING: std_logic := '0';
signal CODE_TRACKING2_LOOP_GAIN: std_logic_vector(1 downto 0) := (others => '0');
signal POWER_ID_SAMPLE_CLK: std_logic := '0';
signal POWER_ID_EARLY: std_logic_vector(13 downto 0) := (others => '0');
signal POWER_ID_LATE: std_logic_vector(13 downto 0) := (others => '0');
signal NCO_TIMING_CONTROL: std_logic_vector(31 downto 0) := (others => '0');
signal NCO_TIMING_CONTROL_CLK: std_logic := '0';
signal CODE_LOCK: std_logic := '0';

--//-- SYMBOL CLK GENERATION ------------------------
signal NOMINAL_SYMBOL_RATE1x2: std_logic_vector(31 downto 0) := (others => '0');
signal NOMINAL_SYMBOL_RATE2x2: std_logic_vector(31 downto 0) := (others => '0');
signal ST_NCO_TIMING_CONTROL1_DIV: std_logic_vector(31 downto 0) := (others => '0');
signal ST_NCO_TIMING_CONTROL2_DIV: std_logic_vector(31 downto 0) := (others => '0');
signal SYMBOL81_CLK: std_logic := '0';
signal SYMBOL81_NODELAY: std_logic := '0';
signal SYMBOL81_HALFSYMBOLDELAY: std_logic := '0';
signal SYMBOL81_CLKx2: std_logic := '0';
signal SYMBOL81_CLK_CNTR:  std_logic_vector(0 downto 0) := (others => '0');
signal SYMBOL82_CLK: std_logic := '0';
signal SYMBOL82A_CLK: std_logic := '0';
signal SYMBOL82_CLKx2: std_logic := '0';
signal SYMBOL82A_CLKx2: std_logic := '0';
signal SYMBOL82A_CLK_CNTR:  std_logic_vector(0 downto 0) := (others => '0');

--//-- FINAL NOISE REJECTION: INTEGRATE & DUMP --------------------------------------
signal SAMPLE101_ID_CLK: std_logic;
signal DATA101_I_ACC: std_logic_vector(25 downto 0) := (others => '0');
signal DATA101_Q_ACC: std_logic_vector(25 downto 0) := (others => '0');
signal DATA101_I_ID: std_logic_vector(25 downto 0) := (others => '0');
signal DATA101_Q_ID: std_logic_vector(25 downto 0) := (others => '0');
signal SAMPLE111_ID_CLK: std_logic;
signal DATA111_I_ACC: std_logic_vector(25 downto 0) := (others => '0');
signal DATA111_Q_ACC: std_logic_vector(25 downto 0) := (others => '0');
signal DATA111_I_ID: std_logic_vector(25 downto 0) := (others => '0');
signal DATA111_Q_ID: std_logic_vector(25 downto 0) := (others => '0');

signal SAMPLE102_ID_CLK: std_logic;
signal DATA102_I_ACC: std_logic_vector(25 downto 0) := (others => '0');
signal DATA102_Q_ACC: std_logic_vector(25 downto 0) := (others => '0');
signal DATA102_I_ID: std_logic_vector(25 downto 0) := (others => '0');
signal DATA102_Q_ID: std_logic_vector(25 downto 0) := (others => '0');
signal SAMPLE112_ID_CLK: std_logic;
signal DATA112_I_ACC: std_logic_vector(25 downto 0) := (others => '0');
signal DATA112_Q_ACC: std_logic_vector(25 downto 0) := (others => '0');
signal DATA112_I_ID: std_logic_vector(25 downto 0) := (others => '0');
signal DATA112_Q_ID: std_logic_vector(25 downto 0) := (others => '0');

--//-- NORMALIZE I&D outputs ---------------------
signal SHIFT101: std_logic_vector(SPREADING_FACTOR1'left downto 0) := (others => '0');	-- same as SPREADING_FACTOR1
signal SHIFT111: std_logic_vector(SPREADING_FACTOR1'left downto 0) := (others => '0');	-- same as SPREADING_FACTOR1
signal COUNT_ENABLE101: std_logic := '0';
signal COUNT_ENABLE101_D: std_logic := '0';
signal COUNT_ENABLE111: std_logic := '0';
signal COUNT_ENABLE111_D: std_logic := '0';
signal DATA101_I_SHIFT: std_logic_vector(25 downto 0) := (others => '0');
signal DATA101_Q_SHIFT: std_logic_vector(25 downto 0) := (others => '0');
signal DATA111_I_SHIFT: std_logic_vector(25 downto 0) := (others => '0');
signal DATA111_Q_SHIFT: std_logic_vector(25 downto 0) := (others => '0');
signal DATA131_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA131_Q: std_logic_vector(13 downto 0) := (others => '0');
signal DATA131_I_E: std_logic_vector(13 downto 0) := (others => '0');
signal DATA131_Q_E: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE131_CLK: std_logic := '0';
signal SYMBOL131_CLK: std_logic := '0';
signal SYMBOL131_SHIFT: std_logic_vector(1 downto 0) := (others => '0');

signal SHIFT102: std_logic_vector(SPREADING_FACTOR1'left downto 0) := (others => '0');	-- same as SPREADING_FACTOR1
signal SHIFT112: std_logic_vector(SPREADING_FACTOR1'left downto 0) := (others => '0');	-- same as SPREADING_FACTOR1
signal COUNT_ENABLE102: std_logic := '0';
signal COUNT_ENABLE102_D: std_logic := '0';
signal COUNT_ENABLE112: std_logic := '0';
signal COUNT_ENABLE112_D: std_logic := '0';
signal DATA102_I_SHIFT: std_logic_vector(25 downto 0) := (others => '0');
signal DATA102_Q_SHIFT: std_logic_vector(25 downto 0) := (others => '0');
signal DATA112_I_SHIFT: std_logic_vector(25 downto 0) := (others => '0');
signal DATA112_Q_SHIFT: std_logic_vector(25 downto 0) := (others => '0');
signal DATA132_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA132_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE132_CLK: std_logic := '0';
signal SYMBOL132_CLK: std_logic := '0';
signal SYMBOL132_SHIFT: std_logic_vector(1 downto 0) := (others => '0');

signal DATA131B_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA131B_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE131B_CLK: std_logic := '0';
signal SYMBOL131B_CLK: std_logic := '0';
signal DATA132B_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA132B_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE132B_CLK: std_logic := '0';
signal SYMBOL132B_CLK: std_logic := '0';

--// FAST FREQUENCY ACQUISITION --------------------
constant NID_MAX_LOG2: integer := 9;
signal FFD_NID: integer range 1 to 2**NID_MAX_LOG2 := 512;
signal FFD_NID_LOG2: integer range 0 to 11 := 8;	
signal FFD_ENABLE: std_logic := '0';
signal FFD_SATURATION: std_logic := '0';
signal DATA81_Ix: std_logic_vector(17 downto 0) := (others => '0');
signal DATA81_Qx: std_logic_vector(17 downto 0) := (others => '0');

--// FAST SYNCHRONIZATION ---------------------
signal FFTM: std_logic_vector(13 downto 0) := (others => '0');
signal FFTM2: std_logic_vector(13 downto 0) := (others => '0');
signal FFTM_AVRG: std_logic_vector(13 downto 0) := (others => '0');
signal FFTM_THRESHOLD: std_logic_vector(13 downto 0) := (others => '0');
signal SIGNAL_PRESENT_local: std_logic := '0';
signal FFTF: std_logic_vector(10 downto 0) := (others => '0');
signal FFTP: std_logic_vector(10 downto 0) := (others => '0');
signal FFT_READY: std_logic := '0';
signal FFT_READY_D: std_logic := '0';
signal FFTF_SHIFT_CNTR: unsigned(3 downto 0) := (others => '0');
signal FFT_SHIFT_FLAG: std_logic := '0';
signal FFTF_SHIFT: std_logic_vector(31 downto 0) := (others => '0');
signal FFT_FREQ_ERROR: std_logic_vector(31 downto 0) := (others => '0');
signal FFT_ERROR_SAMPLE_CLK: std_logic := '0';
signal FFD_TP: std_logic_vector(10 downto 1) := (others => '0');

--// NORMALIZE AFTER FILTER ---------------------
signal DATA13M: std_logic_vector(13 downto 0)  := (others => '0');
signal SAMPLE13M_CLK: std_logic := '0';
signal AGC18_MAGNITUDE_TARGET: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE141_CLK: std_logic := '0';
signal SYMBOL141_CLK: std_logic := '0';
signal SYMBOL141_SHIFT: std_logic_vector(1 downto 0) := (others => '0');
signal DATA141_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA141_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SAMPLE142_CLK: std_logic := '0';
signal SYMBOL142_CLK: std_logic := '0';
signal SYMBOL142_SHIFT: std_logic_vector(1 downto 0) := (others => '0');
signal DATA142_I: std_logic_vector(13 downto 0) := (others => '0');
signal DATA142_Q: std_logic_vector(13 downto 0) := (others => '0');
signal SATURATION_AGC1: std_logic := '0';
signal SATURATION_AGC2: std_logic := '0';

--//-- FREQUENCY TRANSLATION 2 (UNDER PLL CONTROL) -------------------------------
signal DATA151_I: std_logic_vector(11 downto 0) := (others => '0');
signal DATA151_Q: std_logic_vector(11 downto 0) := (others => '0');
signal SAMPLE151_CLK: std_logic := '0';
signal SYMBOL151_CLK: std_logic := '0';
signal SATURATION151: std_logic := '0';
signal DATA152_I: std_logic_vector(11 downto 0) := (others => '0');
signal DATA152_Q: std_logic_vector(11 downto 0) := (others => '0');
signal SAMPLE152_CLK: std_logic := '0';
signal SYMBOL152_CLK: std_logic := '0';
signal SATURATION152: std_logic := '0';
signal CCF_PHASE2: std_logic_vector(31 downto 0) := (others => '0');
signal CCF_PHASE2_D: std_logic_vector(31 downto 0) := (others => '0');
signal CF_NCO_CONTROL2B0: std_logic_vector(31 downto 0) := (others => '0');
signal CF_NCO_CONTROL2B: std_logic_vector(31 downto 0) := (others => '0');
signal CF_NCO_CONTROL2A0: std_logic_vector(31 downto 0) := (others => '0');
signal CF_NCO_CONTROL2A0_SAMPLE_CLK: std_logic := '0';
signal CF_NCO_CONTROL2A: std_logic_vector(31 downto 0) := (others => '0');
signal CF_NCO_CONTROL2A_SAMPLE_CLK: std_logic := '0';

--// After spectrum inversion
signal DATA161_I: std_logic_vector(11 downto 0) := (others => '0');
signal DATA161_Q: std_logic_vector(11 downto 0) := (others => '0');
signal DATA161_I_X: std_logic_vector(17 downto 0) := (others => '0');
signal DATA161_Q_X: std_logic_vector(17 downto 0) := (others => '0');
signal SAMPLE161_CLK: std_logic := '0';
signal SYMBOL161_CLK: std_logic := '0';
signal DATA162_I: std_logic_vector(11 downto 0) := (others => '0');
signal DATA162_Q: std_logic_vector(11 downto 0) := (others => '0');
signal DATA162_I_X: std_logic_vector(17 downto 0) := (others => '0');
signal DATA162_Q_X: std_logic_vector(17 downto 0) := (others => '0');
signal SAMPLE162_CLK: std_logic := '0';
signal SYMBOL162_CLK: std_logic := '0';

--//-- CARRIER TRACKING --------------------
signal CT_SYNC_RESET: std_logic := '0';
signal ACTR2: std_logic := '0';	

signal ACCELERATED_CT_RESPONSE: std_logic := '0';
signal PE: std_logic_vector(11 downto 0):= (others => '0');	-- one bit extension to prevent overflow
signal PE_SYMBOL_CLK: std_logic := '0'; 
signal CARRIER_LOCK_local: std_logic := '0';
signal PHASE_OFFSET_SAMPLE_CLK: std_logic := '0';
--signal CF_ERROR_ACC: std_logic_vector(27 downto 0) := (others => '0');
signal CT_LOCK_THRESHOLD: std_logic_vector(3 downto 0):= (others => '0');	

signal SYMBOL_CNTR: std_logic_vector(9 downto 0) := (others => '0');
signal SYMBOL_DIV1K: std_logic := '0';
signal CARRIER_LOCK_CONFIDENCE: std_logic_vector(2 downto 0) := "000";
signal STATE: integer range 0 to 3 := 0;

--//-- SYMBOL TRACKING ------------------------
signal ST_SYNC_RESET: std_logic := '0';
signal ST2_SYNC_RESET: std_logic := '0';
signal ST2_RESET: std_logic := '0';
signal ST_PHASE_ACC1: std_logic_vector(31 downto 0) := (others => '0');
signal ST_NCO_TIMING_CONTROL1: std_logic_vector(31 downto 0) := (others => '0');
signal ST_NCO_TIMING_CONTROL1_CLK: std_logic := '0';
signal ST_NCO_TIMING_CONTROL2: std_logic_vector(31 downto 0) := (others => '0');
signal ST_NCO_TIMING_CONTROL2_CLK: std_logic := '0';
signal ACCELERATED_STLOOP_RESPONSE: std_logic := '0';

--//-- PSK SYMBOL DECODING ------------------------------------------------
signal SYMBOL191_CLK: std_logic := '0';
signal DATA191: std_logic_vector(3 downto 0) := (others => '0');
signal DATA191_D: std_logic_vector(3 downto 0) := (others => '0');
signal DATA191QUAL: std_logic_vector(2 downto 0) := (others => '0');
signal DATA191QUAL_D: std_logic_vector(2 downto 0) := (others => '0');
signal DATA191AQUAL: std_logic_vector(3 downto 0) := (others => '0');
signal SYMBOL192_CLK: std_logic := '0';
signal DATA192: std_logic_vector(3 downto 0) := (others => '0');
signal DATA192_D: std_logic_vector(3 downto 0) := (others => '0');
signal DATA192QUAL: std_logic_vector(2 downto 0) := (others => '0');
signal DATA192QUAL_D: std_logic_vector(2 downto 0) := (others => '0');
signal SYMBOL201_CLK: std_logic := '0';
signal SYMBOL202_CLK: std_logic := '0';
signal DATA201: std_logic_vector(3 downto 0) := "0000";
signal DATA202: std_logic_vector(3 downto 0) := "0000";
signal BIPHASE201: std_logic := '0';
signal BIPHASE202: std_logic := '0';
signal BIPHASE_ERROR_COUNTER201: std_logic_vector(7 downto 0);
signal BIPHASE_ERROR_COUNTER202: std_logic_vector(7 downto 0);

signal SIM2_3: std_logic_vector(11 downto 0) := (others => '0');
signal SIM4_3: std_logic_vector(11 downto 0) := (others => '0');

--// Carrier NCO
signal NCO_CONTROL: std_logic_vector(23 downto 0) := (others => '0');
signal NCO_CONTROL_B: std_logic_vector(23 downto 0) := (others => '0');
	-- NCO input. signed integer, 2's complement.
	-- value added at every CLK_DIV2 period to the NCO accumulator. 
	-- 0111...111 is (almost) +fclk/2, 100...000 is -fclk/2, where fs is  
	-- the sampling frequency

signal POWER161: std_logic_vector(23 downto 0) := (others => '0');
signal POWER162: std_logic_vector(23 downto 0) := (others => '0');
signal NOISE161: std_logic_vector(23 downto 0) := (others => '0');
signal NOISE161_DIV4: std_logic_vector(23 downto 0) := (others => '0');
signal POWER161_VALID: std_logic := '0';
signal POWER162_VALID: std_logic := '0';
signal SNRx_NUM: std_logic_vector(17 downto 0) := (others => '0');
signal SNRx_SAMPLE_CLK_IN: std_logic := '0';
signal SNRx_LOCKED: std_logic_vector(17 downto 0) := (others => '0');
signal SNRx_VALID: std_logic := '0';
signal SNR_MUX_STATE: integer range 0 to 3 := 0;
--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------

begin

--//-- INTERNAL AGC -------------------------------------------------------------
-- normalize the input
AGC18_000: AGC18 
GENERIC MAP(
	AVERAGING_LENGTH => 1024,
	SIMULATION => SIMULATION
)
PORT MAP(
	CLK => CLK,
	SYNC_RESET => SYNC_RESET,
	DATA_I_IN => DATA_I_IN,
	DATA_Q_IN => DATA_Q_IN,
	SAMPLE_CLK_IN => SAMPLE_CLK_IN,
	MTARGET => "00110000000000",
	CONTROL => "1",	-- always enabled
	SYMBOLx2_CLK_IN => SAMPLE5_CLK,
	DATA_I_OUT => DATA1_I,
	DATA_Q_OUT => DATA1_Q,
	SAMPLE_CLK_OUT => SAMPLE1_CLK,
	SATURATION => SATURATION1,
	DATA_M => open,
	SAMPLE_M_CLK => open,
	TP => open,
	CS1 => open,
	CS1_CLK => open
);

--//-- FREQUENCY TRANSLATION 1  -------------------------------
-- Remove center frequency. 
-- latency 3 CLKs
DIGITAL_DC2_001: DIGITAL_DC2 PORT MAP(
	CLK => CLK,
	DATA_I_IN => DATA1_I(13 downto 2),
	DATA_Q_IN => DATA1_Q(13 downto 2),
	SAMPLE_CLK_IN => SAMPLE1_CLK,
	PHASE_ROTATION => CCF_PHASE1(31 downto 20),	-- CCF_PHASE1 is added to the input signal phase
	DATA_I_OUT => DATA2_I(13 downto 2),
	DATA_Q_OUT => DATA2_Q(13 downto 2),
	SAMPLE_CLK_OUT => SAMPLE2_CLK,
	SATURATION => SATURATION2
);

-- 2D code/frequency acquisition 
-- frequency step is 1/4 of the nominal symbol rate. However, the coarse frequency scan is only
-- activated in extreme cases where the FFT-based acquisition is insufficient.
-- The FAST_FREQUENCY_DETECTION is sized for a worst case +/- 5 KHz center frequency error.
--FREQ_SCAN1_FREQUENCY_STEP <= "00" & NOMINAL_SYMBOL_RATE1(31 downto 2);	--6/25/14

--FREQ_SCAN1_001: FREQ_SCAN PORT MAP(
--	CLK => CLK,
--	SYNC_RESET => SYNC_RESET,	
--	FREQUENCY_STEP => FREQ_SCAN1_FREQUENCY_STEP,
--	N_STEPS => FREQ_SCAN_N_COARSE_STEPS,
--	STEP_TRIGGER => FREQ_SCAN1_STEP_TRIGGER,
--	FREQUENCY_OUT => CF_NCO_CONTROL1
--);
-- SIMPLIFY: DISABLE FREQ SCAN UNLESS ABSOLUTELY NEEDED


-- Phase offset is nominally controlled by (a) the frequency error measured 
-- by FAST_FREQUENCY_DETECTION during acquisition and (b) the 2nd order branch (frequency error) of the final carrier tracking loop.
-- Note: the 1st order branch of the final carrier tracking loop is not corrected here because it needs to be fast, which is 
-- not really possible due to the delay in the integration and dump LPFs.
NCO32_001: process(CLK)
begin
	if rising_edge(CLK) then
--		CF_NCO_CONTROL1a <= CF_NCO_CONTROL1 + CF_NCO_CONTROL2B; -- frequency scan + costas loop (2nd order branch)
		CF_NCO_CONTROL1a <= CF_NCO_CONTROL2B; -- costas loop (2nd order branch)
		CF_NCO_CONTROL1b <= CF_NCO_CONTROL1a - FFT_FREQ_ERROR; -- FFT

		if(SYNC_RESET = '1') or ((SIMULATION = '1') and (CF_NCO_CONTROL1a(0) = 'X')) then
		     -- prevents X propagation in the accumulator during simulation
			CCF_PHASE1 <= (others => '0');
		elsif(SAMPLE5_CLK = '1') then
			-- accumulate phase 
			-- 2x chip rate. Frequency correction based on FFT frequency measurement
			CCF_PHASE1 <= CCF_PHASE1 + CF_NCO_CONTROL1b;
		else
			-- accumulate phase
			CCF_PHASE1 <= CCF_PHASE1 + CF_NCO_CONTROL1a;
		end if;
	end if;
end process;

-- report the frequency error in two parts (different units, simpler to do the aggregation outside in a micro)
CARRIER_TRACK_007: process(CLK)
begin
	if rising_edge(CLK) then
		-- total frequency error = scanning frequency + carrier tracking loop frequency
		CARRIER_FREQUENCY_ERROR1 <= not(CF_NCO_CONTROL2B + CF_NCO_CONTROL1);		-- 4/29/15
		CARRIER_FREQUENCY_ERROR2 <= FFT_FREQ_ERROR;		-- 4/29/15
	end if;
end process;


--//-- RESAMPLING --------------------------
-- Resample at exactly x4 or x2 times per chip
-- under the control of the bit timing tracking loop.
RESAMPLING_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(NOMINAL_CHIP_RATE(31 downto 30) = "00") then
			-- resample at 4 samples per chip (preferred). This resampling will be followed by a half-band filter and 1:2 decimation.
			NOMINAL_RESAMPLING_RATE <= NOMINAL_CHIP_RATE(29 downto 0) & "00";
		else
			-- Chip rate is too high to resample at 4x/chip (preferred).Resample at 2 samples per chip
			NOMINAL_RESAMPLING_RATE <= NOMINAL_CHIP_RATE(30 downto 0) & "0";
		end if;
	end if;
end process;

RESAMPLING_002: RESAMPLING2 
GENERIC MAP(
	NBITS => 14
)
PORT MAP(
	CLK => CLK,
	DATA_I_IN => DATA2_I,
	DATA_Q_IN => DATA2_Q,
	SAMPLE_CLK_IN => SAMPLE2_CLK,
	NOMINAL_RESAMPLING_RATE => NOMINAL_RESAMPLING_RATE,
	NCO_OFFSET => NCO_TIMING_CONTROL,
	NCO_OFFSET_SAMPLE_CLK => NCO_TIMING_CONTROL_CLK,
	DATA_I_OUT => DATA3_I,
	DATA_Q_OUT => DATA3_Q,
	SAMPLE_CLK_OUT => SAMPLE3_CLK	-- exactly x2 or x4 samples per chip while timing loop is tracking
);


--//-- HALF-BAND FILTERS --------------------------
-- before resampling, further reduce input signal bandwidth.
-- We can narrow the bandwidth because the signal is truly centered at 0 Hz while the carrier tracking loop is locked.

-- save power. Do not use filter if resampling is done at 2x chip rate
SAMPLE3A_CLK <= SAMPLE3_CLK when (NOMINAL_CHIP_RATE(31 downto 30) = "00") else '0';

-- latency 6 CLK
FIRHALFBAND3_I2: FIRHALFBAND3 PORT MAP(
	CLK => CLK,
	SAMPLE_CLK_IN => SAMPLE3A_CLK,		-- 4 samples per chip
	DATA_IN => DATA3_I,
	SAMPLE_CLK_OUT => SAMPLE4_CLK,		
	DATA_OUT => DATA4_I
);

FIRHALFBAND3_Q2: FIRHALFBAND3 PORT MAP(
	CLK => CLK,
	SAMPLE_CLK_IN => SAMPLE3A_CLK,		-- 4 samples per chip
	DATA_IN => DATA3_Q,
	SAMPLE_CLK_OUT => open,		
	DATA_OUT => DATA4_Q
);

-- bypass HBF and subsequent 1:2 decimation to 2x chip rate if resampling is already at 2x chip rate
HBF_BYPASS_001:  process(CLK)
begin
	if rising_edge(CLK) then
		if(NOMINAL_CHIP_RATE(31 downto 30) = "00") then
			-- decimate from x4 to x2 chip rate
			if(SAMPLE4_CLK = '1') then
				SAMPLE4_CNTR <= SAMPLE4_CNTR + 1;	-- modulo-4 counter
				if (SAMPLE4_CNTR(0) = '0') then
					DATA5_I <= DATA4_I;
					DATA5_Q <= DATA4_Q;
					SAMPLE5_CLK <= '1';
				else
					SAMPLE5_CLK <= '0';
				end if;
				if (SAMPLE4_CNTR = "00") then
					SYMBOL5_CLK <= '1';
				else
					SYMBOL5_CLK <= '0';
				end if;
			else
				SAMPLE5_CLK <= '0';
				SYMBOL5_CLK <= '0';
			end if;
		else
			-- bypass HBF. Already sampling at x2 chip rate
			if(SAMPLE3_CLK = '1') then
				SAMPLE3_CNTR <= SAMPLE3_CNTR + 1;	-- modulo-2 counter
				DATA5_I <= DATA3_I;
				DATA5_Q <= DATA3_Q;
				SAMPLE5_CLK <= '1';
				if (SAMPLE3_CNTR = "0") then
					SYMBOL5_CLK <= '1';
				else
					SYMBOL5_CLK <= '0';
				end if;
			else
				SAMPLE5_CLK <= '0';
				SYMBOL5_CLK <= '0';
			end if;
		end if;
	end if;
end process;

SYMBOL_CLK <= SYMBOL5_CLK;
	-- time reference related to the modulation bandwidth. Originates from the demodulator. 
	-- used by the AGC and bias removal circuitry to avoid tracking the modulation.

----//-- RAISED COSINE FILTER  --------------------
---- Objective: Noise rejection. However, the waveform smoothing introduces despreading losses (because we despread with a square signal). 
---- Tradeoff despreading losses vs noise performance when deciding to keep RRC filter or bypass it.
---- input sampling rate: 2 samples per symbol
---- output sampling rate: 2 samples per symbol
---- Latency is 5 CLK
--
---- mux two samples in, symbol center first
--RCMUX_001: process(CLK)
--begin
--	if rising_edge(CLK) then
--		if(SYMBOL5_CLK = '1') then
--			DATA5_I_D <= DATA5_I;
--			DATA5_Q_D <= DATA5_Q;
--		end if;
--	end if;
--end process;
--
--SAMPLE5A_CLK <= '1' when (SAMPLE5_CLK = '1') and (SYMBOL5_CLK = '0') else '0';
--
--RAISED_COS2_40_001: RAISED_COS2_40 PORT MAP(
--	CLK => CLK,
--	SAMPLE_CLK_IN => SAMPLE5A_CLK,
--	DATA0_IN => DATA5_I_D,
--	DATA180_IN => DATA5_I,
--	SAMPLE_CLK_OUT => SYMBOL6_CLK,
--	DATA0_OUT => DATA6A_I,
--	DATA180_OUT => DATA6B_I
--);
--RAISED_COS2_40_002: RAISED_COS2_40 PORT MAP(
--	CLK => CLK,
--	SAMPLE_CLK_IN => SAMPLE5A_CLK,
--	DATA0_IN => DATA5_Q_D,
--	DATA180_IN => DATA5_Q,
--	SAMPLE_CLK_OUT => open,
--	DATA0_OUT => DATA6A_Q,
--	DATA180_OUT => DATA6B_Q
--);
--
---- demux filter output samples
--RCDEMUX_001: process(CLK)
--begin
--	if rising_edge(CLK) then
--		SAMPLE5_SHIFT(4 downto 0) <= SAMPLE5_SHIFT(3 downto 0) & SAMPLE5_CLK;
--	end if;
--end process;
--
--SAMPLE6_CLK <= SAMPLE5_SHIFT(4);	-- 5 CLK latency
--DATA6_I <= DATA6A_I when (SYMBOL6_CLK = '1') else DATA6B_I;
--DATA6_Q <= DATA6A_Q when (SYMBOL6_CLK = '1') else DATA6B_Q;

--
--SAMPLE6_CLK_E <= SAMPLE5_CLK_D4;	-- 1 clk early
--SYMBOL6_CLK_E <= SYMBOL5_CLK_D4;

-- Bypass Root raised cosine filter. sharper edges for less despreading losses. However lets in more noise.
-- The noise will be filtered out after despreading.
SAMPLE6_CLK_E <= SAMPLE5_CLK;	-- 1 clk early
SYMBOL6_CLK_E <= SYMBOL5_CLK;

FIRCOS_001: process(CLK)
begin
	if rising_edge(CLK) then
		DATA6_I <= DATA5_I;
		DATA6_Q <= DATA5_Q;
		SAMPLE6_CLK <= SAMPLE6_CLK_E;
		SYMBOL6_CLK <= SYMBOL6_CLK_E;
	end if;
end process;

--//-- SPREADING CODE REPLICA (1/2)--------------------
-- The code replica generator 
-- 1 CLK latency between request (BIT_CLK_REQ) and CODE_BIT output.
CODE_PERIOD_X <= ext(CODE_PERIOD,24);

CODEGEN3_001A: CODEGEN3 PORT MAP (
	CLK => CLK,
	BIT_CLK_REQ => CHIPA_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	LFSRA_INIT => LFSRA_INIT, 
	LFSRC_INIT => LFSRC_INIT, 
	CODE_MODE => CODE_MODE,
	BIT_CLK_OUT => open,	-- aligned with SYMBOL6_CLK,
	CODE_START => CODE6A_START,
	CODE_I_BIT => CODE61A(0),	-- I-code
	CODE_Q_BIT => CODE62A_E,	-- Q-code, staggered offset to be done subsequently (not done within)
	BIT_COUNT_OUT => CODE61A_CNTR(10 downto 0)
);


-- pulse to request the next chip
CHIPA_CLK_REQ <= SYMBOL6_CLK_E and (not CHIPA_CLK_REQ_MASK);

CODE_START_OUT <= CODE6A_START;
	-- 1 CLK pulse indicating the 1st chip in the periodic code replica.
	-- Can be used for round-trip delay measurement.

-- Skip NACQ half-chips while generating the code replica
CODEGEN_002A:  process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			CHIPA_CLK_REQ_MASK <= '0';
			SKIP_CNTR_A <= 0;
		elsif(STATE_ACQ = 0) and (NODETECT = '1') then
			-- No detection while searching this stretch of NACQ/2 chips.
			-- skip NACQ/2 chips
			SKIP_CNTR_A <= NACQ;	-- re-arm counter
			CHIPA_CLK_REQ_MASK <= '1';
		elsif(STATE_ACQ = 0) and (DETECT = '1') then
			-- detected code match with an offset of EPOCH/2 chips
			-- skip EPOCH/2 chips
			if(EPOCH > 1) then
				SKIP_CNTR_A <= EPOCH-1;	-- re-arm counter
				CHIPA_CLK_REQ_MASK <= '1';
			else
				SKIP_CNTR_A <= 0;	-- no code shift needed
			end if;
		elsif(STATE_ACQ = 3) and (DETECT_FL = '1') then
			-- detected false lock or loss of lock. Skip 1.5 chips
			SKIP_CNTR_A <= 3;	-- re-arm counter
			CHIPA_CLK_REQ_MASK <= '1';
		elsif(SAMPLE6_CLK_E = '1') and (SKIP_CNTR_A /= 0) then
			-- count-down, 1/2 chip apart
			SKIP_CNTR_A <= SKIP_CNTR_A - 1;
			if(SKIP_CNTR_A = 1) then
				CHIPA_CLK_REQ_MASK <= '0';
			end if;
		end if;
	end if;
end process;

-- new 4/8/13 
-- 2D code/frequency acquisition:
-- Keep track whether we went full circle searching for all possible code epochs (if so, time to jump to the next frequency bin)
ACQ_2D_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYMBOL6_CLK_E = '1') and (CHIPA_CLK_REQ_MASK = '1')then
			-- skipping 1 chip during acquisition
			if(CHIP_SKIP_CNTR = CODE_PERIOD) then
				CHIP_SKIP_CNTR <= (0 => '1', others => '0');
				FREQ_SCAN1_STEP_TRIGGER <= '1';
			else
				CHIP_SKIP_CNTR <= CHIP_SKIP_CNTR + 1;
				FREQ_SCAN1_STEP_TRIGGER <= '0';
			end if;
		else
			FREQ_SCAN1_STEP_TRIGGER <= '0';
		end if;
	end if;
end process;


--//-- SPREADING CODE REPLICA (2/2)--------------------
-- Second, independent, code generator used to detect false locks/loss of lock while in the tracking phase.
-- Unused during initial acquisition.
CODEGEN3_001B: CODEGEN3 PORT MAP (
	CLK => CLK,
	BIT_CLK_REQ => CHIPB_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	LFSRA_INIT => LFSRA_INIT, 
	LFSRC_INIT => LFSRC_INIT, 
	CODE_MODE => CODE_MODE,
	BIT_CLK_OUT => open,	-- aligned with SYMBOL6_CLK,
	CODE_START => CODE6B_START,
	CODE_I_BIT => CODE61B(0),	-- I-code
	CODE_Q_BIT => CODE62B_E,	-- Q-code, staggered offset to be done subsequently (not done within)
	BIT_COUNT_OUT => CODE6B_CNTR(10 downto 0)
);

-- pulse to request the next chip
CHIPB_CLK_REQ <= SYMBOL6_CLK_E and (not CHIPB_CLK_REQ_MASK);


-- Keep scanning code while in tracking mode (so as to detect false lock or loss of lock)
CODEGEN_002B:  process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			CHIPB_CLK_REQ_MASK <= '0';
			SKIP_CNTR_B <= 0;
		elsif(CODE_PERIOD <= conv_std_logic_vector((NACQ/2),CODE_PERIOD'length)) then
			-- To avoid infinite code6B shift, make sure NACQ/2 > CODE PERIOD
			-- special case: short code period (would repeat in NACQ/2 processing bins)
			-- use fixed CODE61A for false lock detection instead of scanning CODE6B
			CHIPB_CLK_REQ_MASK <= '0';
			SKIP_CNTR_B <= 0;
		elsif(STATE_ACQ = 3) and (NODETECT_FL = '1') then
			-- No false lock detection while searching this stretch of (NACQ-3)/2 chips.
			-- skip (NACQ-3)/2 chips
			SKIP_CNTR_B <= NACQ-3;	-- re-arm counter
			CHIPB_CLK_REQ_MASK <= '1';
		elsif (CODE61AB_CNTR_DIFF_D > (CODE_PERIOD_X(16 downto 0) - conv_std_logic_vector((NACQ/2),17))) then
			-- check for possible presence of good correlation peak in the next (NACQ-3)/2 bins
			-- if so, keep on shifting.
			CHIPB_CLK_REQ_MASK <= '1';
			SKIP_CNTR_B <= 1;
		elsif(SAMPLE6_CLK_E = '1') and (SKIP_CNTR_B /= 0) then
			-- count-down, 1/2 chip apart
			SKIP_CNTR_B <= SKIP_CNTR_B - 1;
			if(SKIP_CNTR_B = 1) then
				CHIPB_CLK_REQ_MASK <= '0';
			end if;
		end if;
	end if;
end process;

-- keep track of the phase difference between code replicas A and B is (in chips, modulo code period)
-- Goal is to avoid having a good code sync while searching for false lock in the next (NACQ-3)/2 code phases. 
CODEGEN_002c:  process(CLK)
begin
	if rising_edge(CLK) then
		CODE61AB_CNTR_DIFF <=  CODE61A_CNTR(16 downto 0) - CODE6B_CNTR(16 downto 0);
		-- modulo code period
		if(CODE61AB_CNTR_DIFF(CODE61AB_CNTR_DIFF'left) = '0') then
			-- positive
			CODE61AB_CNTR_DIFF_D <= CODE61AB_CNTR_DIFF;
		else
			-- negative. make it positive modulo code period
			CODE61AB_CNTR_DIFF_D <= CODE61AB_CNTR_DIFF + CODE_PERIOD_X(16 downto 0);
		end if;
		
		-- to avoid having a code code sync in the next (NACQ-1)/2 code phases, 
		-- CODE61AB_CNTR_DIFF_D MUST be >= NACQ/2
		
	end if;
end process;



--//-- CODE ACQUISITION --------------------
-- state machine
CODE_ACQ_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			-- reset state machine. Enter acquisition state.
			STATE_ACQ <= 0;
		elsif(STATE_ACQ = 0) and (NODETECT = '1') then
			-- no code detection for this batch of NACQ parallel detectors.
			-- Shift the code replica by NACQ/2 chips.
			STATE_ACQ <= 1;
		elsif(STATE_ACQ = 1) and (SAMPLE6_CLK_E = '1') and (SKIP_CNTR_A = 1) then 
			-- shifting code is complete. Start next acquisition.
			STATE_ACQ <= 0;
		elsif(STATE_ACQ = 0) and (DETECT = '1') then
			-- code detection
			STATE_ACQ <= 2;
			-- Shift the code replica by  EPOCH/2 chips
		elsif(STATE_ACQ = 2) and (SAMPLE6_CLK_E = '1') and (SKIP_CNTR_A < 2) then 
			-- shifting code is complete. Start code tracking.
			STATE_ACQ <= 3;
		elsif(STATE_ACQ = 3) and ((DETECT_FL = '1') or (DETECT_FL2 = '1')) then
			-- false lock or loss of lock. Re-enter acquisition
			STATE_ACQ <= 0;
		end if;
	end if;
end process;

CODE_LOCK <= '1' when (STATE_ACQ = 3) else '0';
CODE_LOCK_OUT <= CODE_LOCK;

--==================================================================
-- Reject the code detection if the first on-time power measurement after code acquisition
-- is below the detection threshold.
-- flag the first on-time bin power measurement immediately after code acquisition
FIRST_ACC_ONTIME_REF_GEN: process(CLK)
begin
	if rising_edge(CLK) then
		DETECT_D <= DETECT;

		if(SYNC_RESET = '1') or (STATE_ACQ = 0) then  -- new 10/2/14
			-- reset flag
			FIRST_ACC_ONTIME_REF_FLAG <= '0';
		elsif(DETECT_D = '1') then
			-- code detection
			FIRST_ACC_ONTIME_REF_FLAG <= '1';
		elsif (POWER_ACC_MAX_SAMPLE_CLK = '1') then
			-- first on-time power measurement after code acquisition
			FIRST_ACC_ONTIME_REF_FLAG <= '0';
		end if;
	end if;
end process;

-- false acquisition if the first on-time power measurement after code acquisition
-- is below the detection threshold. 
DETECT_FL2_GEN: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			DETECT_FL2 <= '0';
		elsif (POWER_ACC_MAX_SAMPLE_CLK = '1') and (FIRST_ACC_ONTIME_REF_FLAG = '1') and 
			(ext(POWER_ACC_ONTIME_REF,20) < DETECT_THRESHOLD) then
			DETECT_FL2 <= '1';
		else
			DETECT_FL2 <= '0';
		end if;
	end if;
end process;
--==================================================================


-- NACQ parallel detectors, spaced 1/2 chip apart
CODE_ACQ_002: process(CLK)
begin
	if rising_edge(CLK) then
		if(SAMPLE6_CLK_E = '1') then
			CODE62A(0) <= CODE62A_E;	-- 1/2 chip Q-code delay for SQPN
			CODE62B(0) <= CODE62B_E;	-- 1/2 chip Q-code delay for SQPN
			
			if(STATE_ACQ = 0) then
				-- during acquisition. Generate NACQ code replica spaced 1/2 chip apart
				CODE61A((NACQ-1) downto 1) <= CODE61A((NACQ-2) downto 0);	-- I-code
				CODE62A((NACQ-1) downto 1) <= CODE62A((NACQ-2) downto 0); 	-- Q-code (delayed 1/2 chip)
			else
				-- during code tracking, the first 3 code replica are 1/2 chip apart (early, center, late) for code tracking.
				CODE61A(2 downto 1)  <= CODE61A(1 downto 0);	-- I-code early/center/late
				CODE62A(2 downto 1)  <= CODE62A(1 downto 0);	-- Q-code early/center/late
				-- The other NACQ-3 codes are scanning for false lock
				CODE61B(2 downto 1)  <= CODE61B(1 downto 0);	-- keep the same time reference as CODE6
				CODE62B(2 downto 1)  <= CODE62B(1 downto 0);	-- keep the same time reference as CODE6
				
				if(CODE_PERIOD <= (NACQ/2)) then
					-- special case: short code period (would repeat in NACQ/2 processing bins)
					-- use fixed CODE61A for false lock detection instead of scanning CODE6B
					-- TODO: ignore the POWER_ACC values above index 2*CODE_PERIOD-1
					CODE61A(3) <= CODE61A(2);
					CODE62A(3) <= CODE62A(2);
				else
					-- code is longer than NACQ/2 processing bins. Scan for false lock.
					CODE61A(3) <= CODE61B(2);
					CODE62A(3) <= CODE62B(2);
				end if;
				CODE61A((NACQ-1) downto 4) <= CODE61A((NACQ-2) downto 3);
				CODE62A((NACQ-1) downto 4) <= CODE62A((NACQ-2) downto 3);
			end if;
		end if;
	end if;
end process;

-- define coherent integration and dump duration (75%)
-- I&D duration set to about 1/2 the spreading factor.
-- Reason #1: data modulation will stay unchanged for at least half of the I&D periods.
-- Reason #2: the center frequency error will not cause a significant phase shift in a given I&D period.
N_CID_GEN:  process(CLK)
begin
	if rising_edge(CLK) then
        N_CID <= SPREADING_FACTOR1 - ("00" & SPREADING_FACTOR1(12 downto 2));
    end if;
end process;

CODE_ACQ_003:  process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			COHERENT_ID_CNTR <= (others => '1');	
		elsif(SAMPLE6_CLK = '1') then
			if(COHERENT_ID_CNTR = N_CID) then
				COHERENT_ID_CNTR <= (others => '0');	
			else
				COHERENT_ID_CNTR <= COHERENT_ID_CNTR + 1;
			end if;
		end if;
	end if;
end process;

-- start of integration and dump
SOID <= '1' when (SAMPLE6_CLK = '1') and (COHERENT_ID_CNTR = 0) else '0';

-- The I&D truncation depends on the number of samples integrated.
-- Note: reduced truncation by two bits, seems to give a better dynamic range (less truncation at low SNR).
CODE_ACQ_004: process(SPREADING_FACTOR1)
begin	
	if(SPREADING_FACTOR1(12) = '1') then 
		TRUNCATE_OBITS <= 12;
	elsif(SPREADING_FACTOR1(11) = '1') then 
		TRUNCATE_OBITS <= 11;
	elsif(SPREADING_FACTOR1(10) = '1') then 
		TRUNCATE_OBITS <= 10;
	elsif(SPREADING_FACTOR1(9) = '1') then 
		TRUNCATE_OBITS <= 9;
	elsif(SPREADING_FACTOR1(8) = '1') then 
		TRUNCATE_OBITS <= 8;
	elsif(SPREADING_FACTOR1(7) = '1') then 
		TRUNCATE_OBITS <= 7;
	elsif(SPREADING_FACTOR1(6) = '1') then 
		TRUNCATE_OBITS <= 6;
	elsif(SPREADING_FACTOR1(5) = '1') then 
		TRUNCATE_OBITS <= 5;
	elsif(SPREADING_FACTOR1(4) = '1') then 
		TRUNCATE_OBITS <= 4;
	elsif(SPREADING_FACTOR1(3) = '1') then 
		TRUNCATE_OBITS <= 3;
	elsif(SPREADING_FACTOR1(2) = '1') then 
		TRUNCATE_OBITS <= 2;
	elsif(SPREADING_FACTOR1(1) = '1') then 
		TRUNCATE_OBITS <= 1;
	else
		TRUNCATE_OBITS <= 0;
	end if;
end process;

-- NACQ parallel despreading + coherent integration and dump
CODE_ACQ_005: for I in 0 to (NACQ-1) generate
	DESPREAD_ID_00x: DESPREAD_ID 
	GENERIC MAP(
		NBITS => 14
	)
	PORT MAP(
		CLK => CLK,
		SYNC_RESET => SYNC_RESET,
		DATA_I_IN => DATA6_I,
		DATA_Q_IN => DATA6_Q,
		SAMPLE_CLK_IN => SAMPLE6_CLK,	-- 2 samples per chip
		CODE_I => CODE61A(I),
		CODE_Q => CODE62A(I),
		SOID => SOID,
		TRUNCATE_OBITS => TRUNCATE_OBITS,
		BPSK0_SQPN1 => CONTROL(1),
		DATA_I_OUT => DATA7_I(I),
		DATA_Q_OUT => DATA7_Q(I),
		SAMPLE_CLK_OUT => SAMPLE7_CLK(I),
		SATURATION => SATURATION(I)
	);
end generate;

-- Stagger the I&D sampling clock to facilitate (i.e. time-share) the subsequent power computation
SAMPLE7_STAGGERED_CLK(0) <=  SAMPLE7_CLK(0);
CODE_ACQ_006:  process(CLK)
begin
	if rising_edge(CLK) then
		-- add a few (5) bins to use the same array after reclocking signals a few (5) times.
		SAMPLE7_STAGGERED_CLK((SAMPLE7_STAGGERED_CLK'left) downto 1) <= SAMPLE7_STAGGERED_CLK((SAMPLE7_STAGGERED_CLK'left -1) downto 0); 
	end if;
end process;

-- additional integration and dump to further improve the detector SNR, non-coherent this time
-- mux
-- A,B are aligned with SAMPLE7_STAGGERED_CLK(I+1), for I = 0 to NACQ-1
POWER_001: process (CLK)
begin
	if rising_edge(CLK) then
		for I in 0 to (NACQ-1) loop
			if(SAMPLE7_STAGGERED_CLK(I) = '1') then
				A <= DATA7_I(I) & "0000";
				B <= DATA7_Q(I) & "0000";
			end if;
		end loop;
	end if;
end process;

-- pipelining
-- A_D,B_D are aligned with SAMPLE7_STAGGERED_CLK(I+2), for I = 0 to NACQ-1
POWER_002: process (CLK)
begin
	if rising_edge(CLK) then
		A_D <= A;
		B_D <= B;
	end if;
end process;

POWER_003: MULT18X18SIGNED port map (
	A => A_D,
	B => A_D,
	P => A_SQUARE
);

POWER_004: MULT18X18SIGNED port map (
	A => B_D,
	B => B_D,
	P => B_SQUARE
);

-- A_SQUARE_D,B_SQUARE_D are aligned with SAMPLE7_STAGGERED_CLK(I+3), for I = 0 to NACQ-1
POWER_005: process(CLK) 
begin
	if rising_edge(CLK) then
		A_SQUARE_D <= A_SQUARE(34 downto 21);	-- no need to use LSBs. 14-bit precision is enough
		B_SQUARE_D <= B_SQUARE(34 downto 21);
	end if;
end process;
AB_SQUARE_D <= A_SQUARE_D + B_SQUARE_D;

-- define non-coherent integration and dump duration
NCID_001:  process(CLK)
begin
	if rising_edge(CLK) then
		NONCOHERENT_ID_CNTR_D <= NONCOHERENT_ID_CNTR;
		NONCOHERENT_ID_CNTR_D2 <= NONCOHERENT_ID_CNTR_D;
		NONCOHERENT_ID_CNTR_D3 <= NONCOHERENT_ID_CNTR_D2;

		if(SAMPLE7_STAGGERED_CLK(NACQ+2) = '1') then	-- accumulating the last power sample. Rewind NC I&D counter
			if(NONCOHERENT_ID_CNTR = N_NCID) then
				NONCOHERENT_ID_CNTR <= (others => '0');
			else
				NONCOHERENT_ID_CNTR <= NONCOHERENT_ID_CNTR + 1;
			end if;
		end if;
	end if;
end process;

-- non-coherent (power) integrate and dump. NACQ parallel computations.
-- POWER_ACC_X is aligned with SAMPLE7_STAGGERED_CLK(I+4), for I = 0 to NACQ-1
NCID_00x: for I in 3 to (NACQ+2) generate
	NCID_002: process(CLK) 
	begin
		if rising_edge(CLK) then
			if(SAMPLE7_STAGGERED_CLK(I) = '1') and ((SIMULATION = '0') or (AB_SQUARE_D(0) /= 'X')) then	-- prevent propagation of undefined during simulation
				if(NONCOHERENT_ID_CNTR = 0) then
					-- reset accumulated values
					POWER_ACC_X(I-3) <=  ext(AB_SQUARE_D, N_NCID_LOG2+14);
				else
					-- accumulate power measurements
					-- extend precision by N_NCID_LOG2 bits to avoid any overflow.
					POWER_ACC_X(I-3) <=  POWER_ACC_X(I-3) + ext(AB_SQUARE_D, N_NCID_LOG2+14);
				end if;
			end if;
		end if;
	end process;
end generate;


-- drop (N_NCID_LOG2 LSBs-4) + multiplex the power measurements into POWER_ACC
-- POWER_ACC_E values are valid for NACQ consecutive clocks when SAMPLE7_STAGGERED_CLK((NACQ+4) downto 5) /= 0)
NCID_003: process(CLK) 
begin
	if rising_edge(CLK) then
		if(NONCOHERENT_ID_CNTR_D = N_NCID) then
			for I in 4 to (NACQ+3) loop
				if(SAMPLE7_STAGGERED_CLK(I) = '1') then
					-- multiplexing
					POWER_ACC_E <= POWER_ACC_X(I-4)((N_NCID_LOG2+13) downto (N_NCID_LOG2-4));
				end if;
			end loop;
		end if;
	end if;
end process;

NCID_004: process(CLK) 
begin
	if rising_edge(CLK) then
		if(NONCOHERENT_ID_CNTR_D = N_NCID) and (SAMPLE7_STAGGERED_CLK((NACQ+3) downto 4) /= 0) then
			POWER_ACC_SAMPLE_CLK_E <= '1';	-- when SAMPLE7_STAGGERED_CLK((NACQ+4) downto 5) /= 0)
		else
			POWER_ACC_SAMPLE_CLK_E <= '0';
		end if;
	end if;
end process;

-- pipelining
NCID_005: process(CLK) 
begin
	if rising_edge(CLK) then
		POWER_ACC_SAMPLE_CLK <= POWER_ACC_SAMPLE_CLK_E;	-- when SAMPLE7_STAGGERED_CLK((NACQ+5) downto 6) /= 0)
		POWER_ACC <= POWER_ACC_E;
		-- keep track of the bin number
		if(POWER_ACC_SAMPLE_CLK_E = '0') then
			POWER_ACC_SAMPLE_CNTR <= (others => '0');
		else
			POWER_ACC_SAMPLE_CNTR <= POWER_ACC_SAMPLE_CNTR + 1;
		end if;
	end if;
end process;



-- Non-coherent integration complete. 
-- Dump and compare accumulated POWER_ACC
POWER_ACC_MAX_001: process(CLK)
begin
	if rising_edge(CLK) then
		POWER_ACC_SAMPLE_CLK_D <= POWER_ACC_SAMPLE_CLK;
		
		if(POWER_ACC_SAMPLE_CLK = '1') then
			if(POWER_ACC_SAMPLE_CLK_D = '0') then
				-- first of NACQ power measurements
				POWER_ACC_MAX <= POWER_ACC;
				IMAX <= 0;
				IMAX_PTR <= 1;
			elsif(POWER_ACC > POWER_ACC_MAX) then
				-- new max
				POWER_ACC_MAX <= POWER_ACC;
				IMAX <= IMAX_PTR;
				IMAX_PTR <= IMAX_PTR + 1;
			else
				-- not a max
				IMAX_PTR <= IMAX_PTR + 1;
			end if;
		end if;

		if(POWER_ACC_SAMPLE_CLK = '1') and (POWER_ACC_SAMPLE_CLK_E = '0') then
			-- max search complete
			POWER_ACC_MAX_SAMPLE_CLK <= '1';
		else
			POWER_ACC_MAX_SAMPLE_CLK <= '0';
		end if;
	end if;
end process;

-- Detection threshold is relative to the noise level.
-- The noise level is computed by averaging POWER_ACC(I)
-- New 7/8/13 skip the first 3 samples (on-time +/- 1/2 chip) which can be significantly larger and skew this noise level measurement
-- New 4/1/14 stop averaging power before the next periodic correlation peak when code period is short
CODE_PERIODx2 <= CODE_PERIOD(14 downto 0) & "0";
AVERAGE_NOISE_001: process(CLK)
begin
	if rising_edge(CLK) then
		POWER_AVERAGE_D <= POWER_AVERAGE;
		POWER_ACC_SAMPLE_CLK_D2 <= POWER_ACC_SAMPLE_CLK_D;
		POWER_ACC_SAMPLE_CLK_D3 <= POWER_ACC_SAMPLE_CLK_D2;

        if(SYNC_RESET = '1') then
            -- new 9/19/14
            POWER_AVERAGE_X <= (others => '0');
        elsif(POWER_AVERAGE_X = 0) and (POWER_ACC_SAMPLE_CLK = '1') then
            -- initialize power average at the first valid POWER_ACC_SAMPLE_CLK
 			POWER_AVERAGE_X <= "0" & POWER_ACC & "00000";	
		elsif(POWER_ACC_SAMPLE_CLK = '1') and (POWER_ACC_SAMPLE_CNTR > 3) and (POWER_ACC_SAMPLE_CNTR <= CODE_PERIODx2) then
			-- leaky integrator. No need for reset. skip first 3 power measurements (on-time +/- 1/2 chip) 
			-- and stop prior to the next peak or NACQ whichever comes first
			POWER_AVERAGE_X <= POWER_AVERAGE_X + ext(POWER_ACC,POWER_AVERAGE_X'length) - ext(POWER_AVERAGE,POWER_AVERAGE_X'length);	
		end if;
	end if;
end process;
POWER_AVERAGE <= POWER_AVERAGE_X(POWER_AVERAGE_X'left downto 6);	-- running average over 64 samples

-- detection or no detection decision
-- Detect at the end of the non-coherent integration period if max power > 1.5*average power
DETECT_001: process(CLK)
begin
	if rising_edge(CLK) then
		-- threshold
		DETECT_THRESHOLD <= ("00" & POWER_AVERAGE_D) + ("000" & POWER_AVERAGE_D(17 downto 1));	-- x1.5
		
		if(POWER_ACC_MAX_SAMPLE_CLK = '1') and (STATE_ACQ = 0) then
			-- during acquisition mode only, compare with threshold.
			if(ext(POWER_ACC_MAX,20) > DETECT_THRESHOLD) then
				DETECT <= '1';
				NODETECT <= '0';
				EPOCH <= IMAX;
			else
				DETECT <= '0';
				NODETECT <= '1';
			end if;
		else
			DETECT <= '0';
			NODETECT <= '0';
		end if;
	end if;
end process;

-- new 4/9/13
--//-- SNR (when code lock is achieved) -------------------------------------
-- This method is not accurate, but it has the advantage of avoiding dependencies on carrier tracking/symbol tracking/etc.
-- A more accurate measurement is also computed further down this component.
-- noise power is approximately POWER_AVERAGE_D(17:0)
-- signal power is approximately POWER_ACC_ONTIME_REF(17:0) (when in lock)
-- (on second thought, it is more likely S+N, not just S)
SNR_DENOM <= ext(POWER_AVERAGE_D(17 downto 2),18);
SNR_003: DIVIDER 
GENERIC MAP(
	NBITS => 18
)
PORT MAP (
		 CLK => CLK,
		 NUM => POWER_ACC_ONTIME_REF,
		 DENOM => SNR_DENOM,
		 SAMPLE_CLK_IN => POWER_ACC_ONTIME_REF_SAMPLE_CLK,	-- when POWER_ACC_ONTIME_REF is ready
		 QUOTIENT => SNR_LOCKED,	-- format 16.2
		 REMAINDER => open,
		 SAMPLE_CLK_OUT => SNR_LOCKED_SAMPLE_CLK
	  );

-- actual measurements (BPSK)
-- Eb/No (dB)	SNR_LOCKED (format 16.2)
-- > 30 dB		296
-- 14.5			120
-- 8.5			60
-- 5				36
--	2.9			28
-- 1.9			22.4

--//-- FALSE LOCK DETECTION --------------------
-- False lock or loss of lock is characterized by a power measurement at a code offset much greater (x3) than
-- the on-time power measurement.

-- Non-coherent integration complete. 
-- Dump and compare accumulated POWER_ACC(I). Skip first 3 bins (0/1/2) which are used for code tracking.
-- POWER_ACC(I) value is aligned with SAMPLE7_STAGGERED_CLK(I+4), for I = 0 to NACQ-1
FALSE_LOCK_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(NONCOHERENT_ID_CNTR_D3 = N_NCID) and (STATE_ACQ = 3) then
			if(SAMPLE7_STAGGERED_CLK(8) = '1') then
				-- Initialize false lock power measurement
				POWER_ACC_MAX_FL <= (others => '0');
				POWER_FL_BIN <= 0;
			elsif(SAMPLE7_STAGGERED_CLK((NACQ+5) downto 9) /= 0) then
				-- maximum power measurement for code epochs other than the one being tracked.
				POWER_FL_BIN <= POWER_FL_BIN + 1;
				if (POWER_ACC > POWER_ACC_MAX_FL) then
					-- new max
					POWER_ACC_MAX_FL <= POWER_ACC;	
					IMAX_FL <= POWER_FL_BIN;
				end if;
			end if;
		end if;
	end if;
end process;
POWER_ACC_MAX_FL_SAMPLE_CLK <= POWER_ACC_MAX_SAMPLE_CLK when (STATE_ACQ = 3) else '0';

-- on-time power measurement. Serves as reference for false lock detection.
-- Note: because of the 1/2 chip uncertainty after acquisition + jitter, the power measurement is the max
-- of early/on-time/late power measurements (no need to be too strict).
ON_TIME_POWER_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(NONCOHERENT_ID_CNTR_D3 = N_NCID) and (SAMPLE7_STAGGERED_CLK(9) = '1') and (STATE_ACQ = 3) then
            -- on-time power measurement (max of early,center,late power measurements)
            -- save on-time power measurement for comparison purpose
            POWER_ACC_ONTIME_REF <= POWER_ACC_MAX;	-- max of bins 0,1,2 = early,on-time,late
            POWER_ACC_ONTIME_REF_SAMPLE_CLK <= '1';	-- POWER_ACC_ONTIME_REF is ready
		elsif(DETECT = '1') then
			-- don't wait. Compute SNR immediately upon the first DETECT
			-- otherwise code tracking loop may be directed to increase its gain and become unstable
			POWER_ACC_ONTIME_REF <= POWER_ACC_MAX;	
			POWER_ACC_ONTIME_REF_SAMPLE_CLK <= '1';	
		else
			POWER_ACC_ONTIME_REF_SAMPLE_CLK <= '0';		
		end if;
	end if;
end process;

-- false lock detection or loss of lock detection
-- Detect at the end of the non-coherent integration period if max power > x*ontime power
FALSE_LOCK_002: process(CLK)
begin
	if rising_edge(CLK) then
		-- threshold (adaptative vs SNR)
		if(SNR_LOCKED_SAMPLE_CLK = '1') then
			if(SNR_LOCKED > 80) then
				--  SNR > 10 dB
				DETECT_THRESHOLD_FL <= ("0" & POWER_ACC_ONTIME_REF & "0") + ("00" & POWER_ACC_ONTIME_REF(17 downto 0));	-- x3
			else
				--  SNR <= 10 dB
   				DETECT_THRESHOLD_FL <= ("0" & POWER_ACC_ONTIME_REF & "0") - ("000" & POWER_ACC_ONTIME_REF(17 downto 1));	-- x1.5  (optimized for C/No = 36 dB.Hz, 4/13/15)
			end if;
		end if;
		
		if(POWER_ACC_MAX_FL_SAMPLE_CLK = '1') and (STATE_ACQ = 3) then
			-- during tracking mode only, compare with threshold.
			if(ext(POWER_ACC_MAX_FL,20) > DETECT_THRESHOLD_FL) then
				DETECT_FL <= '1';
				NODETECT_FL <= '0';
				EPOCH_FL <= IMAX_FL;
			else
				DETECT_FL <= '0';
				NODETECT_FL <= '1';
			end if;
		else
			DETECT_FL <= '0';
			NODETECT_FL <= '0';
		end if;
	end if;
end process;


--//-- DESPREADING --------------------
-- After acquisition and during tracking the early/center/late codes are CODE61A(0/1/2) respectively.
-- despread with center/on-time code 
DESPREAD_001: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE8_CLK <= SAMPLE6_CLK;
		
		-- I-code despreading
		if(SAMPLE6_CLK = '1') then 	-- 2 samples per chip
			-- on-time despreading code 
			if(CODE61A(1)  = '1') then
				DATA81_I <= DATA6_I;
				DATA81_Q <= DATA6_Q;
			else
				-- Note: using not instead of the more rigorous not+1 is simpler, keeps symmetry and alleviates the need to check for overflow
				DATA81_I <= not DATA6_I;
				DATA81_Q <= not DATA6_Q;
			end if;
			
		-- Q-code despreading (SQPN, 1/2 chip Q-code delay already built into CODE62A)
		    if(CONTROL(1) = '1') then
		        -- SQPN
                if(CODE62A(1)  = '1') then
                    DATA82_I <= DATA6_I;
                    DATA82_Q <= DATA6_Q;
                else
                    -- Note: using not instead of the more rigorous not+1 is simpler, keeps symmetry and alleviates the need to check for overflow
                    DATA82_I <= not DATA6_I;
                    DATA82_Q <= not DATA6_Q;
                end if;
            end if;
		end if;
	end if;
end process; 

-- despread output for monitoring purposes (unfiltered, 2 samples per chip)
-- There is also a filtered version below. Comment in/out depending on usage.
DESPREAD_002: process(CLK)
begin
	if rising_edge(CLK) then
		DESPREAD1_SAMPLE_CLK <= SAMPLE8_CLK;

		if(SAMPLE8_CLK = '1') then		
			DESPREAD1_I_OUT <= DATA81_I;
			DESPREAD1_Q_OUT <= DATA82_Q;
		end if;
	end if;
end process;


--//-- CODE TRACKING --------------------
-- After acquisition and during tracking the early/center/late codes are CODE61A(0/1/2) respectively.

-- power of coherent I&D after despreading with early/late code replicas.
-- Note: we did not use the power average POWER_ACC because the inherent delay in the power I&D process would limit the 
-- ability to track codes with strong clock drifts. Instead, we take the raw (coherent I&D)^2 and compare the 
-- early/late values with a very small loop gain in the tracking loop (in effect averaging).
CODE_TRACKING_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SAMPLE7_STAGGERED_CLK(3) = '1') and ((SIMULATION = '0') or (AB_SQUARE_D(0) /= 'X')) then	-- prevent propagation of undefined during simulation
			-- First item = power after early code despreading
			POWER_ID_EARLY <=  AB_SQUARE_D;
		end if;
		if(SAMPLE7_STAGGERED_CLK(5) = '1') and ((SIMULATION = '0') or (AB_SQUARE_D(0) /= 'X')) then	-- prevent propagation of undefined during simulation
				-- 3rd item = power after late code despreading
			POWER_ID_LATE <=  AB_SQUARE_D;
			POWER_ID_SAMPLE_CLK <= '1';
		else
			POWER_ID_SAMPLE_CLK <= '0';
		end if;
	end if;
end process; 


-- Input: early / late samples
-- Freeze code tracking loop during initial acquisition
FREEZE_CODE_TRACKING <= '1' when (STATE_ACQ /= 3) else '0';

-- Adaptive loop gain (depends on SNR)
CODE_TRACKING_002: process(CLK)
begin
	if rising_edge(CLK) then
		-- threshold (adaptative vs SNR)
		-- justification: the lower the SNR, the lower the correlation peak. 
		-- Instead of another AGC to normalize the code tracking error, we use this approximative normalization
		-- based on the measured SNR
		if(SYNC_RESET = '1') then
			-- reset to prevent unrecoverable instability (oscillating code lock/unlock)
			-- set the minimum loop gain
			CODE_TRACKING2_LOOP_GAIN <= "00";
		elsif(SNR_LOCKED_SAMPLE_CLK = '1') then
			-- new: change order to account for Undefined during simulation. 3/25/14
			if(SNR_LOCKED <= 36) then
				--  SNR <= 5 dB
				CODE_TRACKING2_LOOP_GAIN <= "11";
			elsif(SNR_LOCKED <= 60) then
				--  SNR <= 8.5 dB
				CODE_TRACKING2_LOOP_GAIN <= "10";
			elsif(SNR_LOCKED <= 120) then
				--  SNR <= 14.5 dB
				CODE_TRACKING2_LOOP_GAIN <= "01";
			else
				--  SNR > 14.5 dB or 'U'ndefined. Use minimum loop gain to prevent instabilities
				CODE_TRACKING2_LOOP_GAIN <= "00";
			end if;
		end if;
	end if;
end process; 
	
CODE_TRACKING_003: CODE_TRACKING2 PORT MAP(
	CLK => CLK,
	SYNC_RESET => SYNC_RESET,
	DATA_EARLY => POWER_ID_EARLY,
	DATA_LATE => POWER_ID_LATE,
	SAMPLE_CLK => POWER_ID_SAMPLE_CLK,
	FREEZE_CODE_TRACKING => FREEZE_CODE_TRACKING,
	LOOP_GAIN => CODE_TRACKING2_LOOP_GAIN,
	NCO_TIMING_CONTROL => NCO_TIMING_CONTROL,
	NCO_TIMING_CONTROL_CLK => NCO_TIMING_CONTROL_CLK,
	CS1 => CS8,	-- Comscope: accumulated code tracking phase correction
	CS1_CLK => CS8_CLK
);

--//-- SYMBOL CLOCKS GENERATION ------------------------
-- generate 2*symbol rate
-- Different symbol rates for I and Q channels
NOMINAL_SYMBOL_RATE1x2 <= NOMINAL_SYMBOL_RATE1(30 downto 0) & "0";
NOMINAL_SYMBOL_RATE2x2 <= NOMINAL_SYMBOL_RATE2(30 downto 0) & "0";
	-- NCO output frequency is 2*symbol rate
ST_NCO_TIMING_CONTROL1_DIV <= sxt(ST_NCO_TIMING_CONTROL1(31 downto 3),32);	
ST_NCO_TIMING_CONTROL2_DIV <= sxt(ST_NCO_TIMING_CONTROL2(31 downto 3),32);	
	-- divide correction factor by 8 (previously by 4 when generating 4*symbol rate)
	-- previous comment "divide correction factor by 4 because we apply it 4x per symbol" was WRONG as
	-- the correction is applied ST_NCO_TIMING_CONTROL1_CLK only once per symbol
ST_NCO32_001: NCO32X 
GENERIC MAP(
	SIMULATION => SIMULATION
)
PORT MAP(
	CLK => CLK,
	SYNC_RESET => SYNC_RESET,
	NOMINAL_FREQUENCY => NOMINAL_SYMBOL_RATE1x2,
	PHASE_OFFSET => ST_NCO_TIMING_CONTROL1_DIV,
	PHASE_OFFSET_SAMPLE_CLK => ST_NCO_TIMING_CONTROL1_CLK,
	PHASE => open,
	SAMPLE_CLK_OUT => SYMBOL81_CLKx2
);

-- 2nd independent symbol tracking (when enabled)
ST2_RESET <= SYNC_RESET or CONTROL(2);
ST_NCO32_002: NCO32X 
GENERIC MAP(
	SIMULATION => SIMULATION
)
PORT MAP(
	CLK => CLK,
	SYNC_RESET => ST2_RESET,
	NOMINAL_FREQUENCY => NOMINAL_SYMBOL_RATE2x2,
	PHASE_OFFSET => ST_NCO_TIMING_CONTROL2_DIV,
	PHASE_OFFSET_SAMPLE_CLK => ST_NCO_TIMING_CONTROL2_CLK,
	PHASE => open,
	SAMPLE_CLK_OUT => SYMBOL82A_CLKx2	
);

-- independent symbol rates on I/Q? yes if SQPN and double source and not alternating I/Q
SYMBOL82_CLKx2 <= SYMBOL82A_CLKx2 when (CONTROL(2 downto 1) = "01") and (CONTROL(7) = '0') else SYMBOL81_CLKx2;
SYMBOL82_CLK <= SYMBOL82A_CLK when (CONTROL(2 downto 1) = "01") and (CONTROL(7) = '0') else SYMBOL81_NODELAY;

-- when tracking..
-- SYMBOL81_CLK='1' is at the symbol boundary
-- SYMBOL81_CLK='0' and SYMBOL81_CLKx2='1' mark the symbol center
SYMBOL_CLKGEN_81: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYMBOL81_CLKx2 = '1') then
			SYMBOL81_CLK_CNTR <= SYMBOL81_CLK_CNTR + 1;
		end if;
	end if;
end process; 
-- delay I channel by half a symbol whenever the Q channel was delayed by half a symbol at the modulator?
SYMBOL81_NODELAY <= 	SYMBOL81_CLKx2 when (SYMBOL81_CLK_CNTR(0 downto 0) = "0") else '0';	-- never delayed
SYMBOL81_HALFSYMBOLDELAY <= SYMBOL81_CLKx2 when (SYMBOL81_CLK_CNTR(0 downto 0) = "1") else '0';	-- 1/2 I symbol delay
SYMBOL81_CLK <= SYMBOL81_NODELAY when (CONTROL(6) = '0') else SYMBOL81_HALFSYMBOLDELAY;


SYMBOL_CLKGEN_82: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYMBOL82A_CLKx2 = '1') then
			SYMBOL82A_CLK_CNTR <= SYMBOL82A_CLK_CNTR + 1;
		end if;
	end if;
end process; 
SYMBOL82A_CLK <= SYMBOL82A_CLKx2 when (SYMBOL82A_CLK_CNTR(0 downto 0) = "0") else '0';

--//-- FINAL NOISE REJECTION: INTEGRATE & DUMP, I-channel --------------------------------------
-- Integrate and dump for one symbol around the presumed symbol center
ID_010: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			DATA101_I_ACC <= (others => '0');
			DATA101_Q_ACC <= (others => '0');
		elsif(SYMBOL81_CLK = '1') then
			-- start a new I&D
			-- two cases: aligned with SAMPLE8_CLK or not
			if(SAMPLE8_CLK = '1') then
				-- reset integrator, add first sample
				DATA101_I_ACC <= sxt(DATA81_I,26);	-- 14-bit samples + 2*2047 max spreading factor	
				DATA101_Q_ACC <= sxt(DATA81_Q,26);	-- 14-bit samples + 2*2047 max spreading factor	
			else
				-- reset integrator
				DATA101_I_ACC <= (others => '0');
				DATA101_Q_ACC <= (others => '0');
			end if;
	  	elsif(SAMPLE8_CLK = '1') then
			DATA101_I_ACC <= DATA101_I_ACC + sxt(DATA81_I,26);
			DATA101_Q_ACC <= DATA101_Q_ACC + sxt(DATA81_Q,26);
	  	end if;
	end if;
end process;

ID_011: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			DATA101_I_ID <= (others => '0');
			DATA101_Q_ID <= (others => '0');
			SAMPLE101_ID_CLK <= '0';
		elsif(SYMBOL81_CLK = '1') then
			-- start a new I&D
			-- Save previous integrated value
			DATA101_I_ID <= DATA101_I_ACC;
			DATA101_Q_ID <= DATA101_Q_ACC;
			SAMPLE101_ID_CLK <= '1';
		else
			SAMPLE101_ID_CLK <= '0';
	  	end if;
	end if;
end process;

-- Integrate and dump for one symbol (1/2 symbol off)
ID_012: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			DATA111_I_ACC <= (others => '0');
			DATA111_Q_ACC <= (others => '0');
		elsif(SYMBOL81_CLKx2 = '1') and (SYMBOL81_CLK = '0') then
			-- start a new I&D in the middle of the symbol
			-- two cases: aligned with SAMPLE8_CLK or not
			if(SAMPLE8_CLK = '1') then
				-- reset integrator, add first sample
				DATA111_I_ACC <= sxt(DATA81_I,26);	-- 14-bit samples + 2*2047 max spreading factor	
				DATA111_Q_ACC <= sxt(DATA81_Q,26);	-- 14-bit samples + 2*2047 max spreading factor	
			else
				-- reset integrator
				DATA111_I_ACC <= (others => '0');
				DATA111_Q_ACC <= (others => '0');
			end if;
	  	elsif(SAMPLE8_CLK = '1') then
			DATA111_I_ACC <= DATA111_I_ACC + sxt(DATA81_I,26);
			DATA111_Q_ACC <= DATA111_Q_ACC + sxt(DATA81_Q,26);
	  	end if;
	end if;
end process;

ID_013: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			DATA111_I_ID <= (others => '0');
			DATA111_Q_ID <= (others => '0');
			SAMPLE111_ID_CLK <= '0';
		elsif(SYMBOL81_CLKx2 = '1') and (SYMBOL81_CLK = '0') then
			-- start a new I&D in the middle of the symbol
			-- Save previous integrated value
			DATA111_I_ID <= DATA111_I_ACC;
			DATA111_Q_ID <= DATA111_Q_ACC;
			SAMPLE111_ID_CLK <= '1';
		else
			SAMPLE111_ID_CLK <= '0';
	  	end if;
	end if;
end process;

--//-- FINAL NOISE REJECTION: INTEGRATE & DUMP, Q-channel --------------------------------------
-- Integrate and dump for one symbol around the presumed symbol center
ID_010Q: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') or (CONTROL(1) = '0') then
			-- reset when BPSK 
			DATA102_I_ACC <= (others => '0');
			DATA102_Q_ACC <= (others => '0');
		elsif(SYMBOL82_CLK = '1') then
			-- start a new I&D
			-- two cases: aligned with SAMPLE8_CLK or not
			if(SAMPLE8_CLK = '1') then
				-- reset integrator, add first sample
				DATA102_I_ACC <= sxt(DATA82_I,26);	-- 14-bit samples + 2*2047 max spreading factor	
				DATA102_Q_ACC <= sxt(DATA82_Q,26);	-- 14-bit samples + 2*2047 max spreading factor	
			else
				-- reset integrator
				DATA102_I_ACC <= (others => '0');
				DATA102_Q_ACC <= (others => '0');
			end if;
	  	elsif(SAMPLE8_CLK = '1') then
			DATA102_I_ACC <= DATA102_I_ACC + sxt(DATA82_I,26);
			DATA102_Q_ACC <= DATA102_Q_ACC + sxt(DATA82_Q,26);
	  	end if;
	end if;
end process;

ID_011Q: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') or (CONTROL(1) = '0') then
			-- reset when BPSK 
			DATA102_I_ID <= (others => '0');
			DATA102_Q_ID <= (others => '0');
			SAMPLE102_ID_CLK <= '0';
		elsif(SYMBOL82_CLK = '1') then
			-- start a new I&D
			-- Save previous integrated value
			DATA102_I_ID <= DATA102_I_ACC;
			DATA102_Q_ID <= DATA102_Q_ACC;
			SAMPLE102_ID_CLK <= '1';
		else
			SAMPLE102_ID_CLK <= '0';
	  	end if;
	end if;
end process;

-- Integrate and dump for one symbol (1/2 symbol off)
ID_012Q: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') or (CONTROL(1) = '0') then
			-- reset when BPSK 
			DATA112_I_ACC <= (others => '0');
			DATA112_Q_ACC <= (others => '0');
		elsif(SYMBOL82_CLKx2 = '1') and (SYMBOL82_CLK = '0') then
			-- start a new I&D in the middle of the symbol
			-- two cases: aligned with SAMPLE8_CLK or not
			if(SAMPLE8_CLK = '1') then
				-- reset integrator, add first sample
				DATA112_I_ACC <= sxt(DATA82_I,26);	-- 14-bit samples + 2*2047 max spreading factor	
				DATA112_Q_ACC <= sxt(DATA82_Q,26);	-- 14-bit samples + 2*2047 max spreading factor	
			else
				-- reset integrator
				DATA112_I_ACC <= (others => '0');
				DATA112_Q_ACC <= (others => '0');
			end if;
	  	elsif(SAMPLE8_CLK = '1') then
			DATA112_I_ACC <= DATA112_I_ACC + sxt(DATA82_I,26);
			DATA112_Q_ACC <= DATA112_Q_ACC + sxt(DATA82_Q,26);
	  	end if;
	end if;
end process;

ID_013Q: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') or (CONTROL(1) = '0') then
			-- reset when BPSK 
			DATA112_I_ID <= (others => '0');
			DATA112_Q_ID <= (others => '0');
			SAMPLE112_ID_CLK <= '0';
		elsif(SYMBOL82_CLKx2 = '1') and (SYMBOL82_CLK = '0') then
			-- start a new I&D in the middle of the symbol
			-- Save previous integrated value
			DATA112_I_ID <= DATA112_I_ACC;
			DATA112_Q_ID <= DATA112_Q_ACC;
			SAMPLE112_ID_CLK <= '1';
		else
			SAMPLE112_ID_CLK <= '0';
	  	end if;
	end if;
end process;

--//-- NORMALIZE I&D outputs I-channel ---------------------
-- During the integration and dump process, 2*SPREADING_FACTOR samples
-- were accumulated. To normalize the output, do a coarse gain adjustment based on the 2*spreading factor
-- followed by an AGC (as the despread signal so far is function of the spreading factor (known) and
-- of the SNR (unknown).

-- (a) coarse scaling. Function of the spreading factor only.
-- Create a pulse of length 1 to 11 clocks, depending on 2*spreading factor
-- 2 or less -> 1
-- 4-3 -> 2
-- etc... General rule: N CLKs for SPREADING_FACTOR = 2^N
-- Start at SAMPLE101_ID_CLK
COARSE_GAIN_ADJUST_101A: process(CLK)
begin
	if rising_edge(CLK) then
		if(SAMPLE101_ID_CLK = '1') then
			SHIFT101 <= SPREADING_FACTOR1;
	  	elsif(SHIFT101 /= 0) then
			-- as long as SHIFT101 is not zero, keep shifting
			SHIFT101 <= "0" & SHIFT101(SHIFT101'left downto 1);
			COUNT_ENABLE101 <= '1';	-- start count enable pulse
		else
			-- SHIFT101 = 0. stop.
			COUNT_ENABLE101 <= '0';	-- stop count enable pulse
		end if;
	end if;
end process;
COARSE_GAIN_ADJUST_111A: process(CLK)
begin
	if rising_edge(CLK) then
		if(SAMPLE111_ID_CLK = '1') then
			SHIFT111 <= SPREADING_FACTOR1;
	  	elsif(SHIFT111 /= 0) then
			-- as long as SHIFT111 is not zero, keep shifting
			SHIFT111 <= "0" & SHIFT111(SHIFT111'left downto 1);
			COUNT_ENABLE111 <= '1';	-- start count enable pulse
		else
			-- SHIFT111 = 0. stop.
			COUNT_ENABLE111 <= '0';	-- stop count enable pulse
		end if;
	end if;
end process;


COARSE_GAIN_ADJUST_101B: process(CLK)
begin
	if rising_edge(CLK) then
		COUNT_ENABLE101_D <= COUNT_ENABLE101;

		if(SAMPLE101_ID_CLK = '1') then
			-- let the input in
			DATA101_I_SHIFT <= DATA101_I_ID;
			DATA101_Q_SHIFT <= DATA101_Q_ID;
	  	elsif(COUNT_ENABLE101 = '1') then
			-- divide by 2, keep MSB unchanged (sign extension)
			DATA101_I_SHIFT(24 downto 0) <= DATA101_I_SHIFT(25 downto 1);
			DATA101_Q_SHIFT(24 downto 0) <= DATA101_Q_SHIFT(25 downto 1);
	  	end if;
  	end if;
end process;
COARSE_GAIN_ADJUST_111B: process(CLK)
begin
	if rising_edge(CLK) then
		COUNT_ENABLE111_D <= COUNT_ENABLE111;

		if(SAMPLE111_ID_CLK = '1') then
			-- let the input in
			DATA111_I_SHIFT <= DATA111_I_ID;
			DATA111_Q_SHIFT <= DATA111_Q_ID;
	  	elsif(COUNT_ENABLE111 = '1') then
			-- divide by 2, keep MSB unchanged (sign extension)
			DATA111_I_SHIFT(24 downto 0) <= DATA111_I_SHIFT(25 downto 1);
			DATA111_Q_SHIFT(24 downto 0) <= DATA111_Q_SHIFT(25 downto 1);
	  	end if;
  	end if;
end process;

-- mux samples at symbol center and 1/2 symbol off center 
-- DATA13 is sampled at 2x symbol rate
COARSE_GAIN_ADJUST_003: process(CLK)
begin
	if rising_edge(CLK) then
		if(COUNT_ENABLE101_D = '1') and (COUNT_ENABLE101 = '0') then
			-- shift is complete
			-- output shifted result. Keep only 14 LSBs.
			-- Guaranteed overflow-free.
			if(CONTROL(6) = '0') then
				-- no delay
				DATA131_I <= DATA101_I_SHIFT(14 downto 1);
				DATA131_Q <= DATA101_Q_SHIFT(14 downto 1);
				SAMPLE131_CLK <= '1';	
				SYMBOL131_CLK <= '1';
			else
				-- 1/2 symbol delay
				DATA131_I_E <= DATA101_I_SHIFT(14 downto 1);
				DATA131_Q_E <= DATA101_Q_SHIFT(14 downto 1);
				DATA131_I <= DATA131_I_E;
				DATA131_Q <= DATA131_Q_E;
				SAMPLE131_CLK <= '1';	
				SYMBOL131_CLK <= '0';
			end if;
		elsif(COUNT_ENABLE111_D = '1') and (COUNT_ENABLE111 = '0') then
			-- shift is complete
			-- output shifted result. Keep only 14 LSBs.
			-- Guaranteed overflow-free.
			if(CONTROL(6) = '0') then
				-- no delay
				DATA131_I <= DATA111_I_SHIFT(14 downto 1);
				DATA131_Q <= DATA111_Q_SHIFT(14 downto 1);
				SAMPLE131_CLK <= '1';
				SYMBOL131_CLK <= '0';
			else
				-- 1/2 symbol delay
				DATA131_I_E <= DATA111_I_SHIFT(14 downto 1);
				DATA131_Q_E <= DATA111_Q_SHIFT(14 downto 1);
				DATA131_I <= DATA131_I_E;
				DATA131_Q <= DATA131_Q_E;
				SAMPLE131_CLK <= '1';	
				SYMBOL131_CLK <= '1';
			end if;
		else
			SAMPLE131_CLK <= '0';
			SYMBOL131_CLK <= '0';
	  	end if;
  	end if;
end process;

-- coherent summing when SQPN + single source
COHERENT_SUM: process(CLK)
begin
	if rising_edge(CLK) then
		-- keep DATA131B and DATA132B aligned. Important when reconstructing the alternating I/Q sequence after demod.
		SAMPLE131B_CLK <= SAMPLE131_CLK;
		SYMBOL131B_CLK <= SYMBOL131_CLK;
		SAMPLE132B_CLK <= SAMPLE132_CLK;
		SYMBOL132B_CLK <= SYMBOL132_CLK;
		DATA132B_I <= DATA132_I;
		DATA132B_Q <= DATA132_Q;

		if(CONTROL(2 downto 1) = "11") then
			-- SQPN, same data on I/Q (after possible 1/2 symbol re-alignment)
			-- rotate DATA132 -90 deg before coherent sum. Extend precision 1bit to prevent overflow
			DATA131B_I <= (DATA131_I(13) & DATA131_I(13 downto 1)) + (DATA132_Q(13) & DATA132_Q(13 downto 1));
			DATA131B_Q <= (DATA131_Q(13) & DATA131_Q(13 downto 1)) - (DATA132_I(13) & DATA132_I(13 downto 1));
		else
			DATA131B_I <= DATA131_I;
			DATA131B_Q <= DATA131_Q;
		end if;
  	end if;
end process;

--//-- NORMALIZE I&D outputs Q-channel ---------------------
-- Start at SAMPLE102_ID_CLK
COARSE_GAIN_ADJUST_102A: process(CLK)
begin
	if rising_edge(CLK) then
		if(SAMPLE102_ID_CLK = '1') then
			SHIFT102 <= SPREADING_FACTOR2;
	  	elsif(SHIFT102 /= 0) then
			-- as long as SHIFT102 is not zero, keep shifting
			SHIFT102 <= "0" & SHIFT102(SHIFT102'left downto 1);
			COUNT_ENABLE102 <= '1';	-- start count enable pulse
		else
			-- SHIFT102 = 0. stop.
			COUNT_ENABLE102 <= '0';	-- stop count enable pulse
		end if;
	end if;
end process;
COARSE_GAIN_ADJUST_112A: process(CLK)
begin
	if rising_edge(CLK) then
		if(SAMPLE112_ID_CLK = '1') then
			SHIFT112 <= SPREADING_FACTOR2;
	  	elsif(SHIFT112 /= 0) then
			-- as long as SHIFT112 is not zero, keep shifting
			SHIFT112 <= "0" & SHIFT112(SHIFT112'left downto 1);
			COUNT_ENABLE112 <= '1';	-- start count enable pulse
		else
			-- SHIFT112 = 0. stop.
			COUNT_ENABLE112 <= '0';	-- stop count enable pulse
		end if;
	end if;
end process;


COARSE_GAIN_ADJUST_102B: process(CLK)
begin
	if rising_edge(CLK) then
		COUNT_ENABLE102_D <= COUNT_ENABLE102;

		if(SAMPLE102_ID_CLK = '1') then
			-- let the input in
			DATA102_I_SHIFT <= DATA102_I_ID;
			DATA102_Q_SHIFT <= DATA102_Q_ID;
	  	elsif(COUNT_ENABLE102 = '1') then
			-- divide by 2, keep MSB unchanged (sign extension)
			DATA102_I_SHIFT(24 downto 0) <= DATA102_I_SHIFT(25 downto 1);
			DATA102_Q_SHIFT(24 downto 0) <= DATA102_Q_SHIFT(25 downto 1);
	  	end if;
  	end if;
end process;
COARSE_GAIN_ADJUST_112B: process(CLK)
begin
	if rising_edge(CLK) then
		COUNT_ENABLE112_D <= COUNT_ENABLE112;

		if(SAMPLE112_ID_CLK = '1') then
			-- let the input in
			DATA112_I_SHIFT <= DATA112_I_ID;
			DATA112_Q_SHIFT <= DATA112_Q_ID;
	  	elsif(COUNT_ENABLE112 = '1') then
			-- divide by 2, keep MSB unchanged (sign extension)
			DATA112_I_SHIFT(24 downto 0) <= DATA112_I_SHIFT(25 downto 1);
			DATA112_Q_SHIFT(24 downto 0) <= DATA112_Q_SHIFT(25 downto 1);
	  	end if;
  	end if;
end process;

-- mux samples at symbol center and 1/2 symbol off center 
-- DATA13 is sampled at 2x symbol rate
COARSE_GAIN_ADJUST_132: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') or (CONTROL(1) = '0') then
			-- reset when BPSK 
			DATA132_I <= (others => '0');
			DATA132_Q <= (others => '0');
			SAMPLE132_CLK <= '0';
			SYMBOL132_CLK <= '0';
		elsif(COUNT_ENABLE102_D = '1') and (COUNT_ENABLE102 = '0') then
			-- shift is complete
			-- output shifted result. Keep only 14 LSBs.
			-- Guaranteed overflow-free.
			DATA132_I <= DATA102_I_SHIFT(14 downto 1);
			DATA132_Q <= DATA102_Q_SHIFT(14 downto 1);
			SAMPLE132_CLK <= '1';	
			SYMBOL132_CLK <= '1';
		elsif(COUNT_ENABLE112_D = '1') and (COUNT_ENABLE112 = '0') then
			-- shift is complete
			-- output shifted result. Keep only 14 LSBs.
			-- Guaranteed overflow-free.
			DATA132_I <= DATA112_I_SHIFT(14 downto 1);
			DATA132_Q <= DATA112_Q_SHIFT(14 downto 1);
			SAMPLE132_CLK <= '1';
			SYMBOL132_CLK <= '0';
		else
			SAMPLE132_CLK <= '0';
			SYMBOL132_CLK <= '0';
	  	end if;
  	end if;
end process;


------------------------------------------------------------------------
-- From here onwards, the demodulator is a regular PSK demodulator
------------------------------------------------------------------------
-- DATA13 are unspread PSK modulated signals at baseband. Use regular PSK modulator for symbol timing and carrier tracking.
-- see below.

--// FAST FREQUENCY ACQUISITION --------------------
-- Algorithm: I&D + complex square + complex FFT + max magnitude bin
DATA81_Ix <= DATA81_I & "0000";	
DATA81_Qx <= DATA81_Q & "0000";	
FFD_ENABLE <= '1' when (CODE_LOCK = '1') else '0';

-- previous: remove dependency
--FFD_ENABLE <= '1' when (CODE_LOCK = '1') and ((CARRIER_LOCK_local = '0') or (STATE < 2)) else '0';
	-- enable FFT only when needed
	
-- Algorithm: despread input is squared (doubles the frequency and removes the PSK modulation) then
-- goes through a NID integrate and dump. 
-- 2048-pt FFT 
-- rule of thumb: I&D for just a fraction (1/3, 1/4) of an I symbol
-- For example: I symbol rate = 5 Kbits/s =>  NID = 256
--   frequency error is 2*3Mchips/s/256/2048/2 = 5.7Hz
--   frequency range: +/- 12 KHz
--   detection duration: 2048*256/2*3Mchips/s = 87ms
-- It is important to have a small resolution to ease the transition to the Costas loop.

-- find the closest 2^n value for NID, depending on the I symbol rate
FAST_FREQUENCY_DETECTION2_001: process(CLK)
begin
	if rising_edge(CLK) then
		-- IMPORTANT: DO NOT CHANGE UNLESS CONSIDERING EVERYTHING! (threshold SNR, min/max symbol rate, etc)
		-- criteria1: fft bin has to be small enough to be accurate at better than 1% of the symbol rate
		-- criteria2: fft bin has to be small enough to detect signal presence at the threshold Eb/No
		-- criteria3: FFD_NID has to be small enough not to blurr the symbol during I&D
		-- criteria4: verify acquisition range requirement is met
		if(SPREADING_FACTOR1(12 downto 9) /= "0000") then
			FFD_NID <= 256;
			FFD_NID_LOG2 <= 8;
		elsif(SPREADING_FACTOR1(8) = '1') then
			FFD_NID <= 128;
			FFD_NID_LOG2 <= 7;
		elsif(SPREADING_FACTOR1(7) = '1') then
			FFD_NID <= 64;
			FFD_NID_LOG2 <= 6;
		elsif(SPREADING_FACTOR1(6) = '1') then
			FFD_NID <= 32;
			FFD_NID_LOG2 <= 5;
		elsif(SPREADING_FACTOR1(5) = '1') then
			FFD_NID <= 16;
			FFD_NID_LOG2 <= 4;
		elsif(SPREADING_FACTOR1(4) = '1') then
			FFD_NID <= 8;
			FFD_NID_LOG2 <= 3;
		elsif(SPREADING_FACTOR1(3) = '1') then
			FFD_NID <= 4;
			FFD_NID_LOG2 <= 2;
		elsif(SPREADING_FACTOR1(2) = '1') then
			FFD_NID <= 2;
			FFD_NID_LOG2 <= 1;
		else
			FFD_NID <= 1;	
			FFD_NID_LOG2 <= 0;
		end if;
	end if;
end process;

FAST_FREQUENCY_DETECTION_002: FAST_FREQUENCY_DETECTION 
	generic map(
		NID_MAX_LOG2 => NID_MAX_LOG2,	-- NID max 
		SIMULATION => SIMULATION
	)
port map(
	CLK => CLK,    
	SYNC_RESET => ST_SYNC_RESET,
	DATA_I_IN => DATA81_Ix,
	DATA_Q_IN => DATA81_Qx,  
	SAMPLE_CLK_IN => SAMPLE8_CLK, -- 2x chip rate
	ENABLE => FFD_ENABLE,	-- trigger. enable only during acquisition
	NID => FFD_NID,
	NID_LOG2 => FFD_NID_LOG2, 
	FFTM => FFTM,	
	FFTM2 => FFTM2,   
	FFTM_AVRG => FFTM_AVRG, 
	FFTF => FFTF,
	FFTP => FFTP,	 -- unused
	FFT_READY => FFT_READY,
	SATURATION => FFD_SATURATION,
	CS1 => open,    
	CS1_CLK => open,
	TP => open
);      

-- compare FFTM and FFTM2 or FFTM_AVRG as reliable signal presence indicator (tweak to optimize Pd/Pfa at threshold SNR)
FFTM_THRESHOLD(13 downto 2) <= FFTM_AVRG(11 downto 0);  -- 4* average
SIGNAL_PRESENCE_001: process(CLK)
begin
	if rising_edge(CLK) then
	   FFT_READY_D <= FFT_READY;

	   if(ST_SYNC_RESET = '1') then
	       -- no signal assumed when code tracking loop is unlocked
	       SIGNAL_PRESENT_local <= '0';
	   elsif(FFT_READY = '1') then
--	       if(( FFTM2(13) = '0') and (FFTM(13 downto 1) > FFTM2(12 downto 0))) or 
--	       (( FFTM_AVRG(13 downto 11) = 0) and (FFTM(13 downto 3) > FFTM_AVRG(10 downto 0))) then
--	           -- when FFT peak is larger than 2*second peak
--	           -- or FFT peak > 8 average FFT magnitude
	       if(FFTM(13 downto 2) > FFTM_THRESHOLD(13 downto 2)) then
	               -- when FFT peak > X average FFT magnitude
	           SIGNAL_PRESENT_local <= '1';
	       else
	           SIGNAL_PRESENT_local <= '0';
	       end if;
		end if;
    end if;
end process;
SIGNAL_PRESENT_OUT <= SIGNAL_PRESENT_local;

-- perform frequency correction once after the first FFT
-- remember to invert sign. Frequency units are chip_rate/NID*2048. 
FREQ_CORRECTION_GEN: process(CLK)
begin
	if rising_edge(CLK) then
		if(STATE = 0) and (FFT_READY = '1') then
			-- scale the FFTF units from chip_rate /NID*2048 to 2*chip_rate
			-- adjust only during acquisition
			-- extend to 32 bits NCO
			FFTF_SHIFT(31 downto 31) <= (others => FFTF(10));	-- sign extension
			FFTF_SHIFT(30 downto 20) <= FFTF;
			FFTF_SHIFT(19 downto 0) <= (others => '0');	
			FFTF_SHIFT_CNTR <= conv_unsigned(FFD_NID_LOG2, FFTF_SHIFT_CNTR'length);
			FFT_SHIFT_FLAG <= '1';
			FFT_ERROR_SAMPLE_CLK <= '1';
		elsif(FFTF_SHIFT_CNTR /= 0) then
			-- shift right
			FFTF_SHIFT_CNTR <= FFTF_SHIFT_CNTR - 1;
			FFTF_SHIFT(30 downto 0) <= FFTF_SHIFT(31 downto 1);
		elsif(FFT_SHIFT_FLAG = '1') then
			FFT_SHIFT_FLAG <= '0';
			FFT_FREQ_ERROR <= FFTF_SHIFT;
			FFT_ERROR_SAMPLE_CLK <= '1';
		elsif (STATE = 0) then
			-- clear frequency error
			FFT_FREQ_ERROR <= (others => '0');
			FFT_ERROR_SAMPLE_CLK <= '0';
		else
			FFT_ERROR_SAMPLE_CLK <= '0';
		end if;
	end if;
end process;

--// NORMALIZE AFTER FILTER ---------------------
-- Several tracking loops (symbol timing, carrier phase tracking) are designed such that the loop gain depends 
-- on the input signal amplitude. To eliminate this dependency and guarantee a predictable behavior, the post
-- filtering signal is normalized by this AGC

-- target magnitude depends on modulation scheme 
-- Objective: keep amplitude samples I/Q constant
AGC18_MAGNITUDE_TARGET <= 	"00010100011110";  -- empirical. adjust so that DATA151_I is 512 at center of symbol (same as in COM-1831)

-- forward AGC
-- Latency 3 CLKs
AGC18_001: AGC18 
GENERIC MAP(
	AVERAGING_LENGTH => 1024,
	SIMULATION => SIMULATION
)
PORT MAP(
	CLK => CLK,
	SYNC_RESET => SYNC_RESET,
	DATA_I_IN => DATA131B_I,
	DATA_Q_IN => DATA131B_Q,
	SAMPLE_CLK_IN => SAMPLE131B_CLK,
	MTARGET => AGC18_MAGNITUDE_TARGET,
	CONTROL => "1",	-- always enabled
	SYMBOLx2_CLK_IN => SAMPLE131B_CLK,
	DATA_I_OUT => DATA141_I,
	DATA_Q_OUT => DATA141_Q,
	SAMPLE_CLK_OUT => SAMPLE141_CLK,
	SATURATION => SATURATION_AGC1,
	DATA_M => DATA13M,
	SAMPLE_M_CLK => SAMPLE13M_CLK,
	TP => open,
	CS1 => CS6,
	CS1_CLK => CS6_CLK
);

AGC18_002: AGC18 
GENERIC MAP(
	AVERAGING_LENGTH => 1024,
	SIMULATION => SIMULATION
)
PORT MAP(
	CLK => CLK,
	SYNC_RESET => SYNC_RESET,
	DATA_I_IN => DATA132B_I,
	DATA_Q_IN => DATA132B_Q,
	SAMPLE_CLK_IN => SAMPLE132B_CLK,
	MTARGET => AGC18_MAGNITUDE_TARGET,
	CONTROL => "1",	-- always enabled
	SYMBOLx2_CLK_IN => SAMPLE132B_CLK,
	DATA_I_OUT => DATA142_I,
	DATA_Q_OUT => DATA142_Q,
	SAMPLE_CLK_OUT => SAMPLE142_CLK,
	SATURATION => SATURATION_AGC2,
	DATA_M => open,
	SAMPLE_M_CLK => open,
	TP => open,
	CS1 => open,
	CS1_CLK => open
);

-- When the AGC is tracking, DATA13M magnitude is AGC18_MAGNITUDE_TARGET, around 2048 (or 1.0 with a 3.11 format).
-- Therefore, the real and imaginary DATA141_I/DATA141_Q are typically around approx 1250.

-- realign SYMBOL141_CLK
RECLOCK_141: process(CLK)
begin
	if rising_edge(CLK) then
		SYMBOL131_SHIFT(1 downto 0) <= SYMBOL131_SHIFT(0 downto 0) & SYMBOL131B_CLK;
		SYMBOL141_CLK <= SYMBOL131_SHIFT(1);
		SYMBOL132_SHIFT(1 downto 0) <= SYMBOL132_SHIFT(0 downto 0) & SYMBOL132B_CLK;
		SYMBOL142_CLK <= SYMBOL132_SHIFT(1);
	end if;
end process;


--//-- FREQUENCY TRANSLATION 2 (UNDER PLL CONTROL) -------------------------------
-- Track phase under PLL control 
-- latency 3 CLKs
DIGITAL_DC2_002: DIGITAL_DC2 PORT MAP(
	CLK => CLK,
	DATA_I_IN => DATA141_I(13 downto 2),
	DATA_Q_IN => DATA141_Q(13 downto 2),
	SAMPLE_CLK_IN => SAMPLE141_CLK,
	PHASE_ROTATION => CCF_PHASE2_D(31 downto 20),	-- CCF_PHASE is added to the input signal phase.,
	DATA_I_OUT => DATA151_I,
	DATA_Q_OUT => DATA151_Q,
	SAMPLE_CLK_OUT => SAMPLE151_CLK,
	SATURATION => SATURATION151
);

DIGITAL_DC2_003: DIGITAL_DC2 PORT MAP(
	CLK => CLK,
	DATA_I_IN => DATA142_I(13 downto 2),
	DATA_Q_IN => DATA142_Q(13 downto 2),
	SAMPLE_CLK_IN => SAMPLE142_CLK,
	PHASE_ROTATION => CCF_PHASE2_D(31 downto 20),	-- CCF_PHASE is added to the input signal phase.,
	DATA_I_OUT => DATA152_I,
	DATA_Q_OUT => DATA152_Q,
	SAMPLE_CLK_OUT => SAMPLE152_CLK,
	SATURATION => SATURATION152
);

-- realign SYMBOL151_CLK, SYMBOL152_CLK
RECLOCK_151: process(CLK)
begin
	if rising_edge(CLK) then
		SYMBOL141_SHIFT(1 downto 0) <= SYMBOL141_SHIFT(0 downto 0) & SYMBOL141_CLK;
		SYMBOL151_CLK <= SYMBOL141_SHIFT(1);
		SYMBOL142_SHIFT(1 downto 0) <= SYMBOL142_SHIFT(0 downto 0) & SYMBOL142_CLK;
		SYMBOL152_CLK <= SYMBOL142_SHIFT(1);
	end if;
end process;

NCO32_002: process(CLK)
begin
	if rising_edge(CLK) then
		-- NCO: accumulate phase
		if(CF_NCO_CONTROL2A_SAMPLE_CLK = '1') and ((SIMULATION = '0') or (CF_NCO_CONTROL2A(0) /= 'X')) then	-- prevent 'X' propagation in the accumulator
            CCF_PHASE2 <= CCF_PHASE2 + CF_NCO_CONTROL2A; -- 1st order CT loop contribution only.
        end if;

		CCF_PHASE2_D <= CCF_PHASE2;	-- pipelining
	end if;
end process;

--// Good place to implement spectrum inversion when selected.
-- Phase error is adjusted accordingly not to change the phase tracking loop sign.
SPECTRUM_INVERSION_001:  process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE161_CLK <= SAMPLE151_CLK;
		SYMBOL161_CLK <= SYMBOL151_CLK;
		SAMPLE162_CLK <= SAMPLE152_CLK;
		SYMBOL162_CLK <= SYMBOL152_CLK;

		DATA161_I <= DATA151_I;
		DATA162_I <= DATA152_I;

		if(CONTROL(0) = '0') then
			-- no spectrum inversion
			DATA161_Q <= DATA151_Q;
			DATA162_Q <= DATA152_Q;
		else
			-- spectrum inversion.
			-- change the sign of the Q channel.
			DATA161_Q <= not DATA151_Q;  -- approximation of a sign inversion. simpler than not()+1 + overflow detection;
			DATA162_Q <= not DATA152_Q;  -- approximation of a sign inversion. simpler than not()+1 + overflow detection;
		end if;
	end if;
end process;

--//-- ACCURATE SNRs -------------------------------------
-- More accurate SNRs measurement, but dependent on all tracking loops (code, carrier, symbol timing, AGC) 
-- properly locked and tracking.
-- Independent SNR measurement on each channel.
-- new 2/2/16

-- channel 1 average power at the center of the symbol
POWER161_GEN: POWER_MEASUREMENT 
GENERIC MAP(
	REAL_COMPLEXn => '0',	-- input is real
	SIMULATION => SIMULATION
)
PORT MAP(
	  CLK => CLK,
	  SYNC_RESET => ST_SYNC_RESET,	-- keep in reset while code is unlocked
	  SAMPLE_CLK_IN => SYMBOL161_CLK,
	  DATA_I_IN => DATA161_I_X,
	  DATA_Q_IN => (others => '0'),
	  SAMPLE_CLK_OUT => POWER161_VALID,
	  POWER_OUT => POWER161
);

POWER162_GEN: POWER_MEASUREMENT 
GENERIC MAP(
	REAL_COMPLEXn => '0',	-- input is real
	SIMULATION => SIMULATION
)
PORT MAP(
	  CLK => CLK,
	  SYNC_RESET => ST_SYNC_RESET,	-- keep in reset while code is unlocked
	  SAMPLE_CLK_IN => SYMBOL162_CLK,
	  DATA_I_IN => DATA162_Q_X,
	  DATA_Q_IN => (others => '0'),
	  SAMPLE_CLK_OUT => POWER162_VALID,
	  POWER_OUT => POWER162
);

NOISE161_GEN: POWER_MEASUREMENT 
GENERIC MAP(
	REAL_COMPLEXn => '0',	-- input is real
	SIMULATION => SIMULATION
)
PORT MAP(
	  CLK => CLK,
	  SYNC_RESET => ST_SYNC_RESET,	-- keep in reset while code is unlocked
	  SAMPLE_CLK_IN => SYMBOL161_CLK,
	  DATA_I_IN => DATA161_Q_X,
	  DATA_Q_IN => (others => '0'),
	  SAMPLE_CLK_OUT => open,
	  POWER_OUT => NOISE161
);

-- format 16.2  (2 bits after decimal point obtained by scaling the denominator by 4)
SNR_MUX_STATE_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			SNR_MUX_STATE <= 0;	-- wait for first POWER161_VALID
		elsif(SNR_MUX_STATE = 0) and (POWER161_VALID = '1') then
			SNR_MUX_STATE <= 1;	-- wait for the division to complete
		elsif(SNR_MUX_STATE = 1) and (SNRx_VALID = '1') then
			SNR_MUX_STATE <= 2;	-- wait for first POWER162_VALID
		elsif(SNR_MUX_STATE = 2) and (POWER162_VALID = '1') then
			SNR_MUX_STATE <= 3;	-- wait for the division to complete
		elsif(SNR_MUX_STATE = 3) and (SNRx_VALID = '1') then
			SNR_MUX_STATE <= 0;	-- done. repeat
		end if;
	end if;
end process;

SNRx_NUM <= POWER161(23 downto 6) when (SNR_MUX_STATE < 2) else POWER162(23 downto 6);
SNRx_SAMPLE_CLK_IN <= POWER161_VALID when (SNR_MUX_STATE < 2) else POWER162_VALID;
NOISE161_DIV4 <= "00" & NOISE161(23 downto 2);
SNRx_GEN: DIVIDER 
GENERIC MAP(
	NBITS => 18
)
PORT MAP (
		 CLK => CLK,
		 NUM => SNRx_NUM,
		 DENOM => NOISE161_DIV4(23 downto 6),
		 SAMPLE_CLK_IN => SNRx_SAMPLE_CLK_IN,	
		 QUOTIENT => SNRx_LOCKED,	-- format 16.2
		 REMAINDER => open,
		 SAMPLE_CLK_OUT => SNRx_VALID
	  );

SNR_MUX_STATE_002: process(CLK)
begin
	if rising_edge(CLK) then
		if(SNR_MUX_STATE = 1) and (SNRx_VALID = '1') then
			SNR1_LOCKED_OUT <= SNRx_LOCKED;
		end if;
		
		if(SNR_MUX_STATE = 3) and (SNRx_VALID = '1') then
			SNR2_LOCKED_OUT <= SNRx_LOCKED;
		end if;
	end if;
end process;


--//-- SYMBOL TRACKING ------------------------
-- Gardner algorithm (not decision-directed)
-- 1st order loop capable of tracking up to +/- 1000ppm (SPECS) 

-- during acquisition: increased loop gain, 1st order only (memory is reset)
-- during tracking, minimize jitter (lower loop gain, 2nd order on)
ACCELERATED_STLOOP_RESPONSE <= '1' when (STATE < 2) else '0';

DATA161_I_X <= DATA161_I & "000000";
DATA161_Q_X <= DATA161_Q & "000000";
DATA162_I_X <= DATA162_I & "000000";
DATA162_Q_X <= DATA162_Q & "000000";
-- reset symbol tracking loop when code sync is lost
ST_SYNC_RESET <= '1' when (CODE_LOCK = '0') else SYNC_RESET;

SYMBOL_TRACKING_003I: SYMBOL_TIMING_LOOP5X2CH 
	GENERIC MAP(
		SIMULATION => SIMULATION
	)
	PORT MAP(
	CLK => CLK,
	SYNC_RESET => ST_SYNC_RESET,
	SYMBOL_CLK_IN => SYMBOL161_CLK,
	SYMBOL_CLKx2_IN => SAMPLE161_CLK,
	DATA_I_IN => DATA161_I_X,
	DATA_Q_IN => DATA161_Q_X,
	FREEZE_SYMBOL_TIMING => '0',
	ACCELERATED_STLOOP_RESPONSE => ACCELERATED_STLOOP_RESPONSE,	
	NCO_TIMING_CONTROL => ST_NCO_TIMING_CONTROL1,
	NCO_TIMING_CONTROL_CLK => ST_NCO_TIMING_CONTROL1_CLK,
	CS1 => CS10,	
	CS1_CLK => CS10_CLK
);

-- For test purposes, accumulate the error.
-- Optimized out by synthesis tool. 
ST_NCO_ACC_GEN: process(CLK)
begin
    if rising_edge(CLK) then
        if(ST_SYNC_RESET = '1') or (SIMULATION = '0') then
            ST_PHASE_ACC1 <= (others => '0');
        elsif(ST_NCO_TIMING_CONTROL1_CLK = '1') and (ST_NCO_TIMING_CONTROL1(31) /= 'X') then
            ST_PHASE_ACC1 <= ST_PHASE_ACC1 + ST_NCO_TIMING_CONTROL1;
        end if;
    end if;
end process;

-- 2nd independent symbol tracking (when enabled)
ST2_SYNC_RESET <= '1' when (CODE_LOCK = '0') or (CONTROL(1) = '0') or (CONTROL(2) = '1') else SYNC_RESET;

SYMBOL_TRACKING_003Q: SYMBOL_TIMING_LOOP5X2CH 
	GENERIC MAP(
		SIMULATION => '0'  -- watch out for dual writing to SIM2OUTFILE st5.txt file when two loops are active
	)
	PORT MAP(
	CLK => CLK,
	SYNC_RESET => ST2_SYNC_RESET,
	SYMBOL_CLK_IN => SYMBOL162_CLK,
	SYMBOL_CLKx2_IN => SAMPLE162_CLK,
	DATA_I_IN => DATA162_I_X,
	DATA_Q_IN => DATA162_Q_X,
	FREEZE_SYMBOL_TIMING => '0',
	ACCELERATED_STLOOP_RESPONSE => ACCELERATED_STLOOP_RESPONSE,	
	NCO_TIMING_CONTROL => ST_NCO_TIMING_CONTROL2,
	NCO_TIMING_CONTROL_CLK => ST_NCO_TIMING_CONTROL2_CLK,
	CS1 => open,	
	CS1_CLK => open
);

--//-- CARRIER TRACKING --------------------
-- The main purpose of this loop is to rotate the received (filtered) complex samples so that 
-- all the channel1 energy is on the I axis (and therefore all the channel2 energy is on the Q axis).
-- Only tracking channel 1.
-- Compute the phase error PE as Q*sign(I) 
-- Note: this method seems more resilient at very low SNRs than the POLAR3 cartesian to polar coordinate look-up table.
-- Computation is done only once per symbol period at the presumed optimum sampling instant.
-- 1 bit sign extension for PE to prevent overflow, dropped further below.
-- Design note about scaling: DATA161_x is normalized at 32K when AGC18 is tracking.
-- Although PE is an approximation, we scale it such that it roughly matches a 11 bit phase (2047 = 360 deg)
CARRIER_TRACK_001: process(CLK)
begin
	if rising_edge(CLK) then
		PE_SYMBOL_CLK <= SYMBOL161_CLK;

		if(SYMBOL161_CLK = '1') then
			-- presumed optimum sampling instant
			-- compute phase error as for BPSK: Q*sign(I). 
			if(DATA161_I_X(17) = '0') then
				PE <= sxt(DATA161_Q_X(17 downto 7),12);
			else
				PE <= sxt(not DATA161_Q_X(17 downto 7),12);
			end if;
		end if;
	end if;
end process;

CT_SYNC_RESET <= SYNC_RESET or RESET_DEMOD_IN_FALSE_LOCK or FFT_ERROR_SAMPLE_CLK;
	-- must clear the 2nd order branch (inertia) when jumping to the next scan frequency
ACCELERATED_CT_RESPONSE <= '1' when (STATE = 0) or (STATE = 1) else '0';
    -- disable the 2nd order (wide-range frequency tracking loop) until code and carrier are locked.

	
-- we are lucky here since we know the SNR (at least when the code is locked). So we can set
-- the carrier lock threshold accordingly.
-- This is important to achieve both lock at very low SNR and avoid false lock report at very high SNR.
CT_LOCK_THRESHOLD_GEN: process(CLK)
begin
	if rising_edge(CLK) then
		if(CODE_LOCK = '1') then
--			if(SNR_LOCKED >= 120) then
--				-- high SNR: SNR > 14.5 dB.   rms phase error < 10.8 deg rms
--				CT_LOCK_THRESHOLD <= "0011";	-- 10 deg rms threshold
--			elsif(SNR_LOCKED >= 60) then
--				-- SNR > 8.5 dB.   rms phase error < 21.5 deg rms
--				CT_LOCK_THRESHOLD <= "0101";	-- 20 deg rms threshold
			if(SNR_LOCKED >= 36) then
				-- SNR > 5 dB.   rms phase error < 32.2 deg rms
				CT_LOCK_THRESHOLD <= "0111";	-- 30 deg rms threshold
			elsif(SNR_LOCKED >= 28) then
				-- SNR > 2.9 dB.   rms phase error < 41 deg rms
				CT_LOCK_THRESHOLD <= "1001";	-- 40 deg rms threshold
			else
				-- low SNR
				CT_LOCK_THRESHOLD <= "1010";	-- 45 deg rms threshold
			end if;
--		else
--			CT_LOCK_THRESHOLD <= "0111";	-- 30 deg. Does not matter anyway.
		end if;
	end if;
end process;

ACTR2 <= '1' when (STATE = 0) else '0';	    -- disable CT2 until after the FAST_FREQUENCY_DETECTION is done
CARRIER_TRACK2_003: CARRIER_TRACKING2 
	generic map(
    SIMULATION => SIMULATION
    )
    PORT MAP(
	CLK => CLK,
	SYNC_RESET => CT_SYNC_RESET,
	OPTIMUM_SAMPLING_CLK => PE_SYMBOL_CLK,	-- phase is measured once per symbol at the presumed symbol center
	PHASE_ERROR => PE(10 downto 0),	-- expected units: 2048 = 360 deg
	NOMINAL_SYMBOL_RATE => NOMINAL_SYMBOL_RATE1,
	LOOP_GAIN1 => "00",	-- for test purposes only. maybe commented out within.
	LOOP_GAIN2 => "00",	-- for test purposes only. maybe commented out within.
-- 	ACCELERATED_CT_RESPONSE => ACTR2,	-- accelerate convergence + disable 2nd order loop during acquisition.
 	ACCELERATED_CT_RESPONSE => ACCELERATED_CT_RESPONSE,	-- accelerate convergence during acquisition.
	LOCK_THRESHOLD => CT_LOCK_THRESHOLD,	
	NCO_CONTROL => CF_NCO_CONTROL2A0,	
	NCO_CONTROL_SAMPLE_CLK => CF_NCO_CONTROL2A0_SAMPLE_CLK,	
	FREQ_ERROR => CF_NCO_CONTROL2B0,     -- frequency error (expressed as 2^32*fe/fclk)
	CARRIER_LOCK => CARRIER_LOCK_local,
	CS1 => open,
	CS1_CLK => open,
	CS2 => open,
	CS2_CLK => open,
	CS3 => open,		
	CS3_CLK => open
);


-- Watch out: the sign depends on whether the spectrum inversion is enabled or not (CONTROL(0))
CARRIER_TRACK_004: process(CLK)
begin
	if rising_edge(CLK) then
	   CF_NCO_CONTROL2A_SAMPLE_CLK <= CF_NCO_CONTROL2A0_SAMPLE_CLK;
	   
		-- Correct sign depending on spectrum inversion or not
		if(CONTROL(0) = '0') then
			-- no spectrum inversion
			CF_NCO_CONTROL2A <= not CF_NCO_CONTROL2A0;	
			CF_NCO_CONTROL2B <= not CF_NCO_CONTROL2B0;	
		else
			-- spectrum inversion
			CF_NCO_CONTROL2A <= CF_NCO_CONTROL2A0;	
			CF_NCO_CONTROL2B <= CF_NCO_CONTROL2B0;	
		end if;
	end if;
end process;

-- monitoring
MONITORING_OUT_001: process(CLK)
begin
	if rising_edge(CLK) then
		CARRIER_LOCK_OUT <= CARRIER_LOCK_local;
		-- test test test
--		POWER_N_AVERAGE_OUT <= POWER_AVERAGE_D;
--		POWER_S_AVERAGE_OUT <= POWER_ACC_ONTIME_REF;
-- alternate measurement, more precise but predicated on all loops tracking. Beware of circular logic when using these values	
		POWER_S_AVERAGE_OUT <= POWER161(23 downto 6);
		POWER_N_AVERAGE_OUT <= NOISE161(23 downto 6);
	end if;
end process;


-- Carrier phase/frequency tracking state machine
-- Updated once every 1024 symbols (because there are several integrators within AFC/CARRIER TRACKING
-- with a latency of 512 symbols)
STATE_GEN_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			SYMBOL_CNTR <= (others => '0');
		elsif(SYMBOL81_CLK = '1') then
			-- first, generate a pulse once every 1024 symbols
			SYMBOL_CNTR <= SYMBOL_CNTR + 1;
			if(SYMBOL_CNTR = 0) then
				SYMBOL_DIV1K <= '1';
			else
				SYMBOL_DIV1K <= '0';
			end if;
		else
			SYMBOL_DIV1K <= '0';
		end if;
	end if;
end process;

-- assess confidence level regarding carrier lock and code lock
-- Confidence ranges from 0 to 7
STATE_GEN_002B: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') or (RESET_DEMOD_IN_FALSE_LOCK = '1') then
			CARRIER_LOCK_CONFIDENCE <= (others => '0');
		elsif(SYMBOL_DIV1K = '1') then
			if(CARRIER_LOCK_local = '1') and (CARRIER_LOCK_CONFIDENCE /= 7) then
				CARRIER_LOCK_CONFIDENCE <= CARRIER_LOCK_CONFIDENCE + 1;
			elsif(CARRIER_LOCK_local = '0') and (CARRIER_LOCK_CONFIDENCE /= 0) then
				CARRIER_LOCK_CONFIDENCE <= CARRIER_LOCK_CONFIDENCE - 1;
			end if;
		end if;
	end if;
end process;

STATE_GEN_003: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') or (RESET_DEMOD_IN_FALSE_LOCK = '1') or (CODE_LOCK = '0')  then
			STATE <= 0;
		elsif(STATE = 0) and (FFT_READY_D = '1') and (SIGNAL_PRESENT_local = '1') then
			-- FFT output. Perform frequency, phase and amplitude corrections. Await carrier lock.
			STATE <= 1;
		elsif(STATE = 1) and (CARRIER_LOCK_local = '1') then 
			-- completed frequency, phase and amplitude corrections. Carrier locked.
			STATE <= 2;
		elsif(STATE = 2) and (CARRIER_LOCK_CONFIDENCE = 7) then
			-- reached the highest level of confidence. Confirmed lock.
			STATE <= 3;
	   elsif(STATE = 3) and (CARRIER_LOCK_CONFIDENCE = 0) then
			-- confirmed loss of carrier lock after having reached the highest level of confidence.
			-- go back to acquisition state
			STATE <= 0;
		end if;
	end if;
end process;

--//-- PSK SYMBOL DECODING ------------------------------------------------
-- truncate to signed 4 bits. 
-- Algorithm note: DATA16x_ is normalized at 32K when AGC18 is tracking

SOFT_QUANT_001:  process(CLK)
begin
	if rising_edge(CLK) then
		SYMBOL191_CLK <= SYMBOL161_CLK;
		SYMBOL192_CLK <= SYMBOL162_CLK;
		
		if(SYMBOL161_CLK = '1') then
			-- truncate I sample
			if(DATA161_I_X(17) = '0') and (DATA161_I_X(16 downto 15) /= 0) then
				-- positive saturation
				DATA191 <= "0111";
			elsif(DATA161_I_X(17) = '1') and ((not DATA161_I_X(16 downto 15)) /= 0) then
				-- negative saturation
				DATA191 <= "1000";
			else
				DATA191 <= DATA161_I_X(15 downto 12);
			end if;
		end if;
			
		if(SYMBOL162_CLK = '1') then
			-- truncate Q sample
			if(DATA162_Q_X(17) = '0') and (DATA162_Q_X(16 downto 15) /= 0) then
				-- positive saturation
				DATA192 <= "0111";
			elsif(DATA162_Q_X(17) = '1') and ((not DATA162_Q_X(16 downto 15)) /= 0) then
				-- negative saturation
				DATA192 <= "1000";
			else
				DATA192 <= DATA162_Q_X(15 downto 12);
			end if;
		end if;
	end if;
end process;

-- quality bits
DATA191QUAL <= DATA191(2 downto 0) when (DATA191(3) = '0') else not DATA191(2 downto 0);
	-- "111" for best quality, "000" for worst quality
DATA191AQUAL <= ("0" & DATA191QUAL) + ("0" & DATA191QUAL_D);
	-- average quality when two successive symbols are involved (NRZ-S,-M)

--// DATA FORMAT DECODING ------------------------------------------------
-- Convert to unsigned (binary offset) format

-- DATA20x format is 4-bit soft-quantized demodulated bits.
-- The most significant bit (3) represents the demodulated information, while
-- the lower 3-bits represent the demodulated bit quality for use by 
-- subsequent error correction decoder. Unsigned representation: 
-- 0000 for best quality '0', 1111 for best quality '1', etc.

--  BI-PHASE, NRZ, as defined in CONTROL(5:3)
DECODE_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYMBOL191_CLK = '1') then
			DATA191_D <= DATA191;
			DATA191QUAL_D <= DATA191QUAL;
			
			if(CONTROL(5 downto 3) = 0) then
				-- NRZ-L. same as output. 
				SYMBOL201_CLK <= '1';
				DATA201 <= DATA191(3) & not(DATA191(2 downto 0));
			elsif(CONTROL(5 downto 3) = 1) then
				-- NRZ-M
				-- unchanged demodulated bit -> '0' 
				-- changed demodulated bit -> '1'.
				-- information quality depends on two samples (average)
				SYMBOL201_CLK <= '1';
				if(DATA191(3) = DATA191_D(3)) then
					DATA201(3) <= '0';
					DATA201(2 downto 0) <=  not DATA191AQUAL(3 downto 1);  
				else
					DATA201(3) <= '1';
					DATA201(2 downto 0) <=  DATA191AQUAL(3 downto 1);
				end if;
			elsif(CONTROL(5 downto 3) = 2) then
				-- NRZ-S
				-- unchanged demodulated bit -> '1' 
				-- changed demodulated bit -> '0'.
				-- information quality depends on two samples (average)
				SYMBOL201_CLK <= '1';
				if(DATA191(3) /= DATA191_D(3)) then
					DATA201(3) <= '0';
					DATA201(2 downto 0) <=  not DATA191AQUAL(3 downto 1);   
				else
					DATA201(3) <= '1';
					DATA201(2 downto 0) <=  DATA191AQUAL(3 downto 1);  
				end if;

			elsif(CONTROL(5 downto 3) = 4) then
				-- Bi-Phase Level
				if(BIPHASE201 = '1') and (DATA191(3) = '0') and (DATA191_D(3) = '1') then
					-- received a '1'
					SYMBOL201_CLK <= '1';
					DATA201(3) <= '1';
					DATA201(2 downto 0) <= DATA191AQUAL(3 downto 1); 
					BIPHASE201 <= not BIPHASE201;  -- 0 for 1st half, '1' for second half
					if(BIPHASE_ERROR_COUNTER201 > 0) then
						BIPHASE_ERROR_COUNTER201 <= BIPHASE_ERROR_COUNTER201 -1;
					end if;
				elsif(BIPHASE201 = '1') and (DATA191(3) = '1') and (DATA191_D(3) = '0') then
					-- received a '0'
					SYMBOL201_CLK <= '1';
					DATA201(3) <= '0';
					DATA201(2 downto 0) <=  not DATA191AQUAL(3 downto 1);   
					BIPHASE201 <= not BIPHASE201;  -- 0 for 1st half, '1' for second half
					if(BIPHASE_ERROR_COUNTER201 > 0) then
						BIPHASE_ERROR_COUNTER201 <= BIPHASE_ERROR_COUNTER201 -1;
					end if;
				elsif(BIPHASE201 = '1') then
					-- illegal transition
					if(BIPHASE_ERROR_COUNTER201 > 15) then
						-- too many biphase errors. change foot. right-left-right-left
						-- skip toggling BIPHASE201 for one clock.
						BIPHASE_ERROR_COUNTER201 <= (others => '0');
						SYMBOL201_CLK <= '0';
					else
						BIPHASE_ERROR_COUNTER201 <= BIPHASE_ERROR_COUNTER201 + 3;
						BIPHASE201 <= not BIPHASE201;  -- 0 for 1st half, '1' for second half
						SYMBOL201_CLK <= '1';
					end if;
				else
					BIPHASE201 <= not BIPHASE201;  -- 0 for 1st half, '1' for second half
					SYMBOL201_CLK <= '0';
				end if;

			end if;
		else
			SYMBOL201_CLK <= '0';
		end if;
		
		if(SYMBOL192_CLK = '1') and (CONTROL(2 downto 1) = "01") then
		    -- output only when SQPN dual-source
			DATA192_D <= DATA192;
			DATA192QUAL_D <= DATA192QUAL;
			
			if(CONTROL(5 downto 3) = 0) then
				-- NRZ-L. same as output. 
				SYMBOL202_CLK <= '1';
				DATA202 <= DATA192(3) & not(DATA192(2 downto 0));
			end if;
		else
			SYMBOL202_CLK <= '0';
		end if;
		
		
	end if;
end process;

DATA_I_OUT <= DATA201;
DATA_Q_OUT <= DATA202;
SAMPLE_I_CLK_OUT <= SYMBOL201_CLK;
SAMPLE_Q_CLK_OUT <= SYMBOL202_CLK;


--// TEST POINTS -----------------------
	-- bit 1: recovered carrier frequency (coarse)
	-- bit 2: carrier lock
	-- bit 3: code lock
	-- bit 4: recovered carrier frequency (fine)
	-- bit 5: recovered chip clock
	-- bit 6: recovered I symbol clock
	-- bit 7: start of code replica
	-- bit 8: code replica used for despreading
	-- bit 9: received signal (I-channel, MSB) before despreading (compare with code replica above)
	-- bit 10: demodulated I bit
	-- bit 11: demodulated Q bit
	-- bit 12: saturation1 AGC18
	-- bit 13: saturation2 frequency translation
	-- bit 14: saturation on-time correlation
	-- bit 15: saturation AGC1
	-- bit 16: FFT overflow
	-- bit 17: saturation151 frequency translation
TP_OUT_001: process(CLK)
begin
	if rising_edge(CLK) then
		TP(1) <= CCF_PHASE1(31);
		TP(2) <= CARRIER_LOCK_local;
		TP(3) <= CODE_LOCK;
		TP(4) <= SIGNAL_PRESENT_local;
		TP(5) <= SYMBOL5_CLK;	-- chip clock
		TP(6) <= SYMBOL81_CLK;
		TP(7) <= CODE6A_START;
		TP(8) <= CODE61A(1);	-- despreading code replica
		TP(9) <= DATA6_I(13);	-- I-channel MSb before despreading. compare with code replica (should be aligned)
		TP(10) <= DATA191(3);	
		TP(11) <= DATA192(3);	
		TP(12) <= SATURATION1;
		TP(13) <= SATURATION2;
		TP(14) <= SATURATION(1);
		TP(15) <= SATURATION_AGC1;
		TP(16) <= FFD_ENABLE;

		-- test test test
		
		if(SNR_MUX_STATE = 1) and (SNRx_VALID = '1') then
			TP(17) <= '1';
		else
			TP(17) <= '0';
		end if;
		if(SNR_MUX_STATE = 3) and (SNRx_VALID = '1')  then
			TP(18) <= '1';
		else
			TP(18) <= '0';
		end if;
--		TP(17) <= DETECT;
--		TP(18) <= DETECT_FL;
		TP(19) <= DETECT_FL2;
	end if;
end process;

-- test test test
--TP_OUT_001: process(CLK)
--begin
--	if rising_edge(CLK) then
--	    TP(1) <= DETECT;
--	    TP(2) <= NODETECT;
--	    TP(3) <= DETECT_FL;
--	    TP(4) <= NODETECT_FL;
--	    TP(5) <= DETECT_FL2;
--	    if(STATE = 0) then
--	       TP(6) <= '1';
--	    else
--	       TP(6) <= '0';
--	    end if;
--		TP(7) <= CODE_LOCK;
--		TP(8) <= CARRIER_LOCK_local;
--		if(CARRIER_LOCK_CONFIDENCE = 7) then
--	       TP(9) <= '1';
--		else
--	       TP(9) <= '0';
--		end if;
--		TP(10) <= CCF_PHASE1(31);
--		TP(11) <= SIGNAL_PRESENT_local;
--	end if;
--end process;


--// COMSCOPE test points
	-- CS1: spread I-channel after AFC, resampling and channel LPF filter
	-- CS2: despread I-channel after coherent I&D
	-- CS3: despread Q-channel after coherent I&D
	-- CS4: demodulated I
	-- CS5: demodulated Q
	-- CS6: AGC18 scaling gain
	-- CS7: code replica
	-- CS8: accumulated code tracking phase correction (8 MSbs)
	-- CS9: carrier NCO phase (8 MSBs)
	-- CS10: accumulated symbol timing phase correction (8 MSbs)
	-- CS11: 2(S+N)/N, valid only if code lock. Linear, not in dBs.
	-- T1: start of code replica
	-- T2: code lock (1-bit). assessed once per code-sweep period
COMSCOPE_OUT_001: process(CLK)
begin
	if rising_edge(CLK) then
    	CS1 <= DATA6_I(13 downto 6);
		CS1_CLK <= SAMPLE6_CLK;
	    CS2 <= POWER_ACC(13 downto 6);
        CS2_CLK <= POWER_ACC_SAMPLE_CLK;
		CS3 <= DATA7_Q(1)(13 downto 6);	
		CS3_CLK <= SAMPLE7_CLK(1);
		CS4 <= DATA161_I_X(17 downto 10);	
		CS4_CLK <= SYMBOL161_CLK;
		CS5 <= DATA162_Q_X(17 downto 10);	
		CS5_CLK <= SYMBOL162_CLK;
		-- CS6 see AGC18
		CS7 <= CODE61A(1) & "0000000";
      CS7_CLK <= SAMPLE6_CLK;
		-- CS8 (see CODE_TRACKING)
		CS9 <= CCF_PHASE2_D(31 downto 24);
		CS9_CLK <= '1';
		-- CS10 (see SYMBOL_TIMING_LOOP5)
		-- clamp SNR display to avoid overflow
		if(SNR_LOCKED(SNR_LOCKED'left downto 10) = 0) then
			CS11 <= SNR_LOCKED(9 downto 2);
		else
			CS11 <= x"FF";
		end if;
		CS11_CLK <= SNR_LOCKED_SAMPLE_CLK;

		T1 <= CODE6A_START;
		T1_CLK <= '1';
		T2 <= CODE_LOCK;
		T2_CLK <= '1';
	end if;
end process;


--// simulation. send to a tab-delimited text file for subsequent (Matlab) plot.
SIM2OUTFILE_X: if(SIMULATION = '1') generate
--	Inst_SIM2OUTFILEA: SIM2OUTFILE 
--	generic map(
--		FILENAME => "ddA.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => PE,
--		DATA2 => CCF_PHASE2_D(31 downto 20),
--		DATA3 => CF_NCO_CONTROL2B(18 downto 7),
--		SAMPLE_CLK_IN => PE_SYMBOL_CLK
--	);
--
	Inst_SIM2OUTFILE81: SIM2OUTFILE 
	generic map(
		FILENAME => "d6.txt"
	)
	PORT MAP(
		CLK => CLK,
		DATA1 => DATA6_I(13 downto 2),
		DATA2 => DATA6_Q(13 downto 2),
		DATA3 => x"000",
		SAMPLE_CLK_IN => SAMPLE6_CLK
	);
	Inst_SIM2OUTFILE82: SIM2OUTFILE 
	generic map(
		FILENAME => "d82.txt"
	)
	PORT MAP(
		CLK => CLK,
		DATA1 => DATA81_I(13 downto 2),
		DATA2 => DATA81_Q(13 downto 2),
		DATA3 => CODE_LOCK & "00000000000",
		SAMPLE_CLK_IN => SAMPLE8_CLK
	);


--	Inst_SIM2OUTFILEB: SIM2OUTFILE 
--	generic map(
--		FILENAME => "ddB.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DATA_I_IN(13 downto 2),
--		DATA2 => DATA_Q_IN(13 downto 2),
--		DATA3 => x"000",
--		SAMPLE_CLK_IN => SAMPLE3_CLK
--	);
--

--	Inst_SIM2OUTFILE1: SIM2OUTFILE 
--	generic map(
--		FILENAME => "dd1.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DETECT_THRESHOLD_FL(15 downto 4),
--		DATA2 => POWER_ACC_MAX_FL(15 downto 4),
--		DATA3 => SNR_LOCKED(11 downto 0),
--		SAMPLE_CLK_IN => POWER_ACC_MAX_FL_SAMPLE_CLK
--	);

--	Inst_SIM2OUTFILE2: SIM2OUTFILE 
--	generic map(
--		FILENAME => "dd2.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DETECT_THRESHOLD(15 downto 4),
--		DATA2 => POWER_AVERAGE_D(15 downto 4),
--		DATA3 => POWER_ACC_MAX(15 downto 4),
--		SAMPLE_CLK_IN => POWER_ACC_MAX_SAMPLE_CLK
--	);

--	Inst_SIM2OUTFILE3: SIM2OUTFILE 
--	generic map(
--		FILENAME => "dd3.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DATA131B_I(13 downto 2),
--		DATA2 => DATA131B_Q(13 downto 2),
--		DATA3 => x"000",
--		SAMPLE_CLK_IN => SAMPLE131B_CLK
--	);
--
--	Inst_SIM2OUTFILE41: SIM2OUTFILE 
--	generic map(
--		FILENAME => "dd41.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DATA141_I(13 downto 2),
--		DATA2 => DATA141_Q(13 downto 2),
--		DATA3 => x"000",
--		SAMPLE_CLK_IN => SAMPLE141_CLK
--	);
--	
--	Inst_SIM2OUTFILE42: SIM2OUTFILE 
--	generic map(
--		FILENAME => "dd42.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DATA142_I(13 downto 2),
--		DATA2 => DATA142_Q(13 downto 2),
--		DATA3 => x"000",
--		SAMPLE_CLK_IN => SAMPLE142_CLK
--	);
	
--	Inst_SIM2OUTFILE51: SIM2OUTFILE 
--	generic map(
--		FILENAME => "dd51.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DATA151_I,
--		DATA2 => DATA151_Q,
--		DATA3 => CCF_PHASE2_D(31 downto 20),
--		SAMPLE_CLK_IN => SYMBOL151_CLK
--	);
--
--	Inst_SIM2OUTFILE52: SIM2OUTFILE 
--	generic map(
--		FILENAME => "dd52.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DATA152_I,
--		DATA2 => DATA152_Q,
--		DATA3 => CCF_PHASE2_D(31 downto 20),
--		SAMPLE_CLK_IN => SYMBOL152_CLK
--	);

--	Inst_SIM2OUTFILE161: SIM2OUTFILE 
--	generic map(
--		FILENAME => "dd161.txt"
--	)
--	PORT MAP(
--		CLK => CLK,
--		DATA1 => DATA161_I_X(17 downto 6),
--		DATA2 => DATA161_Q_X(17 downto 6),
--		DATA3 => ST_PHASE_ACC1(31 downto 20),
--		SAMPLE_CLK_IN => SAMPLE161_CLK
--	);

end generate;



end behavioral;
