-------------------------------------------------------------
-- MSS copyright 2014-2022
-- Filename:  COM1826_TOP.VHD
-- Authors: 
--		Alain Zarembowitch / MSS
-- Version: Rev 14a
-- Last modified: 1/9/22
-- Inheritance: 	COM1518 rev 004c 6/27/14, COM-5401, COM-5402
--
-- description:  Top level for COM-1528 TDRSS DAS receiver when ported to the COM-1800 FPGA development platform.
--
-- Rev 3 12/4/14 AZ
-- Added bad UDP frame filter
-- Added SDDS rx overflow condition / wptr can no longer pass rptr
-- Simplify SDDS rx abnormal conditions (odd/even alignment was flawed)
--
-- Rev3b 12/13/14 AZ
-- rephrased UDP_RX (synthesis behaved differently than simulation, wrong UDP checksum valid)
-- SYNTHESIS CONFIGURATION: to be safe, keep equivalent registers + disable resource sharing. Can't hurt.
--
-- Rev4a 12/27/14 AZ
-- Added IGMP for receiving multicast UDP frames
--
-- Rev4b 1/7/15 AZ
-- udp port moved to -- port 29495
-- IGMP membership registration after a config change
--
-- Rev5e 3/18/15 AZ
-- periodic IGMP membership registration every 102.4 seconds
--
-- Rev5f 4/11/15 AZ
-- Added simulated CLK_TCXOg (otherwise no reset during simulation)
-- added convolutional encoders for a more comprehensive test mode
--
-- Rev6f 12/10/15 AZ
-- More reliable LAN start (reset PHY longer at power up)
-- Removed (most) ASYNC_RESET in COM-5402SOFT because synthesis was complaining about the timing
--
-- Rev7a 12/12/15 AZ
-- Interfaces to/from external DACs and ADCs
--
-- Rev7b 12/16/15 AZ
-- switched to numeric_std library
-- bram_dp2
-- 2 additional tcp ports as modulator inputs
-- CIC_R input
--
-- Rev7g 1/16/16 AZ
-- switched to NRAMB2. More protection against bad rx UDP frames. Tested M&C connection reliability (see Java test code)
-- 
-- Rev8a 2/2/16 AZ
-- modified CIC.vhd for simulation
-- simulation in generic section of NCO32X
-- AGC18 target magnitude in demod for better normalization (same as in com-1831)
--
-- Rev9a 3/6/16 AZ
-- Added alternating I/Q modulation mode and 1/2 symbol Q modulation delay
-- Corrected bug with fast frequency detection (new rev)
--
-- Rev9b 3/17/16 AZ
-- Corrected statement in external ADC input mux
-- Adjusted .xdc drive for output clocks to ADCs and DACs (marginal)
--
-- Rev10c 5/17/16 AZ
-- Add SDDS-formatted input file for simulation
--
-- Rev11a 5/24/16
-- Updated IP stack
-- Better FFT for SQPN 
--
-- Rev11e 6/6/16 AZ
-- 2 distinct SNR measurements for I and Q channels. 
-- faster AWGN.vhd component
--
-- Rev 12b 7/28/16 AZ
-- For higher reliability of GbE timing, swap the functions of the connectorized COM-5401 Ethernet LAN and the 
-- built-in Ethernet LAN.
-- Updated AGC18 for larger input dynamic range
--
-- Rev 12c 8/4/16 AZ
-- account for 1/2 chip Q-code delay during parallel acquisition (previously only done during despreading/tracking phase)
-- corrected modulator 1/2 chip Q-code delay
-- moved LAN address LSB to REG236 (previously REG0)
-- LAN PHY reset only when changing LAN address through REG236 
--
-- Rev 12e 11/15/16 AZ
-- rephrased FT_PLAYBACK for better timing (TBC)
-- clean .xdc
-- Corrected bug with unwarranted 1/2 chip Q-code delay in despread_id.vhd (input Q-code is already delayed by 1/2 chip in dsss_demod_tdrss above)
--
-- Rev 12g 11/27/16 AZ
-- NOMINAL_CHIP_RATE_DYNAMIC: Demodulator chip rate is corrected by dynamic frequency table (scaled down by 2.2875 GHz / 3.077799 Mchips/s)
--
-- Rev 13b 2/21/17 AZ
-- Updated the COM5402 IP stack
-- Updated ComScope2 for 3rd trace
-- Changed synth settings (resource sharing, do not keep equivalent registers)
-- Simplified symbol NCO in demod (x2 oversampling, instead of x4 previously)
-- Corrected NCO32X anomaly at 122Kbps and 61Kbps.
--
-- Rev 13c 4/11/17 AZ
-- SDDS_RX: Generate a timetag for each I/Q complex sample: the first one in a SDDS frame is read from the frame header,
-- the subsequent 255 timetags are linearly interpolated (not used at this stage)
-- Corrected wrong ST loop gain (bug in 13b).
--
-- Rev 13d 7/21/17 AZ
-- Added mechanism to synchronize two Viterbi decoders in the case of SQPN alternating I/Q bits [JM discrepancy report]
--
-- Rev14b 1/9/21 AZ
-- Editorial + added options -C/-D (COM-4009 + COM-30XX) interfaces
-- changed RECEIVER1 AGC mode to both because COM-3010 receiver does not have internal AGC
---------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.com5402pkg.all;	-- defines global types, number of TCP streams, etc
Library UNISIM;
use UNISIM.vcomponents.all;

entity COM1826_TOP is
	generic (
	   -- the code is written for three configurations
	   -- 1. demodulator with SDDS input over GbE  COM-5102 - COM-1826
	   --   OPTION A or B + MODULATOR disabled + DEMODULATOR enabled + ADC disabled + DAC disabled + AWGN disabled
	   -- 2. RF receiver or modem: COM-1826 + COM-3504 + COM-3506. No SDDS GbE input
	   --   OPTION A or B + DEMODULATOR enabled + ADC enabled + MODULATOR (optional) + DAC (optional) + AWGN (optional)
	   -- 3. RF receiver or modem: COM-30XX + COM-1826 + COM-4009. No SDDS GbE input
	   --   OPTION C or D + DEMODULATOR enabled + ADC enabled + MODULATOR (optional) + DAC (optional) + AWGN (optional)
	
	
		--OPTION: std_logic_vector(7 downto 0) := x"41";    -- 'A'    -- internal VCTCXO reference 19.2MHz, COM-3504 dual A/D + D/A converters (right connector)
		OPTION: std_logic_vector(7 downto 0) := x"42";    -- 'B'    -- external 10 MHz reference  OR COM1826_TOP stand-alone simulation, , COM-3504 dual A/D + D/A converters on right side
		--OPTION: std_logic_vector(7 downto 0) := x"43";    -- 'C'    -- VCTCXO reference, COM-4009 RF modulator (right connector), COM-30XX RF receiver (left connector)
		--OPTION: std_logic_vector(7 downto 0) := x"44";    -- 'D'    -- external 10 MHz reference, COM-4009 RF modulator (right connector), COM-30XX RF receiver (left connector)
		REVISION: std_logic_vector(7 downto 0) := x"45";    -- 'E=14'
			--// FPGA option and revision (ASCII format '0' = x30, 'A' = x41)
			-- These two ASCII characters appear in the Comblock Control Center.
			-- Helpful in identifying which firmware version is currently running in the FPGA. 
			-- Select internal vs external frequency reference option. 
			-- REMINDER: do change the .xdc file according to the option selection -A or -B
		MODULATOR_EN: std_logic := '1';
			-- instantiate (1)/do not instantiate (0) a built-in modulator
		DEMODULATOR_EN: std_logic := '1';
			-- instantiate (1)/do not instantiate (0) a built-in demodulator
		ADCs_EN: std_logic := '1';
			-- instantiate (1)/do not instantiate (0) the demodulator input path from external ADCs, in addition to the baseline SDDS input
		DACs_EN: std_logic := '1';
			-- instantiate (1)/do not instantiate (0) the modulator output path to external DACs
		AWGN_EN: std_logic := '1';
			-- additive white Gaussian noise. Usually disabled to save space in FPGA
		SIMULATION: std_logic := '0'
		-- 1 during simulation, 0 for release	
	);
    Port ( 
		--GLOBAL CLOCKS
	   CLKREF_TCXO : in std_logic;	
			-- 19.2MHz reference clock. Generated by the VCTCXO on this board.
		CLKREF25B: in std_logic;
			-- 25 MHz low-jitter, but poor stability
		CLKREF_EXT: in std_logic;
			-- external (higher-stability) frequency reference via J9 SMA connector ("EXT REF")

		--// GbE LAN. 
		-- connects to RGMII PHY (Micrel KSZ9031)
		LAN_TXC: out std_logic;  -- tx clock
		LAN_TXD: out std_logic_vector(3 downto 0);  -- tx data
		LAN_TX_CTL: out std_logic;  -- tx control: combines TX_EN and TX_ER
			-- valid at the falling clock edge
		LAN_RXC: in std_logic;  -- receive clock
			-- must be delayed by 1.5 to 2.1 ns to prevent glitches
			-- Set the strapping options in the .xdc constraint file.
		LAN_RXD: in std_logic_vector(3 downto 0);  
			-- receive data
			-- Set the strapping options in the .xdc constraint file.
		LAN_RX_CTL: in std_logic;  -- receive control. combines RX_DV and RX_ER
			-- valid at the falling clock edge
			-- Note: Micrel KSZ9021RN PHY defines these as dual-function signals.
			-- Set the strapping options in the .xdc constraint file.
		LAN_RESET_N: out std_logic;
			-- PHY reset
		LAN_MCLK: out std_logic;
		LAN_MDIO: inout std_logic;  -- (tri-state)
		LAN_CLK125: in std_logic;   -- optional 125 MHz from PHY
		LAN_INT_N: in std_logic;    -- unused interrupt
        
		--// Left connector, 98 pin PCIe female connector. 
		-- Pins B5,B20,B31,B42 reserved for Ground
		-- Pins A49/B49 reserved for ComBlock Monitoring and Control.
		-- Place B13 in high-impedance when using the 12-bit DAC or vice versa.
		LEFT_CONNECTOR_A: inout std_logic_vector(26 downto 1);
		LEFT_CONNECTOR_B1: inout std_logic_vector(4 downto 1);
		LEFT_CONNECTOR_B2: inout std_logic_vector(16 downto 6);

		--// Right connector: 98 pin PCIe female connector.   
		-- Pins B5,B20,B31,B42 reserved for Ground
		-- Pins A49/B49 reserved for ComBlock Monitoring and Control.
		-- Connector pins A39 - A48, B40,B41,B43-B48 can be used by 
		-- re-routing LEFT_CONNECTOR signals using a resistor array (requires soldering)
		-- See schematics for details.
		RIGHT_CONNECTOR_A: inout std_logic_vector(38 downto 1);
		RIGHT_CONNECTOR_B1: inout std_logic_vector(4 downto 1);
		RIGHT_CONNECTOR_B2: inout std_logic_vector(19 downto 6);
		RIGHT_CONNECTOR_B3: inout std_logic_vector(30 downto 21);
		RIGHT_CONNECTOR_B4: inout std_logic_vector(39 downto 32);

		--// DAC AD5621 IC interface (receiver AGC, drives LEFT_CONNECTOR_B2(13) unless in high impedance)
		DAC_SYNC_B: out std_logic;
		DAC_SCLK: out std_logic;
		DAC_SDIN: out std_logic;

		--// Monitoring & Control: ARM Cortex M3 microcontroller interface
		-- asynchronous bus (shared with NAND flash)
		-- set address at the rising edge of UC_WEB_IN when UC_CSIB_IN = '0' and UC_ALE_IN = '1'
		-- write data the rising edge of UC_WEB_IN when UC_CSIB_IN = '0'
		-- read data when  UC_CSIB_IN = '0' and UC_REB_IN = '0'
		UC_CSIB_IN: in std_logic;  -- chip select. active low.
		UC_ALE_IN: in std_logic;  -- address latch enable. active high.
		UC_REB_IN: in std_logic;  -- read enable #
		UC_WEB_IN: in std_logic;	-- write enable #
		UC_AD: inout std_logic_vector(7 downto 0)  -- shared address/data bus

		  
			  );
end entity;

architecture Behavioral of COM1826_TOP is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
-- Comment in/out components/drivers as needed
	COMPONENT CLKGEN7_MMCM_ADJ
	GENERIC (
        CLKFBOUT_MULT_F: real;
        CLKOUT0_DIVIDE_F: real;
        CLKIN1_PERIOD: real
    );    
    PORT(
        CLK_IN1 : IN std_logic;
        CLK_OUT1 : OUT std_logic;
        INPUT_CLK_STOPPED : OUT std_logic;
        LOCKED : OUT std_logic
        );
    END COMPONENT;

	COMPONENT TIMER_4US
	GENERIC (
		CLK_FREQUENCY: integer 
	);
	PORT(
		CLK : IN std_logic;          
		SYNC_RESET : IN std_logic;
		TICK_4US : OUT std_logic;
		TICK_100MS: out std_logic
		);
	END COMPONENT;

	COMPONENT BRAM_DP2
    GENERIC(
		DATA_WIDTHA: integer;
		ADDR_WIDTHA: integer;
		DATA_WIDTHB: integer;
		ADDR_WIDTHB: integer
    );
    PORT(
		CSA : IN std_logic;
		CLKA   : in  std_logic;
		WEA    : in  std_logic;
		OEA : IN std_logic;
		ADDRA  : in  std_logic_vector(ADDR_WIDTHA-1 downto 0);
		DIA   : in  std_logic_vector(DATA_WIDTHA-1 downto 0);
		DOA  : out std_logic_vector(DATA_WIDTHA-1 downto 0);
		CSB : IN std_logic;
		CLKB   : in  std_logic;
		WEB    : in  std_logic;
		OEB : IN std_logic;
		ADDRB  : in  std_logic_vector(ADDR_WIDTHB-1 downto 0);
		DIB   : in  std_logic_vector(DATA_WIDTHB-1 downto 0);
		DOB  : out std_logic_vector(DATA_WIDTHB-1 downto 0)
        );
    END COMPONENT;

	COMPONENT DAC_AD5621
	generic (
		CLK_FREQUENCY: integer 
	);
	PORT(
		CLK : IN std_logic;
		DATA_IN : IN std_logic_vector(11 downto 0);
		DATA_IN_CLK : IN std_logic;
		OP_MODE : IN std_logic_vector(1 downto 0);          
		DONE : OUT std_logic;
		SYNC_B : OUT std_logic;
		SCLK : OUT std_logic;
		SDIN : OUT std_logic
		);
	END COMPONENT;

	COMPONENT CROSS_CLK_DOMAINS is
	generic (
		NBITS: in integer
	);
	PORT(
		CLK_A : in std_logic;				-- 'from' clock domain
		CLK_B : in std_logic;				-- 'to' clock domain
		ASYNC_RESET: in std_logic;
		DATA_IN: in std_logic_vector((NBITS-1) downto 0);
		DATA_OUT: out std_logic_vector((NBITS-1) downto 0)
	);
	END COMPONENT;

	COMPONENT COM1826
	GENERIC (
		BER_EN: std_logic;
		SIMULATION: std_logic
	);
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		ADC_DATA_I_IN : IN std_logic_vector(13 downto 0);
		ADC_DATA_Q_IN : IN std_logic_vector(13 downto 0);
		ADC_SAMPLE_CLK_IN : IN std_logic;
		AGC_RESPONSE : IN std_logic_vector(4 downto 0);
		RECEIVER_CENTER_FREQ : IN std_logic_vector(31 downto 0);
		NOMINAL_CHIP_RATE : IN std_logic_vector(31 downto 0);
	   CIC_R: in std_logic_vector(15 downto 0);    
		NOMINAL_SYMBOL_RATE1: in std_logic_vector(31 downto 0);
		NOMINAL_SYMBOL_RATE2: in std_logic_vector(31 downto 0);
		SPREADING_FACTOR1 : IN std_logic_vector(12 downto 0);
		SPREADING_FACTOR2 : IN std_logic_vector(12 downto 0);
		LFSRA_INIT: in std_logic_vector(10 downto 0);
		LFSRC_INIT: in std_logic_vector(10 downto 0);
		CODE_MODE: in std_logic;
		FREQ_SCAN_N_COARSE_STEPS : IN std_logic_vector(7 downto 0);
		DEMOD_CONTROL : IN std_logic_vector(15 downto 0);
		RESET_DEMOD_IN_FALSE_LOCK : IN std_logic;          
		AGC_DAC : OUT std_logic_vector(11 downto 0);
		AGC_DAC_SAMPLE_CLK : OUT std_logic;
		DATA_I_OUT: out std_logic_vector(7 downto 0);
		DATA_Q_OUT: out std_logic_vector(7 downto 0);
		SAMPLE_I_CLK_OUT: out std_logic;
		SAMPLE_Q_CLK_OUT: out std_logic;
		SYNC_PULSE : OUT std_logic;
		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);
		CARRIER_FREQUENCY_ERROR2 : OUT std_logic_vector(31 downto 0);
		POWER_S_AVERAGE_OUT : OUT std_logic_vector(17 downto 0);
		POWER_N_AVERAGE_OUT : OUT std_logic_vector(17 downto 0);
		SNR1_LOCKED_OUT : OUT std_logic_vector(17 downto 0);
		SNR2_LOCKED_OUT : OUT std_logic_vector(17 downto 0);
		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;
		BER_SYNC : OUT std_logic;
		BER_ERROR_COUNT : OUT std_logic_vector(31 downto 0);
		BYTE_ERROR : OUT std_logic;
		CS0 : OUT std_logic_vector(7 downto 0);
		CS0_CLK : 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;
		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;
		TP : OUT std_logic_vector(20 downto 1)
		);
	END COMPONENT;

   COMPONENT VITERBI_DECODER
	GENERIC(
		K_MAX: integer;	
		N_PARITY_BITS_MAX: integer;
		NDEC: integer;  
		HARD_SOFTN_DECISION: std_logic;
		TB_DEPTH: integer;	
		SIMULATION: std_logic
	);
   PORT(
		CLK : IN  std_logic;
		SYNC_RESET : IN  std_logic;
		DATAIN: in std_logic_vector(31 downto 0);
		DATAIN_VALID : IN  std_logic;
		DATAIN_READY : OUT  std_logic;
		SKIP1BIT_PULSE: in std_logic;
		SYNC_CONTROL: in std_logic;
		G: in std_logic_vector(62 downto 0);  
		N_PARITY_BITS: in integer range 2 to 7;
		K: in integer range 3 to 9;
		R1: in integer range 1 to 7;
		R2: in integer range 2 to 8;
		STANDARD: in integer range 0 to 2;
		DIFF_ENC_ON: in std_logic;
		HIGH_SNR: in std_logic;
        FEC_G1_INVERSION: in std_logic;
		DATAOUT1b: out std_logic;
		DATAOUT1b_VALID: out std_logic;
		DATAOUT8b: out std_logic_vector(7 downto 0);
		DATAOUT8b_VALID: out std_logic;
		BER: out std_logic_vector(23 downto 0);
		BER_VALID : OUT  std_logic;
		BIT_ERROR: out std_logic;
		IN_SYNC: out std_logic;
		OUT_OF_SYNC : OUT  std_logic;
		LOCK_STATUS: out std_logic
        );
    END COMPONENT;

	COMPONENT BER2
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA_IN : IN std_logic_vector(7 downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		CONTROL : IN std_logic_vector(7 downto 0);          
		MF_DETECT : OUT std_logic;
		MF_DETECT_CONFIRMED : OUT std_logic;
		SYNC_LOCK : OUT std_logic;
		BYTE_ERROR : OUT std_logic;
		DATA_REPLICA : OUT std_logic_vector(7 downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		BER : OUT std_logic_vector(31 downto 0);
		BER_SAMPLE_CLK : OUT std_logic;
		TP : OUT std_logic_vector(10 downto 1)
		);
	END COMPONENT;

	COMPONENT STREAM_2_PACKETS2
	GENERIC (
		NBUFS: integer;
		TIMEOUT: integer range 1 to 262144;
		MAX_PACKET_SIZE: std_logic_vector(13 downto 0);
		SIMULATION: std_logic
	);
	PORT(
		SYNC_RESET : IN std_logic;
		CLK : IN std_logic;
		TICK_4us : IN std_logic;
		DATA_IN : IN std_logic_vector(7 downto 0);
		DATA_VALID_IN : IN std_logic;
		PREAMBLE_IN : IN std_logic_vector(111 downto 0);
		CTS_IN : IN std_logic;
		ACK_IN : IN std_logic;
		NAK_IN : IN std_logic;          
		RTS_OUT: out std_logic;	
		CTS_OUT : OUT std_logic;
		PACKET_TX_PULSE : OUT std_logic;
		DATA_OUT : OUT std_logic_vector(7 downto 0);
		DATA_VALID_OUT : OUT std_logic;
		SOF_OUT : OUT std_logic;
		EOF_OUT : OUT std_logic;
		TP : OUT std_logic_vector(10 downto 1)
		);
	END COMPONENT;

	COMPONENT COM5401
	GENERIC (
		MII_SEL: std_logic;  
		PHY_ADDR: std_logic_vector(4 downto 0);
		CLK_FREQUENCY: integer; 
		PLATFORM: integer;
		TARGET_PHY: integer;
		NO_1000: std_logic;	
		INTERNAL_PHY_TX_CLKS_DELAYS: std_logic;
		INTERNAL_PHY_RX_CLKS_DELAYS: std_logic;
		SIMULATION: std_logic
	);
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		CLK125_0: in std_logic;
		CLK125_1: in std_logic;
		CLK25: in std_logic;	
		MAC_TX_CONFIG : IN std_logic_vector(15 downto 0);
		MAC_RX_CONFIG : IN std_logic_vector(15 downto 0);
		MAC_ADDR : IN std_logic_vector(47 downto 0);
		PHY_CONFIG_CHANGE : IN std_logic;
		PHY_RESET : IN std_logic;
		SPEED : IN std_logic_vector(1 downto 0);
		DUPLEX : IN std_logic;
		TEST_MODE : IN std_logic_vector(1 downto 0);
		POWER_DOWN : IN std_logic;
		CLK_SKEW1: in std_logic_vector(15 downto 0);
		CLK_SKEW2: in std_logic_vector(15 downto 0);
		MAC_TX_DATA : IN std_logic_vector(7 downto 0);
		MAC_TX_DATA_VALID : IN std_logic;
		MAC_TX_EOF : IN std_logic;
		MAC_RX_CTS : IN std_logic;
		RXC : IN std_logic;
		RXD : IN std_logic_vector(3 downto 0);
		RX_CTL : IN std_logic;
		MII_TX_CLK : IN std_logic;
		GMII_MII_CRS : IN std_logic;
		GMII_MII_COL : IN std_logic;
		GMII_MII_RX_CLK : IN std_logic;
		GMII_MII_RXD : IN std_logic_vector(7 downto 0);
		GMII_MII_RX_DV : IN std_logic;
		GMII_MII_RX_ER : IN std_logic;    
		MDIO : INOUT std_logic;      
		MAC_TX_CTS : OUT std_logic;
		MAC_RX_DATA : OUT std_logic_vector(7 downto 0);
		MAC_RX_DATA_VALID : OUT std_logic;
		MAC_RX_SOF : OUT std_logic;
		MAC_RX_EOF : OUT std_logic;
		TXC : OUT std_logic;
		TXD : OUT std_logic_vector(3 downto 0);
		TX_CTL : OUT std_logic;
		RESET_N : OUT std_logic;
		MCLK : OUT std_logic;
		GMII_TX_CLK : OUT std_logic;
		GMII_MII_TXD : OUT std_logic_vector(7 downto 0);
		GMII_MII_TX_EN : OUT std_logic;
		GMII_MII_TX_ER : OUT std_logic;
		LINK_STATUS : OUT std_logic;
		SPEED_STATUS : OUT std_logic_vector(1 downto 0);
		DUPLEX_STATUS : OUT std_logic;
		PHY_ID: out std_logic_vector(15 downto 0);
		N_RX_FRAMES: out  std_logic_vector(15 downto 0);
		N_RX_BAD_CRCS: out  std_logic_vector(15 downto 0);
		N_RX_FRAMES_TOO_SHORT: out  std_logic_vector(15 downto 0);
		N_RX_FRAMES_TOO_LONG: out  std_logic_vector(15 downto 0);
		N_RX_WRONG_ADDR: out  std_logic_vector(15 downto 0);
		N_RX_LENGTH_ERRORS: out  std_logic_vector(15 downto 0);
		CS_CLKG: 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;
		CT1: out std_logic;
		CT1_CLK: out std_logic;
		TP: out std_logic_vector(10 downto 1)
		);
	END COMPONENT;

	COMPONENT COM5402
	GENERIC (
		NUDPTX: integer range 0 to 1;
		NUDPRX: integer range 0 to 1;
		IGMP_EN: std_logic;
		NTCPSTREAMS: integer range 0 to 255;  
		CLK_FREQUENCY: integer;
		TX_IDLE_TIMEOUT: integer range 0 to 50;	
		TCP_KEEPALIVE_PERIOD: integer;
		SIMULATION: std_logic
	);	
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		MAC_ADDR : IN std_logic_vector(47 downto 0);
		IPv4_ADDR : IN std_logic_vector(31 downto 0);
		IPv6_ADDR : IN std_logic_vector(127 downto 0);
		MULTICAST_IP_ADDR: in std_logic_vector(31 downto 0);
		SUBNET_MASK: in std_logic_vector(31 downto 0);
		GATEWAY_IP_ADDR: in std_logic_vector(31 downto 0);
		CONNECTION_RESET: in std_logic_vector((NTCPSTREAMS-1) downto 0);
		TCP_KEEPALIVE_EN: in std_logic;
		MAC_TX_CTS : IN std_logic;
		MAC_TX_RTS: out std_logic;
		MAC_RX_DATA : IN std_logic_vector(7 downto 0);
		MAC_RX_DATA_VALID : IN std_logic;
		MAC_RX_SOF : IN std_logic;
		MAC_RX_EOF : IN std_logic;          
		MAC_TX_DATA : OUT std_logic_vector(7 downto 0);
		MAC_TX_DATA_VALID : OUT std_logic;
		MAC_TX_SOF : OUT std_logic;
		MAC_TX_EOF : OUT std_logic;
		UDP_RX_DATA: out std_logic_vector(7 downto 0);
		UDP_RX_DATA_VALID: out std_logic;
		UDP_RX_SOF: out std_logic;	
		UDP_RX_EOF: out std_logic;	
		UDP_RX_DEST_PORT_NO_IN: in std_logic_vector(15 downto 0);
		CHECK_UDP_RX_DEST_PORT_NO: in std_logic;
		UDP_RX_DEST_PORT_NO_OUT: out std_logic_vector(15 downto 0);
		UDP_TX_DATA: in std_logic_vector(7 downto 0);
		UDP_TX_DATA_VALID: in std_logic;
		UDP_TX_SOF: in std_logic;	
		UDP_TX_EOF: in std_logic;	
		UDP_TX_CTS: out std_logic;	
		UDP_TX_ACK: out std_logic;	
		UDP_TX_NAK: out std_logic;	
		UDP_TX_DEST_IP_ADDR: in std_logic_vector(127 downto 0);
		UDP_TX_DEST_PORT_NO: in std_logic_vector(15 downto 0);
		UDP_TX_SOURCE_PORT_NO: in std_logic_vector(15 downto 0);
		TCP_RX_DATA: out SLV8xNTCPSTREAMStype;
		TCP_RX_DATA_VALID: out std_logic_vector((NTCPSTREAMS-1) downto 0);
		TCP_RX_RTS: out std_logic_vector((NTCPSTREAMS-1) downto 0);	-- Ready To Send
		TCP_RX_CTS: in std_logic_vector((NTCPSTREAMS-1) downto 0);	-- Clear To Send
		TCP_TX_DATA: in SLV8xNTCPSTREAMStype;
		TCP_TX_DATA_VALID: in std_logic_vector((NTCPSTREAMS-1) downto 0);
		TCP_TX_CTS: out std_logic_vector((NTCPSTREAMS-1) downto 0);	
		TCP_CONNECTED_FLAG: out std_logic_vector((NTCPSTREAMS-1) downto 0);
		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;
		TP : OUT std_logic_vector(10 downto 1)
		);
	END COMPONENT;

	COMPONENT PACKETS_2_STREAM
	GENERIC (
        NBUFS: integer
    );
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		PACKET_DATA_IN : IN std_logic_vector(7 downto 0);
		PACKET_DATA_VALID_IN : IN std_logic;
		PACKET_EOF_IN : IN std_logic;
		STREAM_CTS_IN : IN std_logic;          
		PACKET_CTS_OUT : OUT std_logic;
		STREAM_DATA_OUT : OUT std_logic_vector(7 downto 0);
		STREAM_DATA_VALID_OUT : OUT std_logic;
	    STREAM_SOF_OUT: out std_logic;
        STREAM_EOF_OUT: out std_logic;
		BAD_PACKET : OUT std_logic;
		TP : OUT std_logic_vector(10 downto 1)
		);
	END COMPONENT;

	COMPONENT SDDS_rx
	GENERIC (
		NBUFS_LOG2: integer range 0 to 7:= 0;
		SIMULATION: std_logic
	);
	PORT(
		SYNC_RESET : IN std_logic;
		CLK : IN std_logic;
		DATA_IN : IN std_logic_vector(7 downto 0);
		DATA_VALID_IN : IN std_logic;
		SOF_IN : IN std_logic;
		EOF_IN : IN std_logic;   
		CTS: out std_logic;
		DATA_I_OUT: out std_logic_vector(15 downto 0);	
		DATA_Q_OUT: out std_logic_vector(15 downto 0);	
		DATA_VALID_OUT: out std_logic;	
		SAMPLING_RATE_OUT: out std_logic_vector(31 downto 0);
		TIMETAG_OUT: out std_logic_vector(63 downto 0);
		N_MISSING_FRAMES: out  std_logic_vector(15 downto 0);
		TP : OUT std_logic_vector(10 downto 1)
		);
	END COMPONENT;

	COMPONENT ELASTIC_BUFFER_NRAMB2
	GENERIC (
		DATA_WIDTH: integer;
		ADDR_WIDTH: integer;
		READ_AHEAD_1ADDRESS: std_logic
	);	
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA_IN: in std_logic_vector((DATA_WIDTH-1) downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		SAMPLE_CLK_IN_REQ : OUT std_logic;
		DATA_OUT: out std_logic_vector((DATA_WIDTH-1) downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		SAMPLE_CLK_OUT_E : OUT std_logic;
		SAMPLE_CLK_OUT_REQ : IN std_logic;          
		BUFFER_EMPTY: out std_logic;
		USED: out std_logic_vector((ADDR_WIDTH-1) downto 0)
		);
	END COMPONENT;

	COMPONENT LFSR11P
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		SAMPLE_CLK_OUT_REQ : IN std_logic;          
		DATA_OUT : OUT std_logic_vector(7 downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		SOF_OUT : OUT std_logic
		);
	END COMPONENT;

	COMPONENT P8_TO_S1_CONVERSION
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA8_IN : IN std_logic_vector(7 downto 0);
		SAMPLE8_CLK_IN : IN std_logic;
		SAMPLE1_CLK_OUT_REQ : IN std_logic;          
		SAMPLE8_CLK_IN_REQ : OUT std_logic;
		DATA1_OUT : OUT std_logic;
		SAMPLE1_CLK_OUT : OUT std_logic;
		BUF_EMPTY : OUT std_logic
		);
	END COMPONENT;

	COMPONENT NRZ1
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA_IN : IN std_logic;
		DATA_VALID_IN : IN std_logic;
		CONTROL : IN std_logic_vector(2 downto 0);          
		DATA_OUT : OUT std_logic;
		DATA_VALID_OUT : OUT std_logic
		);
	END COMPONENT;

	COMPONENT ENCODER_ROOT
	PORT(
		CLK : IN std_logic;
		ASYNC_RESET : IN std_logic;
		DATA_IN : IN std_logic;
		SAMPLE_CLK_IN : IN std_logic;
		SOF_RESET : IN std_logic;
		SAMPLE_CLK_OUT_REQ : IN std_logic;
		CONTROL : IN std_logic_vector(15 downto 0);          
		SAMPLE_CLK_IN_REQ : OUT std_logic;
		DATA_OUT : OUT std_logic_vector(3 downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		TP : OUT std_logic_vector(4 downto 0)
		);
	END COMPONENT;

	COMPONENT DSSS_MODULATOR_TDRSS
	GENERIC (
        SIMULATION: std_logic
    );
	PORT(
		CLK: in std_logic;
        SYNC_RESET: in std_logic;
        TX_DATA: in std_logic_vector(1 downto 0);
        TX_DATA_SAMPLE_CLK: in std_logic_vector(1 downto 0);
        TX_CTS: out std_logic_vector(1 downto 0);    
        CHIP_RATE: in std_logic_vector(31 downto 0);
        SYMBOL_RATE1: in std_logic_vector(31 downto 0);
        SYMBOL_RATE2: in std_logic_vector(31 downto 0);
        LFSRA_INIT: in std_logic_vector(10 downto 0);
        LFSRC_INIT: in std_logic_vector(10 downto 0);
		  CODE_MODE: in std_logic;
        CODE_START_OUT: out std_logic;
        GAIN: in std_logic_vector(15 downto 0);
        CENTER_FREQ: in std_logic_vector(31 downto 0);
        SINE_FREQ_OFFSET_AMPLITUDE: in std_logic_vector(31 downto 0);
        SINE_FREQ_OFFSET_FREQUENCY: in std_logic_vector(31 downto 0);
        CONTROL: in std_logic_vector(15 downto 0);
        CONFIG_CHANGE_TOGGLE: in std_logic;
        DATA_I_OUT : OUT std_logic_vector(17 downto 0);
        DATA_Q_OUT : OUT std_logic_vector(17 downto 0);
        SATURATION: out std_logic;
        TP: out std_logic_vector(10 downto 1)
		);
	END COMPONENT;	

	COMPONENT AWGN
	PORT(
		CLK : IN std_logic;
		SAMPLE_CLK_REQ : IN std_logic;
		SYNC_RESET : IN std_logic;          
		SAMPLE_CLK_OUT : OUT std_logic;
		NOISE_SAMPLE1_OUT : OUT std_logic_vector(15 downto 0);
		NOISE_SAMPLE2_OUT : OUT std_logic_vector(15 downto 0)
		);
	END COMPONENT;

	COMPONENT POWER_MEASUREMENT
	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 AUX_DACS_ADC
	generic (
		CLK_FREQUENCY: integer 
	);
	PORT(
		CLK : IN std_logic;
		ASYNC_RESET : IN std_logic;
		AUXDAC1_DIN : IN std_logic_vector(11 downto 0);
		AUXDAC2_DIN : IN std_logic_vector(11 downto 0);    
		AUXADC1_DOUT : OUT std_logic_vector(11 downto 0);
		TIMESLOTS_AUXDAC1: in std_logic_vector(15 downto 0);
		TIMESLOTS_AUXDAC2: in std_logic_vector(15 downto 0);
		TIMESLOTS_AUXADC1: in std_logic_vector(15 downto 0);
		AUX_SPI1 : INOUT std_logic;      
		AUX_SPI2 : OUT std_logic;
		AUX_SPI3 : OUT std_logic;
		AUX_SPI4 : OUT std_logic;
		AUX_SPI5 : OUT std_logic
		);
	END COMPONENT;

 	COMPONENT DNA_ID
	GENERIC (
		CLK_FREQUENCY: integer
	);	
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;          
		ID_OUT : OUT std_logic_vector(56 downto 0) := (others => '0');
		ID_VALID_OUT : OUT std_logic;
		ID_SAMPLE_CLK_OUT : OUT std_logic
		);
	END COMPONENT;

	COMPONENT COMSCOPE2
	generic (
		TRACE1_ENABLED: std_logic;	
		TRACE2_ENABLED: std_logic;	
		TRACE3_ENABLED: std_logic;	
		TRACE4_ENABLED: std_logic;
		DATA_WIDTH1A: integer;
		ADDR_WIDTH1A: integer;
		ADDR_WIDTH1B: integer;
		DATA_WIDTH2A: integer;
		ADDR_WIDTH2A: integer;
		ADDR_WIDTH2B: integer;
		DATA_WIDTH3A: integer;
		ADDR_WIDTH3A: integer;
		ADDR_WIDTH3B: integer;
		DATA_WIDTH4A: integer;
		ADDR_WIDTH4A: integer;
		ADDR_WIDTH4B: integer
	);	
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		REG238 : IN std_logic_vector(7 downto 0);
		REG239 : IN std_logic_vector(7 downto 0);
		REG240 : IN std_logic_vector(7 downto 0);
		REG241 : IN std_logic_vector(7 downto 0);
		REG242 : IN std_logic_vector(7 downto 0);
		REG243 : IN std_logic_vector(7 downto 0);
		REG244 : IN std_logic_vector(7 downto 0);
		REG245 : IN std_logic_vector(7 downto 0);
		REG246 : IN std_logic_vector(7 downto 0);
		REG247 : IN std_logic_vector(7 downto 0);
		REG248 : IN std_logic_vector(7 downto 0);
		REG249 : IN std_logic_vector(7 downto 0);
		S1_1 : IN std_logic_vector(7 downto 0);
		S1_1_VALID : IN std_logic;
		S1_2 : IN std_logic_vector(7 downto 0);
		S1_2_VALID : IN std_logic;
		S1_3 : IN std_logic_vector(7 downto 0);
		S1_3_VALID : IN std_logic;
		S1_4 : IN std_logic_vector(7 downto 0);
		S1_4_VALID : IN std_logic;
		S2_1 : IN std_logic_vector(7 downto 0);
		S2_1_VALID : IN std_logic;
		S2_2 : IN std_logic_vector(7 downto 0);
		S2_2_VALID : IN std_logic;
		S2_3 : IN std_logic_vector(7 downto 0);
		S2_3_VALID : IN std_logic;
		S2_4 : IN std_logic_vector(7 downto 0);
		S2_4_VALID : IN std_logic;
		S3_1 : IN std_logic_vector(7 downto 0);
		S3_1_VALID : IN std_logic;
		S3_2 : IN std_logic_vector(7 downto 0);
		S3_2_VALID : IN std_logic;
		S3_3 : IN std_logic_vector(7 downto 0);
		S3_3_VALID : IN std_logic;
		S3_4 : IN std_logic_vector(7 downto 0);
		S3_4_VALID : IN std_logic;
		S4_1 : IN std_logic_vector(7 downto 0);
		S4_1_VALID : IN std_logic;
		S4_2 : IN std_logic_vector(7 downto 0);
		S4_2_VALID : IN std_logic;
		S4_3 : IN std_logic_vector(7 downto 0);
		S4_3_VALID : IN std_logic;
		S4_4 : IN std_logic_vector(7 downto 0);
		S4_4_VALID : IN std_logic;
		T16b_1 : IN std_logic_vector(15 downto 0);
		T16b_1_VALID : IN std_logic;
		T16b_2 : IN std_logic_vector(15 downto 0);
		T16b_2_VALID : IN std_logic;
		T16b_3 : IN std_logic_vector(15 downto 0);
		T16b_3_VALID : IN std_logic;
		T16b_4 : IN std_logic_vector(15 downto 0);
		T16b_4_VALID : IN std_logic;
		TRIGGER_REARM_TOGGLE : IN std_logic;
		FORCE_TRIGGER_TOGGLE : IN std_logic;
		SREG250_READ_TOGGLE : IN std_logic;
		START_CAPTURE_TOGGLE : IN std_logic;          
		SREG250 : OUT std_logic_vector(7 downto 0);
		SREG251 : OUT std_logic_vector(7 downto 0);
		TP: out std_logic_vector(16 downto 1)
		);
	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 _X 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

-- number of TCP streams in IP stack #1 depends on the OPTION
function f_nctp1(OPTION: std_logic_vector(7 downto 0)) return integer is
variable retval: integer;
begin
	if(OPTION = x"41") or (OPTION = x"42") then
		retval := 1;  -- IP stack #1/LAN2 (GbE) used for SDDS rx only
	--elsif(OPTION = x"43") or (OPTION = x"44") then
	else
		retval := 5;  -- IP stack #1/LAN2 (GbE) used for all TCP & UDP traffic
	end if;
	return retval;
end function;


--// CLOCKS, RESETS
signal CLKREF_TCXOg: std_logic := '0';
--signal CLKREF25Bg: std_logic := '0';
--signal CLKREF25Cg: std_logic := '0';
--signal PLL25_CLKFB: std_logic := '0';
--signal PLL25_LOCKED: std_logic := '0';
signal CLKGEN7C_INPUT_CLK_STOPPED: std_logic := '0';
signal CLKGEN7C_LOCKED: std_logic := '0';
signal CLKGEN7D_INPUT_CLK_STOPPED: std_logic := '0';
signal CLKGEN7D_LOCKED: std_logic := '0';
signal CLKFB7D: std_logic := '0';
signal CLK125_0: std_logic := '0';
signal CLK125_1: std_logic := '0';
signal CLK125_2: std_logic := '0';
signal CLK25: std_logic := '0';
signal CLK10: std_logic := '0';
signal CLK10g: std_logic := '0';
signal CLKREF_EXTg: std_logic := '0';
constant CLK_FREQUENCY: integer := 125; -- processing clock frequency CLK_P in MHz, as time reference
signal CLK_RX: std_logic := '0';
signal CLK_RXg: std_logic := '0';
signal TICK_100MS: std_logic := '0';
signal TICK_1S: std_logic := '0';
signal TICK_4US: std_logic := '0';
signal TICK_100MS_CNTR: unsigned(3 downto 0) := (others => '0');
signal RESET_COUNTER: unsigned(23 downto 0) := (others => '0');
	-- spans 2^23/10MHz = 838ms
signal PLLE2_RST: std_logic := '0';
signal RESET_STATE: integer range 0 to 1 := 0;
signal ASYNC_RESET: std_logic := '1';
signal CLK_P: std_logic := '0';
signal CLK_P_FB: std_logic := '0';
signal CLK_P_DIV2: std_logic := '0';
signal SYNC_RESET_CLK_P: std_logic := '0';
signal ASYNC_RESET_D: std_logic := '0';
signal ASYNC_RESET_D2: std_logic := '0';
	-- asynchronous reset
signal READY_FLAG_CLK_P: std_logic := '0';
signal READY_FLAG_CLK_Pn: std_logic := '0';

--//-- ETHERNET MAC#1-----------------------------------
signal LAN1_AVAILABLE: std_logic := '0';
signal CLK_SKEW11: std_logic_vector(15 downto 0) := (others => '0');
signal CLK_SKEW12: std_logic_vector(15 downto 0) := (others => '0');
signal LAN1_MAC_ADDR: std_logic_vector(47 downto 0) := (others => '0');
signal LAN1_TXC: std_logic:= '0';  -- tx clock
signal LAN1_TXD: std_logic_vector(3 downto 0) := (others => '0');  -- tx data
signal LAN1_TX_CTL: std_logic:= '0';  -- tx control: combines TX_EN and TX_ER
			-- valid at the falling clock edge
signal LAN1_RXC: std_logic:= '0';  -- receive clock
			-- must be delayed by 1.5 to 2.1 ns to prevent glitches
signal LAN1_RXD: std_logic_vector(3 downto 0) := (others => '0');  -- receive data
signal LAN1_RX_CTL: std_logic:= '0';  -- receive control. combines RX_DV and RX_ER
			-- valid at the falling clock edge
			-- Note: Micrel KSZ9021RN PHY defines these as dual-function signals.
			-- Set the strapping options in the .xdc constraint file.
signal LAN1_RESET_N: std_logic:= '0';
			-- PHY reset
signal LAN1_MCLK: std_logic:= '0';
signal LAN1_TP: std_logic_vector(10 downto 1) := (others => '0');
signal LAN1_PHY_ID: std_logic_vector(15 downto 0) := (others => '0');
signal LAN1_MAC_RX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal LAN1_MAC_RX_DATA_VALID: std_logic:= '0';
signal LAN1_MAC_RX_SOF: std_logic:= '0';
signal LAN1_MAC_RX_EOF: std_logic:= '0';
signal LAN1_MAC_TX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal LAN1_MAC_TX_DATA_VALID: std_logic:= '0';
signal LAN1_MAC_TX_EOF: std_logic:= '0';
signal LAN1_MAC_TX_CTS: std_logic:= '0';
signal LAN1_LINK_STATUS: std_logic:= '0';
signal LAN1_SPEED_STATUS: std_logic_vector(1 downto 0) := (others => '0');
signal LAN1_DUPLEX_STATUS: std_logic:= '0';
signal LAN1_N_RX_FRAMES:  std_logic_vector(15 downto 0);
signal LAN1_N_RX_BAD_CRCS:  std_logic_vector(15 downto 0);
signal LAN1_N_RX_FRAMES_TOO_SHORT:  std_logic_vector(15 downto 0);
signal LAN1_N_RX_FRAMES_TOO_LONG:  std_logic_vector(15 downto 0);
signal LAN1_N_RX_WRONG_ADDR:  std_logic_vector(15 downto 0);
signal LAN1_N_RX_LENGTH_ERRORS:  std_logic_vector(15 downto 0);

--//-- ETHERNET MAC#2-----------------------------------
signal CLK_SKEW21: std_logic_vector(15 downto 0) := (others => '0');
signal CLK_SKEW22: std_logic_vector(15 downto 0) := (others => '0');
signal LAN2_MAC_ADDR: std_logic_vector(47 downto 0) := (others => '0');
signal LAN2_TP: std_logic_vector(10 downto 1) := (others => '0');
signal LAN2_PHY_ID: std_logic_vector(15 downto 0) := (others => '0');
signal LAN2_MAC_RX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal LAN2_MAC_RX_DATA_VALID: std_logic:= '0';
signal LAN2_MAC_RX_SOF: std_logic:= '0';
signal LAN2_MAC_RX_EOF: std_logic:= '0';
signal LAN2_MAC_TX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal LAN2_MAC_TX_DATA_VALID: std_logic:= '0';
signal LAN2_MAC_TX_EOF: std_logic:= '0';
signal LAN2_MAC_TX_CTS: std_logic:= '0';
signal LAN2_LINK_STATUS: std_logic:= '0';
signal LAN2_SPEED_STATUS: std_logic_vector(1 downto 0) := (others => '0');
signal LAN2_DUPLEX_STATUS: std_logic:= '0';
signal LAN2_N_RX_FRAMES:  std_logic_vector(15 downto 0);
signal LAN2_N_RX_BAD_CRCS:  std_logic_vector(15 downto 0);
signal LAN2_N_RX_FRAMES_TOO_SHORT:  std_logic_vector(15 downto 0);
signal LAN2_N_RX_FRAMES_TOO_LONG:  std_logic_vector(15 downto 0);
signal LAN2_N_RX_WRONG_ADDR:  std_logic_vector(15 downto 0);
signal LAN2_N_RX_LENGTH_ERRORS:  std_logic_vector(15 downto 0);

--//-- IP STACK #1  -----------------------------------
constant NTCPSTREAMS1: integer := f_nctp1(OPTION);  -- number of concurrent TCP streams handled by this component
signal IP1_ADDRv4: std_logic_vector(31 downto 0) := (others => '0');	
signal MULTICAST_IP1_ADDR: std_logic_vector(31 downto 0) := (others => '0');	
signal IP1_TP: std_logic_vector(10 downto 1) := (others => '0');
signal IP1_UDP_RX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal IP1_UDP_RX_DATA_VALID: std_logic := '0';
signal IP1_UDP_RX_DATA_VALID_29495: std_logic := '0';
signal IP1_UDP_RX_DATA_VALID_1029: std_logic := '0';
signal IP1_UDP_RX_SOF: std_logic := '0';
signal IP1_UDP_RX_EOF: std_logic := '0';
signal IP1_UDP_RX_DEST_PORT_NO: std_logic_vector(15 downto 0) := (others => '0');
signal IP1_TCP_RX_DATA: SLV8xNTCPSTREAMStype;
signal IP1_TCP_RX_DATA_VALID: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal IP1_TCP_RX_CTS: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal IP1_TCP_CONNECTED_FLAG: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal IP1_UDP_RX_DATA2: std_logic_vector(7 downto 0) := (others => '0');
signal IP1_UDP_RX_DATA_VALID2: std_logic := '0';
signal IP1_UDP_RX_SOF2: std_logic := '0';
signal IP1_UDP_RX_EOF2: std_logic := '0';
signal IP1_UDP_RX_DATA3: std_logic_vector(7 downto 0) := (others => '0');
signal IP1_UDP_RX_DATA_VALID3: std_logic := '0';
signal IP1_UDP_TX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal IP1_UDP_TX_DATA_VALID: std_logic := '0';
signal IP1_UDP_TX_SOF: std_logic := '0';
signal IP1_UDP_TX_EOF: std_logic := '0';
signal IP1_UDP_TX_CTS: std_logic := '0';
signal IP1_UDP_TX_ACK: std_logic := '0';
signal IP1_UDP_TX_NAK: std_logic := '0';
signal IP1_UDP_TX_DEST_IP_ADDR: std_logic_vector(127 downto 0) := (others => '0');
signal IP1_UDP_TX_DEST_PORT_NO: std_logic_vector(15 downto 0) := (others => '0');
signal IP1_TCP_TX_DATA: SLV8xNTCPSTREAMStype;
signal IP1_TCP_TX_DATA_VALID: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal IP1_TCP_TX_CTS: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');

--//-- IP STACK #2  -----------------------------------
constant NTCPSTREAMS2: integer := 4;  -- number of concurrent TCP streams handled by this component
signal IP2_ADDRv4: std_logic_vector(31 downto 0) := (others => '0');	
signal SUBNET_MASK: std_logic_vector(31 downto 0) := (others => '0');	
signal GATEWAY_IP_ADDR: std_logic_vector(31 downto 0) := (others => '0');	
signal IPSTACK2_TP: std_logic_vector(10 downto 1) := (others => '0');
signal IP2_UDP_RX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal IP2_UDP_RX_DEST_PORT_NO: std_logic_vector(15 downto 0) := (others => '0');
signal IP2_UDP_RX_DATA_VALID: std_logic := '0';
signal IP2_UDP_RX_DATA_VALID_1029: std_logic := '0';
signal IP2_UDP_RX_DATA2: std_logic_vector(7 downto 0) := (others => '0');
signal IP2_UDP_RX_DATA_VALID2: std_logic := '0';
signal IP2_UDP_RX_SOF: std_logic := '0';
signal IP2_UDP_RX_EOF: std_logic := '0';
signal IP2_UDP_TX_DATA1: std_logic_vector(7 downto 0) := (others => '0');
signal IP2_UDP_TX_DATA2: std_logic_vector(7 downto 0) := (others => '0');
signal IP2_UDP_TX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal IP2_UDP_TX_DATA1_VALID: std_logic := '0';
signal IP2_UDP_TX_DATA2_VALID: std_logic := '0';
signal IP2_UDP_TX_DATA_VALID: std_logic := '0';
signal IP2_UDP_TX_SOF: std_logic := '0';
signal IP2_UDP_TX_EOF: std_logic := '0';
signal IP2_UDP_TX_CTS: std_logic := '0';
signal IP2_UDP_TX_ACK: std_logic := '0';
signal IP2_UDP_TX_NAK: std_logic := '0';
signal IP2_UDP_TX_DEST_IP_ADDR: std_logic_vector(127 downto 0) := (others => '0');
signal IP2_UDP_TX_DEST_PORT_NO: std_logic_vector(15 downto 0) := (others => '0');
signal IP2_UDP_TX_DEST_PORT_NO1: std_logic_vector(15 downto 0) := (others => '0');
signal IP2_UDP_TX_DEST_PORT_NO2: std_logic_vector(15 downto 0) := (others => '0');
signal IP2_TCP_RX_DATA: SLV8xNTCPSTREAMStype;
signal IP2_TCP_RX_DATA_VALID: std_logic_vector((NTCPSTREAMS2-1) downto 0) := (others => '0');
--signal IP2_TCP_RX_RTS: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal IP2_TCP_RX_CTS: std_logic_vector((NTCPSTREAMS2-1) downto 0) := (others => '0');
signal IP2_TCP_TX_DATA: SLV8xNTCPSTREAMStype;
signal IP2_TCP_TX_DATA_VALID: std_logic_vector((NTCPSTREAMS2-1) downto 0) := (others => '0');
signal IP2_TCP_TX_CTS: std_logic_vector((NTCPSTREAMS2-1) downto 0) := (others => '0');
signal IP2_TCP_CONNECTED_FLAG: std_logic_vector((NTCPSTREAMS2-1) downto 0) := (others => '0');
signal LAN2_RX_DATA0: std_logic_vector(7 downto 0) := (others => '0');
signal LAN2_RX_SAMPLE0_CLK: std_logic := '0';
signal LAN2_RX_SAMPLE1_CLK: std_logic := '0';

--// LAN#2 TCP-IP Interface for M&C (port 1028)
signal EB1_SAMPLE_CLK_OUT_E: std_logic := '0';
signal RX_LAN: std_logic_vector(7 downto 0) := (others => '0'); 
signal RX_LAN_SAMPLE_CLK_REQ: std_logic;
signal RX_LAN_BUFFER_EMPTY: std_logic := '1';
signal RX_LAN_BUFFER_EMPTY_D: std_logic := '1';
signal RX_LAN_BUFFER_EMPTY_D2: std_logic := '1';
signal TX_LAN_TOGGLE: std_logic;
signal TX_LAN_TOGGLE_D: std_logic;
signal TX_LAN_TOGGLE_D2: std_logic;

--//-- SDDS input (SIMULATION) ----------------------------------
type char_file is file of character; -- one byte each
file SDDS_RX_FILE: char_file;
constant SDDS_FILENAME: string := "c:\swift_neg_20_2015_03_19_193719.det";	
--constant SDDS_FILENAME: string := "c:\sqpn-100-100-pn11.det";	
signal SDDS_FILE_RX_DATA: std_logic_vector(7 downto 0) := x"00";
signal SDDS_FILE_RX_DATA_VALID: std_logic := '0';

--//-- SDDS deframing ----------------------------------
signal INPUT_UDP_TCPN: std_logic := '0';
signal SDDS_RX_DATA_IN: std_logic_vector(7 downto 0) := (others => '0');
signal SDDS_RX_DATA_VALID_IN: std_logic := '0';
signal SDDS_RX_SOF_IN: std_logic := '0';
signal SDDS_RX_EOF_IN: std_logic := '0';
signal SDDS_RX_CTS: std_logic := '0';
signal SDDS_RX_BYTE_CNTR: unsigned(10 downto 0) := (others => '0');
signal SDDS_RX_FRAME_CNTR: unsigned(31 downto 0) := (others => '0');
signal SDDS_RX_SAMPLING_RATE: std_logic_vector(31 downto 0) := (others => '0');
signal SDDS_RX_TIMETAG: std_logic_vector(63 downto 0) := (others => '0');
signal SDDS_RX_TIMETAG1: std_logic_vector(63 downto 0) := (others => '0');
signal SDDS_RX_TIMETAG2: std_logic_vector(63 downto 0) := (others => '0');
signal SDDS_N_MISSING_FRAMES: std_logic_vector(15 downto 0) := (others => '0');
signal SDDS_TP: std_logic_vector(10 downto 1) := (others => '0');
signal RX_DATA1_I: std_logic_vector(15 downto 0) := (others => '0');
signal RX_DATA1_Q: std_logic_vector(15 downto 0) := (others => '0');
signal RX_SAMPLE1_CLK: std_logic := '0';
signal RX_DATA2_I: std_logic_vector(13 downto 0) := (others => '0');
signal RX_DATA2_Q: std_logic_vector(13 downto 0) := (others => '0');
signal RX_SAMPLE2_CLK: std_logic := '0';

--//-- DDR3 SODIMM CONTROLLER  -----------------------------------------------
-- optional/future
constant DDR3_ENABLED : std_logic := '0';    -- 0/1 to instantiate DDR3 SDRAM memory controller
signal DDR3_PLL_LOCKED_OUT: std_logic := '0';

--//-- INPUTS SELECTION -------------------------------------
signal INPUTS_SEL: std_logic_vector(7 downto 0) := (others => '0');
signal PRBS11_SYNC_RESET1: std_logic := '0';
signal PRBS11_SYNC_RESET2: std_logic := '0';
signal PRBS11_DATA1_VALID: std_logic := '0';
signal PRBS11_DATA2_VALID: std_logic := '0';
signal PRBS11_CTS1: std_logic := '0';
signal PRBS11_CTS2: std_logic := '0';
signal PRBS11_DATA1: std_logic_vector(7 downto 0) := (others => '0');
signal PRBS11_DATA2: std_logic_vector(7 downto 0) := (others => '0');

--//-- PARALLEL TO SERIAL CONVERSION ----------------------------
signal CENC1_DATA8b_IN: std_logic_vector(7 downto 0) := (others => '0');
signal CENC1_DATA8b_IN_VALID: std_logic := '0';
signal CENC1_DATA8b_IN_CTS: std_logic := '0';
signal P2S_BUF_EMPTY1: std_logic := '0';
signal TX_DATA1b11: std_logic := '0';
signal TX_DATA1b11_VALID: std_logic := '0';
signal TX_DATA1b11_CTS: std_logic := '0';

signal CENC2_DATA8b_IN: std_logic_vector(7 downto 0) := (others => '0');
signal CENC2_DATA8b_IN_VALID: std_logic := '0';
signal CENC2_DATA8b_IN_CTS: std_logic := '0';
signal P2S_BUF_EMPTY2: std_logic := '0';
signal TX_DATA1b12: std_logic := '0';
signal TX_DATA1b12_VALID: std_logic := '0';
signal TX_DATA1b12_CTS: std_logic := '0';


--//-- I/Q DEMUX --------------------------------------------------
signal TOGGLE_QIn: std_logic := '0';

--//-- DATA FORMAT CONVERTER (TX) --------------------------------------
signal NRZ1_TX_CONTROL: std_logic_vector(2 downto 0) := (others => '0');
signal NRZ1_TX_DATA1_IN: std_logic := '0';
signal NRZ1_TX_DATA1_VALID_IN: std_logic := '0';
signal NRZ1_TX_DATA2_IN: std_logic := '0';
signal NRZ1_TX_DATA2_VALID_IN: std_logic := '0';

--//-- FEC ENCODING --------------------------------------
signal ENCODER_ENABLED: std_logic_vector(1 downto 0) := (others => '0');
signal CENC1_DATA_IN: std_logic := '0';
signal CENC1_SAMPLE_CLK_IN: std_logic := '0';
signal CENC1_SAMPLE_CLK_IN_REQ: std_logic := '0';
signal CENC1_DATA_OUT: std_logic_vector(3 downto 0) := (others => '0');
signal CENC2_DATA_IN: std_logic := '0';
signal CENC2_SAMPLE_CLK_IN: std_logic := '0';
signal CENC2_SAMPLE_CLK_IN_REQ: std_logic := '0';
signal CENC2_DATA_OUT: std_logic_vector(3 downto 0) := (others => '0');
signal CENC1_SAMPLE_CLK_OUT: std_logic := '0';
signal CENC2_SAMPLE_CLK_OUT: std_logic := '0';
signal CENC_CONTROL:  std_logic_vector(15 downto 0) := (others => '0');

--//-- DSSS MODULATOR -------------------------------------
signal MOD_TX_DATA: std_logic_vector(1 downto 0) := (others => '0');
signal MOD_TX_DATA_SAMPLE_CLK:  std_logic_vector(1 downto 0) := (others => '0');
signal MOD_TX_CTS: std_logic_vector(1 downto 0) := (others => '0');
signal MOD_LFSRA_INIT: std_logic_vector(10 downto 0) := (others => '0');	
signal MOD_LFSRC_INIT: std_logic_vector(10 downto 0) := (others => '0');	
signal MOD_CODE_MODE: std_logic := '0';
signal MOD_CHIP_RATE: std_logic_vector(31 downto 0) := (others => '0');
signal MOD_SYMBOL_RATE1: std_logic_vector(31 downto 0) := (others => '0');
signal MOD_SYMBOL_RATE2: std_logic_vector(31 downto 0) := (others => '0');
signal MOD_GAIN: std_logic_vector(15 downto 0) := (others => '0');
signal MOD_CENTER_FREQ: std_logic_vector(31 downto 0) := (others => '0');
signal MOD_SINE_FREQ_OFFSET_AMPLITUDE: std_logic_vector(31 downto 0) := (others => '0');
signal MOD_SINE_FREQ_OFFSET_FREQUENCY: std_logic_vector(31 downto 0) := (others => '0');
signal MOD_CONTROL: std_logic_vector(15 downto 0) := (others => '0');
signal MOD_DATA_I: std_logic_vector(17 downto 0) := (others => '0');	
signal MOD_DATA_Q: std_logic_vector(17 downto 0) := (others => '0');
signal MOD_DATA2_I: std_logic_vector(17 downto 0) := (others => '0');	
signal MOD_DATA2_Q: std_logic_vector(17 downto 0) := (others => '0');
signal MOD_SAMPLE_CLK: std_logic := '0';
signal MOD_SAMPLE_CLK_SHIFT: std_logic_vector(9 downto 0) := (others => '0');
signal NCO_MOD_SAMPLING_CNTR: integer range 0 to 20 := 0;
signal MOD_TP: std_logic_vector(10 downto 1) := (others => '0');
	
--// ADDITIVE WHITE GAUSSIAN NOISE -------------------------------------
signal NOISE_GAIN: std_logic_vector(16 downto 0) := (others => '0');
signal NOISE_DATA1_I: std_logic_vector(15 downto 0) := (others => '0');
signal NOISE_DATA1_Q: std_logic_vector(15 downto 0) := (others => '0');
signal NOISE_DATA1_I_D: signed(15 downto 0) := (others => '0');
signal NOISE_DATA1_Q_D: signed(15 downto 0) := (others => '0');
signal NOISE_DATA2_I: signed(32 downto 0) := (others => '0');
signal NOISE_DATA2_Q: signed(32 downto 0) := (others => '0');
signal NOISE_DATA3_I: signed(17 downto 0) := (others => '0');
signal NOISE_DATA3_Q: signed(17 downto 0) := (others => '0');
signal NOISE_GAIN_I_SATURATION: std_logic := '0';
signal NOISE_GAIN_Q_SATURATION: std_logic := '0';
signal SN1_I: signed(18 downto 0) := (others => '0');
signal SN1_Q: signed(18 downto 0) := (others => '0');
signal SN2_I: std_logic_vector(17 downto 0) := (others => '0');
signal SN2_Q: std_logic_vector(17 downto 0) := (others => '0');
signal SN2_SAMPLE_CLK: std_logic := '0';
signal SN_I_SATURATION: std_logic := '0';
signal SN_Q_SATURATION: std_logic := '0';
signal MOD_SIGNAL_POWER: std_logic_vector(23 downto 0) := (others => '0');
signal NOISE_POWER: std_logic_vector(23 downto 0) := (others => '0');

--//-- COM-30XX RECEIVER INTERFACE
signal RX_DATA0CD_I: std_logic_vector(11 downto 0) := (others => '0');
signal RX_DATA0CD_Q: std_logic_vector(11 downto 0) := (others => '0');
signal RX_DATA0CD: std_logic_vector(23 downto 0) := (others => '0');
signal RX_DATA0: std_logic_vector(23 downto 0) := (others => '0');

--//-- COM-3504 BASEBAND TRANSCEIVER DRIVER 
signal TX_GAIN_DAC: std_logic_vector(11 downto 0) := (others => '0');	
signal COM3504_ADC1_DIN: std_logic_vector(11 downto 0) := (others => '0');
signal COM3504_ADC2_DIN: std_logic_vector(11 downto 0) := (others => '0');
signal RX_DATA0_I: std_logic_vector(11 downto 0) := (others => '0');
signal RX_DATA0_Q: std_logic_vector(11 downto 0) := (others => '0');

--// COM-4009 RF MODULATOR DRIVER ------------------
signal DAC_REFCLK: std_logic := '0'; 
signal DAC_DCI: std_logic := '0'; 
signal DAC_DCO: std_logic := '0'; 
signal DAC_D: std_logic_vector(15 downto 0) := (others => '0');

--// LOOP BACK -----------------------------------------------
signal LOOPBACK_DATA1_I: std_logic_vector(13 downto 0) := (others => '0');
signal LOOPBACK_DATA1_Q: std_logic_vector(13 downto 0) := (others => '0');
signal LOOPBACK_MODE: std_logic := '0';

--//-- RECLOCKED INPUTS ---------------------
signal AGC_DAC: std_logic_vector(11 downto 0) := (others => '0');	
signal AGC_DAC_SAMPLE_CLK: std_logic := '0';
signal AUX_DAC1_OP_MODE: std_logic_vector(1 downto 0) := (others => '0');	
signal ADC_DATA_I_IN: std_logic_vector(13 downto 0) := (others => '0');
signal ADC_DATA_Q_IN: std_logic_vector(13 downto 0) := (others => '0');
	
--//-- DSSS DEMODULATOR ----------------------------------------
signal DEMOD_LFSRA_INIT: std_logic_vector(10 downto 0) := (others => '0');	
signal DEMOD_LFSRC_INIT: std_logic_vector(10 downto 0) := (others => '0');	
signal DEMOD_CODE_MODE: std_logic := '0';
signal NOMINAL_CHIP_RATE: std_logic_vector(31 downto 0) := (others => '0');
signal NOMINAL_CHIP_RATE_DYNAMIC: signed(31 downto 0) := (others => '0');
signal CIC_R: std_logic_vector(15 downto 0) := (others => '0');	
signal NOMINAL_SYMBOL_RATE1: std_logic_vector(31 downto 0) := (others => '0');
signal NOMINAL_SYMBOL_RATE2: std_logic_vector(31 downto 0) := (others => '0');
signal SPREADING_FACTOR1: std_logic_vector(12 downto 0) := (others => '0');
signal SPREADING_FACTOR2: std_logic_vector(12 downto 0) := (others => '0');

signal CARRIER_LOCK_OUT: std_logic := '0';
signal CODE_LOCK_OUT: std_logic := '0';
signal CODE_LOCK_1S: std_logic := '0';
signal CODE_LOCK_FLAG: std_logic := '0';
signal SIGNAL_PRESENT_OUT: std_logic := '0';

signal RECEIVER_AGC_RESPONSE: std_logic_vector(4 downto 0) := (others => '0');	
signal RECEIVER_RESET: std_logic := '0';
signal RECEIVER_CENTER_FREQ: std_logic_vector(31 downto 0) := (others => '0');	
signal RECEIVER_CENTER_FREQ_DYNAMIC: signed(31 downto 0) := (others => '0');	
signal FREQ_SCAN_N_COARSE_STEPS: std_logic_vector(7 downto 0) := (others => '0');
signal DEMOD_CONTROL: std_logic_vector(15 downto 0) := (others => '0');
signal DATA_I_OUT: std_logic_vector(7 downto 0) := (others => '0');
signal DATA_Q_OUT: std_logic_vector(7 downto 0) := (others => '0');
signal SAMPLE_I_CLK_OUT: std_logic := '0'; 
signal SAMPLE_Q_CLK_OUT: std_logic := '0'; 
signal CARRIER_FREQUENCY_ERROR1: std_logic_vector(31 downto 0) := (others => '0');
signal CARRIER_FREQUENCY_ERROR2: std_logic_vector(31 downto 0) := (others => '0');
signal POWER_S_AVERAGE_OUT: std_logic_vector(17 downto 0) := (others => '0');
signal POWER_N_AVERAGE_OUT: std_logic_vector(17 downto 0) := (others => '0');
signal SNR1_LOCKED_OUT: std_logic_vector(17 downto 0) := (others => '0');
signal SNR2_LOCKED_OUT: std_logic_vector(17 downto 0) := (others => '0');
signal DEMOD_TP: std_logic_vector(20 downto 1) := (others => '0');

--//-- VITERBI FEC DECODERS --------------------------------------------
signal FEC_DEC_G: std_logic_vector(62 downto 0) := (others => '0');
signal FEC_DEC_R1: integer range 1 to 7 := 1;
signal FEC_DEC_R2: integer range 2 to 8 := 2;
signal FEC_DEC_STANDARD: integer range 0 to 2 := 0;
signal FEC_DEC_DIFF_ENC_ON: std_logic := '0';
signal FEC_DEC_ENABLE: std_logic := '0';
signal FEC_G1_INVERSION: std_logic := '0';

signal FEC_DEC1_HIGH_SNR: std_logic := '0';
signal FEC_DEC1_DATAIN: std_logic_vector(31 downto 0) := (others => '0');
signal FEC_DEC1_DATAIN_VALID: std_logic := '0';
signal FEC_DEC1_DATAIN_CNTR: unsigned(2 downto 0) := (others => '0');
signal FEC_DEC1_BIT_VALID: std_logic := '0';
signal FEC_DEC1_BIT: std_logic := '0';
signal FEC_DEC8b1: std_logic_vector(7 downto 0) := (others => '0');
signal FEC_DEC8b1_VALID: std_logic := '0';
signal FEC_DEC1_LOCK_STATUS: std_logic := '0';
signal FEC_DEC1_BER_COUNT: std_logic_vector(23 downto 0) := (others => '0');
signal FEC_DEC1_BER_VALID: std_logic := '0';
signal FEC_DEC1_BIT_ERROR: std_logic := '0';
signal FEC_DEC1_IN_SYNC: std_logic := '0';
signal FEC_DEC1_OUT_OF_SYNC: std_logic := '0';
signal FEC_DEC1_LOCK_CONFIDENCE: unsigned(2 downto 0) := (others => '0');
signal FEC_DEC1_CONFIRMED_LOCK: std_logic := '0';

signal FEC_DEC2_HIGH_SNR: std_logic := '0';
signal FEC_DEC2_DATAIN: std_logic_vector(31 downto 0) := (others => '0');
signal FEC_DEC2_DATAIN_VALID: std_logic := '0';
signal FEC_DEC2_DATAIN_CNTR: unsigned(2 downto 0) := (others => '0');
signal FEC_DEC2_SKIP1BIT_PULSE: std_logic := '0';
signal FEC_DEC2_SYNC_CONTROL: std_logic := '0';
signal FEC_DEC2_BIT_VALID: std_logic := '0';
signal FEC_DEC2_BIT: std_logic := '0';
signal FEC_DEC2_LOCK_STATUS: std_logic := '0';
signal FEC_DEC2_BER_COUNT: std_logic_vector(23 downto 0) := (others => '0');
signal FEC_DEC2_BER_VALID: std_logic := '0';
signal FEC_DEC2_BIT_ERROR: std_logic := '0';
signal FEC_DEC2_IN_SYNC: std_logic := '0';
signal FEC_DEC2_OUT_OF_SYNC: std_logic := '0';
signal FEC_DEC2_LOCK_CONFIDENCE: unsigned(2 downto 0) := (others => '0');
signal FEC_DEC2_CONFIRMED_LOCK: std_logic := '0';

--//-- DATA FORMAT CONVERTER (RX) --------------------------------------
signal NRZ1_RX_CONTROL: std_logic_vector(2 downto 0) := (others => '0');
signal NRZ1_RX_DATA1_IN: std_logic := '0';
signal NRZ1_RX_DATA1_VALID_IN: std_logic := '0';
signal NRZ1_RX_DATA2_IN: std_logic := '0';
signal NRZ1_RX_DATA2_VALID_IN: std_logic := '0';
signal NRZ1_RX_DATA1_OUT: std_logic := '0';
signal NRZ1_RX_DATA1_VALID_OUT: std_logic := '0';
signal NRZ1_RX_DATA2_OUT: std_logic := '0';
signal NRZ1_RX_DATA2_VALID_OUT: std_logic := '0';

--//-- BER MEASUREMENT  ---------------------------------------------------------
signal BER2_DATA_IN: std_logic_vector(7 downto 0) := (others => '0');
signal BER2_SAMPLE_CLK_IN: std_logic := '0';
signal BER_CONTROL: std_logic_vector(7 downto 0) := (others => '0');
signal BER_MF_DETECT: std_logic := '0';
signal BER_MF_DETECT_CONFIRMED: std_logic := '0';
signal BER_SYNC: std_logic := '0';
signal BER_BYTE_ERROR: std_logic := '0';
signal BER_ERROR_COUNT: std_logic_vector(31 downto 0) := (others => '0');
signal BER_TEST_POINT: std_logic_vector(10 downto 1) := (others => '0');

--// UDP OUTPUTS ------------------------------	
signal FIRST_BYTE1_FLAG: std_logic := '0';
signal FIRST_BYTE2_FLAG: std_logic := '0';
signal S2P1_CNTR: unsigned(2 downto 0) := (others => '0');
signal S2P2_CNTR: unsigned(2 downto 0) := (others => '0');
signal S2P1_DATA_IN: std_logic_vector(7 downto 0) := (others => '0');
signal S2P2_DATA_IN: std_logic_vector(7 downto 0) := (others => '0');
signal S2P1_DATA_VALID_IN: std_logic := '0';
signal S2P2_DATA_VALID_IN: std_logic := '0';
signal TX_FRAME_CNTR1: unsigned(15 downto 0) := (others => '0');
signal TX_FRAME_CNTR2: unsigned(15 downto 0) := (others => '0');
signal TX_PREAMBLE1: std_logic_vector(111 downto 0) := (others => '0');
signal TX_PREAMBLE2: std_logic_vector(111 downto 0) := (others => '0');
signal PACKET_TX_PULSE1: std_logic := '0';
signal PACKET_TX_PULSE2: std_logic := '0';
signal IP2_UDP_TX_SOF1: std_logic := '0';
signal IP2_UDP_TX_SOF2: std_logic := '0';
signal IP2_UDP_TX_EOF1: std_logic := '0';
signal IP2_UDP_TX_EOF2: std_logic := '0';
signal IP2_UDP_TX_RTS1: std_logic := '0';
signal IP2_UDP_TX_RTS2: std_logic := '0';
signal IP2_UDP_TX_CTS1: std_logic := '0';
signal IP2_UDP_TX_CTS2: std_logic := '0';
signal IP2_UDP_TX_MUX_STATE: integer range 0 to 2 := 0;

--//-- FREQUENCY TABLE ----------------------------------
signal FT_STATE: integer range 0 to 4 := 0;
signal FT_PLAYBACK: std_logic := '0';
signal FT_WPTR: unsigned(13 downto 0) := (others=> '0');    -- expressed in bytes
signal FT_WPTR_D: unsigned(13 downto 0) := (others=> '0');  -- expressed in bytes
signal FT_WRITE_FULL: std_logic := '0';
signal FT_RPTR: unsigned(11 downto 0) := (others=> '0');    -- expressed in 32-bit words
signal FT_START_TIME: std_logic_vector(63 downto 0) := (others => '0');
signal FT_START_TIME_final: unsigned(63 downto 0) := (others => '0');
signal FT_1_64s_CNTR: unsigned(20 downto 0) := (others => '0');
signal FT_1s_CNTR: unsigned(5 downto 0) := (others => '0');
signal FT_1_64s_TICK: std_logic := '0';
signal FT_1_64s_TICK_D: std_logic := '0';
signal FT_1_64s_TICK_D2: std_logic := '0';
signal FT_1s_TICK: std_logic := '0';
signal FT_WRITE_SAMPLE_CLK: std_logic := '0';
signal FT_READ_SAMPLE_CLK: std_logic := '0';
signal FT_READ_SAMPLE_CLK_D: std_logic := '0';
signal FT_DIA: std_logic_vector(31 downto 0) := (others => '0');
signal FT_WEA: std_logic_vector(7 downto 0) := (others => '0');
type DOBtype is array (integer range 0 to 7) of std_logic_vector(31 downto 0);
signal FT_DOB: DOBtype;
signal RPTR_MEMINDEX: integer range 0 to 7 := 0;
signal FT_FREQ0: std_logic_vector(31 downto 0) := (others => '0');
signal FT_FREQ_START: signed(31 downto 0) := (others => '0');
signal FT_FREQ_END: signed(31 downto 0) := (others => '0');
signal FT_FREQ_DIFF: signed(31 downto 0) := (others => '0');
signal FT_FREQ: signed(31 downto 0) := (others => '0');	-- dynamic offset for rx center frequency
signal CFT_A: signed(17 downto 0) := (others => '0');
signal CFT_B: signed(17 downto 0) := (others => '0');
signal CFT_AB: signed(35 downto 0) := (others => '0');
signal CFT_FREQ: signed(31 downto 0) := (others => '0');	-- dynamic offset for rx chip rate

--// USB Interface for M&C
signal SREG254_READ_TOGGLE_D: std_logic := '0';
signal SREG254_READ_TOGGLE_D2: std_logic := '0';

--// ComScope traces
signal S1_1: std_logic_vector(7 downto 0) := (others => '0');	
signal S1_1_CLK: std_logic := '0';
signal S1_2: std_logic_vector(7 downto 0) := (others => '0');	
signal S1_2_CLK: std_logic := '0';
signal S1_3: std_logic_vector(7 downto 0) := (others => '0');	
signal S1_3_CLK: std_logic := '0';
signal S1_4: std_logic_vector(7 downto 0) := (others => '0');	
signal S1_4_CLK: std_logic := '0';
signal S2_1: std_logic_vector(7 downto 0) := (others => '0');	
signal S2_1_CLK: std_logic := '0';
signal S2_2: std_logic_vector(7 downto 0) := (others => '0');	
signal S2_2_CLK: std_logic := '0';
signal S2_3: std_logic_vector(7 downto 0) := (others => '0');	
signal S2_3_CLK: std_logic := '0';
signal S2_4: std_logic_vector(7 downto 0) := (others => '0');	
signal S2_4_CLK: std_logic := '0';
signal S3_1: std_logic_vector(7 downto 0) := (others => '0');	
signal S3_1_CLK: std_logic := '0';
signal S3_2: std_logic_vector(7 downto 0) := (others => '0');	
signal S3_2_CLK: std_logic := '0';
signal S3_3: std_logic_vector(7 downto 0) := (others => '0');	
signal S3_3_CLK: std_logic := '0';
signal S3_4: std_logic_vector(7 downto 0) := (others => '0');	
signal S3_4_CLK: std_logic := '0';
signal S4_1: std_logic_vector(7 downto 0) := (others => '0');	
signal S4_1_CLK: std_logic := '0';
signal S4_2: std_logic_vector(7 downto 0) := (others => '0');	
signal S4_2_CLK: std_logic := '0';
signal S4_3: std_logic_vector(7 downto 0) := (others => '0');	
signal S4_3_CLK: std_logic := '0';
signal S4_4: std_logic_vector(7 downto 0) := (others => '0');	
signal S4_4_CLK: std_logic := '0';

signal T1: std_logic := '0';
signal T1_CLK: std_logic := '0';
signal T2: std_logic := '0';
signal T2_CLK: std_logic := '0';

signal TRIGGER_REARM_TOGGLE: std_logic:= '0';
signal FORCE_TRIGGER_TOGGLE: std_logic:= '0';
signal START_CAPTURE_TOGGLE: std_logic:= '0';
signal SREG250_READ_TOGGLE: std_logic := '0';

--//-- DNA Port ------------------------------------
signal DNA_ID_DATA: std_logic_vector(56 downto 0) := (others => '0');
signal DNA_ID_SAMPLE_CLK: std_logic := '0';

--// ARM co-processor interface
signal UC_WEBG: std_logic := '0';  -- WE# through global buffer
signal UC_REBG: std_logic := '0';	-- RE# through global buffer
signal UC_ADDRESS: unsigned(7 downto 0) := (others => '0');
signal UC_AD_LOCAL: std_logic_vector(7 downto 0) := (others => '0');
signal UC_RDN_D: std_logic := '0';
signal UC_RDN_D2: std_logic := '0';
signal CONFIG_CHANGE_TOGGLE: std_logic := '0';
signal CONFIG_CHANGE_TOGGLE_D: std_logic := '0';
signal CONFIG_CHANGE_TOGGLE_D2: std_logic := '0';
signal CONFIG_CHANGE_PULSE: std_logic := '0';
signal PATH_TO_HOST: integer range 0 to 2 := 0;
signal RX_USB_LAN: std_logic_vector(7 downto 0) := (others => '0'); 
signal LAN_ADDR_CHANGE_TOGGLE: std_logic := '0';
signal LAN_ADDR_CHANGE_TOGGLE_D: std_logic := '0';
signal LAN_ADDR_CHANGE_TOGGLE_D2: std_logic := '0';
signal LAN_ADDR_CHANGE_PULSE: std_logic := '0';

--// Control Registers
---- 200 Kbps SQPN dual sources code 26 low level no noise loopback
--signal REG0: std_logic_vector(7 downto 0) := x"00";	-- demod input selection: UDP (1) vs TCP (0)
--signal REG1: std_logic_vector(7 downto 0) := x"12";	-- I-code (LSB)  
--signal REG2: std_logic_vector(7 downto 0) := x"2d";
--signal REG3: std_logic_vector(7 downto 0) := x"9b"; -- Q-code (LSB)  n/a
--signal REG4: std_logic_vector(7 downto 0) := x"07";	
--signal REG5: std_logic_vector(7 downto 0) := x"30";	-- chip rate (LSB)
--signal REG6: std_logic_vector(7 downto 0) := x"A7";	
--signal REG7: std_logic_vector(7 downto 0) := x"4D";	
--signal REG8: std_logic_vector(7 downto 0) := x"06";	-- chip rate (MSB)
--signal REG9: std_logic_vector(7 downto 0) := x"8c";	-- I symbol rate 
--
--signal REG10: std_logic_vector(7 downto 0) := x"db";	
--signal REG11: std_logic_vector(7 downto 0) := x"68";	
--signal REG12: std_logic_vector(7 downto 0) := x"00";	
--signal REG13: std_logic_vector(7 downto 0) := x"8c";    -- Q symbol rate
--signal REG14: std_logic_vector(7 downto 0) := x"db";
--signal REG15: std_logic_vector(7 downto 0) := x"68";	
--signal REG16: std_logic_vector(7 downto 0) := x"00";	
--signal REG17: std_logic_vector(7 downto 0) := x"0f";	-- I spreading factor 
--signal REG18: std_logic_vector(7 downto 0) := x"00";	
--signal REG19: std_logic_vector(7 downto 0) := x"0f";	-- Q spreading factor
--
--signal REG20: std_logic_vector(7 downto 0) := x"00";
--signal REG21: std_logic_vector(7 downto 0) := x"00";	-- nominal input center frequency (LSB)
--signal REG22: std_logic_vector(7 downto 0) := x"00";	 
--signal REG23: std_logic_vector(7 downto 0) := x"00";
--signal REG24: std_logic_vector(7 downto 0) := x"00";
--signal REG25: std_logic_vector(7 downto 0) := x"00";	-- reserved (for scanning)
--signal REG26: std_logic_vector(7 downto 0) := x"02";	-- controls (LSB)
--signal REG27: std_logic_vector(7 downto 0) := x"16";	-- controls (MSB)
--signal REG28: std_logic_vector(7 downto 0) := x"89";	-- AGC response time, loopback mode
--signal REG29: std_logic_vector(7 downto 0) := x"3c";	-- modulator signal gain (LSB)
--
--signal REG30: std_logic_vector(7 downto 0) := x"00";	-- modulator signal gain (MSB) 
--signal REG31: std_logic_vector(7 downto 0) := x"00";	-- AWGN gain (LSB) 
--signal REG32: std_logic_vector(7 downto 0) := x"00";	-- AWGN gain (MSB)
--signal REG33: std_logic_vector(7 downto 0) := x"E1";	-- multicast IP address, LAN#1 (MSB)
--signal REG34: std_logic_vector(7 downto 0) := x"00";	
--signal REG35: std_logic_vector(7 downto 0) := x"00";	
--signal REG36: std_logic_vector(7 downto 0) := x"01";	-- multicast IP address, LAN#1 (LSB)
--signal REG37: std_logic_vector(7 downto 0) := x"AC";	-- static IP address, LAN#1 (MSB)
--signal REG38: std_logic_vector(7 downto 0) := x"10";	
--signal REG39: std_logic_vector(7 downto 0) := x"01";
--	
--signal REG40: std_logic_vector(7 downto 0) := x"01";	-- static IP address, LAN#1 (LSB)
--signal REG41: std_logic_vector(7 downto 0) := x"AC";	-- static IP address, LAN#2 (MSB)
--signal REG42: std_logic_vector(7 downto 0) := x"10";	
--signal REG43: std_logic_vector(7 downto 0) := x"01";	
--signal REG44: std_logic_vector(7 downto 0) := x"02";	-- static IP address, LAN#2 (LSB)
--signal REG45: std_logic_vector(7 downto 0) := x"AC";	-- destination IP address for demodulated data (MSB)
--signal REG46: std_logic_vector(7 downto 0) := x"10";	
--signal REG47: std_logic_vector(7 downto 0) := x"01";	
--signal REG48: std_logic_vector(7 downto 0) := x"44";	-- destination IP address for demodulated data (LSB)
--signal REG49: std_logic_vector(7 downto 0) := x"01";	-- destination IP port for demodulated data (LSB)
--
--signal REG50: std_logic_vector(7 downto 0) := x"04";	-- MSB
--signal REG51: std_logic_vector(7 downto 0) := x"FF";	-- Subnet mask (MSB)
--signal REG52: std_logic_vector(7 downto 0) := x"FF";	
--signal REG53: std_logic_vector(7 downto 0) := x"FF";	
--signal REG54: std_logic_vector(7 downto 0) := x"00";	-- Subnet mask (LSB)
--signal REG55: std_logic_vector(7 downto 0) := x"AC";	-- Gateway IP address (MSB)
--signal REG56: std_logic_vector(7 downto 0) := x"10";	
--signal REG57: std_logic_vector(7 downto 0) := x"01";	
--signal REG58: std_logic_vector(7 downto 0) := x"03";	-- Gateway IP address (LSB)
--signal REG59: std_logic_vector(7 downto 0) := x"c8";	-- COM-350X controls
--
--signal REG60: std_logic_vector(7 downto 0) := x"10";	-- alternating I/Q bits, 1/2 symbol Q delay, COM-350X controls
--signal REG61: std_logic_vector(7 downto 0) := x"C2";	-- modulator on, SQPN/BPSK, same/different data on I/Q
--signal REG62: std_logic_vector(7 downto 0) := x"12";	-- I-code (LSB)  code 40   2225o
--signal REG63: std_logic_vector(7 downto 0) := x"25";	-- MSB + modulator inputs selection
--signal REG64: std_logic_vector(7 downto 0) := x"9b"; -- Q-code (LSB)  code 40 1337o
--signal REG65: std_logic_vector(7 downto 0) := x"2f";	-- MSB + modulator inputs selection
--signal REG66: std_logic_vector(7 downto 0) := x"30";	-- modulator chip rate (LSB)
--signal REG67: std_logic_vector(7 downto 0) := x"A7";	
--signal REG68: std_logic_vector(7 downto 0) := x"4D";	
--signal REG69: std_logic_vector(7 downto 0) := x"06";	-- modulator chip rate (MSB)
--
--signal REG70: std_logic_vector(7 downto 0) := x"8c";	-- modulator I symbol rate 100 Kbps
--signal REG71: std_logic_vector(7 downto 0) := x"db";	
--signal REG72: std_logic_vector(7 downto 0) := x"68";	
--signal REG73: std_logic_vector(7 downto 0) := x"00";	
--signal REG74: std_logic_vector(7 downto 0) := x"8c";    -- modulator Q symbol rate
--signal REG75: std_logic_vector(7 downto 0) := x"db";
--signal REG76: std_logic_vector(7 downto 0) := x"68";	
--signal REG77: std_logic_vector(7 downto 0) := x"00";	
--signal REG78: std_logic_vector(7 downto 0) := x"2d";	-- output center frequency (LSB)
--signal REG79: std_logic_vector(7 downto 0) := x"3e";
--	 
--signal REG80: std_logic_vector(7 downto 0) := x"05";
--signal REG81: std_logic_vector(7 downto 0) := x"00";	-- output center frequency (MSB)

signal REG0: std_logic_vector(7 downto 0) := x"01";	-- demod input selection: UDP (1) vs TCP (0)
signal REG1: std_logic_vector(7 downto 0) := x"12";	-- I-code (LSB)  
signal REG2: std_logic_vector(7 downto 0) := x"05";
signal REG3: std_logic_vector(7 downto 0) := x"9b"; -- Q-code (LSB)  n/a
signal REG4: std_logic_vector(7 downto 0) := x"07";	
signal REG5: std_logic_vector(7 downto 0) := x"42";	-- chip rate (LSB)
signal REG6: std_logic_vector(7 downto 0) := x"A7";	
signal REG7: std_logic_vector(7 downto 0) := x"4D";	
signal REG8: std_logic_vector(7 downto 0) := x"06";	-- chip rate (MSB)
signal REG9: std_logic_vector(7 downto 0) := x"51";	-- I symbol rate 

signal REG10: std_logic_vector(7 downto 0) := x"49";	
signal REG11: std_logic_vector(7 downto 0) := x"9d";	
signal REG12: std_logic_vector(7 downto 0) := x"00";	
signal REG13: std_logic_vector(7 downto 0) := x"51";    -- Q symbol rate
signal REG14: std_logic_vector(7 downto 0) := x"49";
signal REG15: std_logic_vector(7 downto 0) := x"9d";	
signal REG16: std_logic_vector(7 downto 0) := x"00";	
signal REG17: std_logic_vector(7 downto 0) := x"0A";	-- I spreading factor 
signal REG18: std_logic_vector(7 downto 0) := x"00";	
signal REG19: std_logic_vector(7 downto 0) := x"0A";	-- Q spreading factor

signal REG20: std_logic_vector(7 downto 0) := x"00";
signal REG21: std_logic_vector(7 downto 0) := x"00";	-- nominal input center frequency (LSB)
signal REG22: std_logic_vector(7 downto 0) := x"00";	 
signal REG23: std_logic_vector(7 downto 0) := x"00";
signal REG24: std_logic_vector(7 downto 0) := x"00";
signal REG25: std_logic_vector(7 downto 0) := x"00";	-- LAN1 tx skew
signal REG26: std_logic_vector(7 downto 0) := x"06";	-- controls (LSB) SQPN/BPSK, same/different data on I/Q
signal REG27: std_logic_vector(7 downto 0) := x"16";	-- controls (MSB)
signal REG28: std_logic_vector(7 downto 0) := x"89";	-- AGC response time, loopback mode
signal REG29: std_logic_vector(7 downto 0) := x"32";	-- modulator signal gain (LSB)

signal REG30: std_logic_vector(7 downto 0) := x"00";	-- modulator signal gain (MSB) 
signal REG31: std_logic_vector(7 downto 0) := x"00";	-- AWGN gain (LSB) 
signal REG32: std_logic_vector(7 downto 0) := x"00";	-- AWGN gain (MSB)
signal REG33: std_logic_vector(7 downto 0) := x"E1";	-- multicast IP address, LAN#1 (MSB)
signal REG34: std_logic_vector(7 downto 0) := x"00";	
signal REG35: std_logic_vector(7 downto 0) := x"00";	
signal REG36: std_logic_vector(7 downto 0) := x"01";	-- multicast IP address, LAN#1 (LSB)
signal REG37: std_logic_vector(7 downto 0) := x"AC";	-- static IP address, LAN#1 (MSB)
signal REG38: std_logic_vector(7 downto 0) := x"10";	
signal REG39: std_logic_vector(7 downto 0) := x"01";
	
signal REG40: std_logic_vector(7 downto 0) := x"01";	-- static IP address, LAN#1 (LSB)
signal REG41: std_logic_vector(7 downto 0) := x"AC";	-- static IP address, LAN#2 (MSB)
signal REG42: std_logic_vector(7 downto 0) := x"10";	
signal REG43: std_logic_vector(7 downto 0) := x"01";	
signal REG44: std_logic_vector(7 downto 0) := x"02";	-- static IP address, LAN#2 (LSB)
signal REG45: std_logic_vector(7 downto 0) := x"AC";	-- destination IP address for demodulated data (MSB)
signal REG46: std_logic_vector(7 downto 0) := x"10";	
signal REG47: std_logic_vector(7 downto 0) := x"01";	
signal REG48: std_logic_vector(7 downto 0) := x"b6";	-- destination IP address for demodulated data (LSB)
signal REG49: std_logic_vector(7 downto 0) := x"01";	-- destination IP port for demodulated data (LSB)

signal REG50: std_logic_vector(7 downto 0) := x"04";	-- MSB
signal REG51: std_logic_vector(7 downto 0) := x"FF";	-- Subnet mask (MSB)
signal REG52: std_logic_vector(7 downto 0) := x"FF";	
signal REG53: std_logic_vector(7 downto 0) := x"FF";	
signal REG54: std_logic_vector(7 downto 0) := x"00";	-- Subnet mask (LSB)
signal REG55: std_logic_vector(7 downto 0) := x"AC";	-- Gateway IP address (MSB)
signal REG56: std_logic_vector(7 downto 0) := x"10";	
signal REG57: std_logic_vector(7 downto 0) := x"01";	
signal REG58: std_logic_vector(7 downto 0) := x"03";	-- Gateway IP address (LSB)
signal REG59: std_logic_vector(7 downto 0) := x"c8";	-- COM-350X controls

signal REG60: std_logic_vector(7 downto 0) := x"10";	-- alternating I/Q bits, 1/2 symbol Q delay, COM-350X controls
signal REG61: std_logic_vector(7 downto 0) := x"C6";	-- modulator on, SQPN/BPSK, same/different data on I/Q
signal REG62: std_logic_vector(7 downto 0) := x"12";	-- I-code (LSB)  code 40   2225o
signal REG63: std_logic_vector(7 downto 0) := x"25";	-- MSB + modulator inputs selection
signal REG64: std_logic_vector(7 downto 0) := x"9b"; -- Q-code (LSB)  code 40 1337o
signal REG65: std_logic_vector(7 downto 0) := x"2f";	-- MSB + modulator inputs selection
signal REG66: std_logic_vector(7 downto 0) := x"30";	-- modulator chip rate (LSB)
signal REG67: std_logic_vector(7 downto 0) := x"A7";	
signal REG68: std_logic_vector(7 downto 0) := x"4D";	
signal REG69: std_logic_vector(7 downto 0) := x"06";	-- modulator chip rate (MSB)

signal REG70: std_logic_vector(7 downto 0) := x"51";	-- modulator I symbol rate 
signal REG71: std_logic_vector(7 downto 0) := x"49";	
signal REG72: std_logic_vector(7 downto 0) := x"9D";	
signal REG73: std_logic_vector(7 downto 0) := x"00";	
signal REG74: std_logic_vector(7 downto 0) := x"51";    -- modulator Q symbol rate
signal REG75: std_logic_vector(7 downto 0) := x"49";
signal REG76: std_logic_vector(7 downto 0) := x"9D";	
signal REG77: std_logic_vector(7 downto 0) := x"00";	
signal REG78: std_logic_vector(7 downto 0) := x"00";	-- output center frequency (LSB)
signal REG79: std_logic_vector(7 downto 0) := x"00";
	 
signal REG80: std_logic_vector(7 downto 0) := x"00";
signal REG81: std_logic_vector(7 downto 0) := x"00";	-- output center frequency (MSB)


-- Baseline
--signal REG0: std_logic_vector(7 downto 0) := x"00";	-- demod input selection: UDP (1) vs TCP (0)
--signal REG1: std_logic_vector(7 downto 0) := x"12";	-- I-code (LSB)  code 40   2225o
--signal REG2: std_logic_vector(7 downto 0) := x"2d";
--signal REG3: std_logic_vector(7 downto 0) := x"9b"; -- Q-code (LSB)  code 40 1337o
--signal REG4: std_logic_vector(7 downto 0) := x"07";	
--signal REG5: std_logic_vector(7 downto 0) := x"41";	-- chip rate (LSB)
--signal REG6: std_logic_vector(7 downto 0) := x"A7";	
--signal REG7: std_logic_vector(7 downto 0) := x"4D";	
--signal REG8: std_logic_vector(7 downto 0) := x"06";	-- chip rate (MSB)
--signal REG9: std_logic_vector(7 downto 0) := x"a9";	-- I symbol rate 100 Kbps
--signal REG10: std_logic_vector(7 downto 0) := x"a4";	
--signal REG11: std_logic_vector(7 downto 0) := x"4e";	
--signal REG12: std_logic_vector(7 downto 0) := x"00";	
--signal REG9: std_logic_vector(7 downto 0) := x"38";	-- I symbol rate 1Kbps
--signal REG10: std_logic_vector(7 downto 0) := x"86";	
--signal REG11: std_logic_vector(7 downto 0) := x"00";	
--signal REG12: std_logic_vector(7 downto 0) := x"00";	
--signal REG13: std_logic_vector(7 downto 0) := x"a9";    -- Q symbol rate
--signal REG14: std_logic_vector(7 downto 0) := x"a4";
--signal REG15: std_logic_vector(7 downto 0) := x"4e";	
--signal REG16: std_logic_vector(7 downto 0) := x"00";	
--signal REG17: std_logic_vector(7 downto 0) := x"14";	-- I spreading factor 100Kbps
--signal REG18: std_logic_vector(7 downto 0) := x"00";	
--signal REG17: std_logic_vector(7 downto 0) := x"05";	-- I spreading factor 1Kbps
--signal REG18: std_logic_vector(7 downto 0) := x"0C";	
--signal REG19: std_logic_vector(7 downto 0) := x"14";	-- Q spreading factor
--signal REG20: std_logic_vector(7 downto 0) := x"00";
--signal REG21: std_logic_vector(7 downto 0) := x"00";	-- nominal input center frequency (LSB)
--signal REG22: std_logic_vector(7 downto 0) := x"00";	 
--signal REG23: std_logic_vector(7 downto 0) := x"00";
--signal REG24: std_logic_vector(7 downto 0) := x"00";
--signal REG25: std_logic_vector(7 downto 0) := x"00";	-- reserved (for scanning)
--signal REG26: std_logic_vector(7 downto 0) := x"00";	-- controls (LSB)
--signal REG27: std_logic_vector(7 downto 0) := x"04";	-- controls (MSB)
--signal REG28: std_logic_vector(7 downto 0) := x"89";	-- AGC response time, loopback mode
--signal REG29: std_logic_vector(7 downto 0) := x"20";	-- modulator signal gain (LSB)
--signal REG30: std_logic_vector(7 downto 0) := x"4e";	-- modulator signal gain (MSB) 
--signal REG31: std_logic_vector(7 downto 0) := x"00";	-- AWGN gain (LSB) 
--signal REG32: std_logic_vector(7 downto 0) := x"00";	-- AWGN gain (MSB)
--signal REG33: std_logic_vector(7 downto 0) := x"E1";	-- multicast IP address, LAN#1 (MSB)
--signal REG34: std_logic_vector(7 downto 0) := x"00";	
--signal REG35: std_logic_vector(7 downto 0) := x"00";	
--signal REG36: std_logic_vector(7 downto 0) := x"01";	-- multicast IP address, LAN#1 (LSB)
--signal REG37: std_logic_vector(7 downto 0) := x"AC";	-- static IP address, LAN#1 (MSB)
--signal REG38: std_logic_vector(7 downto 0) := x"10";	
--signal REG39: std_logic_vector(7 downto 0) := x"01";	
--signal REG40: std_logic_vector(7 downto 0) := x"01";	-- static IP address, LAN#1 (LSB)
--signal REG41: std_logic_vector(7 downto 0) := x"AC";	-- static IP address, LAN#2 (MSB)
--signal REG42: std_logic_vector(7 downto 0) := x"10";	
--signal REG43: std_logic_vector(7 downto 0) := x"01";	
--signal REG44: std_logic_vector(7 downto 0) := x"02";	-- static IP address, LAN#2 (LSB)
--signal REG45: std_logic_vector(7 downto 0) := x"AC";	-- destination IP address for demodulated data (MSB)
--signal REG46: std_logic_vector(7 downto 0) := x"10";	
--signal REG47: std_logic_vector(7 downto 0) := x"01";	
--signal REG48: std_logic_vector(7 downto 0) := x"44";	-- destination IP address for demodulated data (LSB)
--signal REG49: std_logic_vector(7 downto 0) := x"01";	-- destination IP port for demodulated data (LSB)
--signal REG50: std_logic_vector(7 downto 0) := x"04";	-- MSB
--signal REG51: std_logic_vector(7 downto 0) := x"FF";	-- Subnet mask (MSB)
--signal REG52: std_logic_vector(7 downto 0) := x"FF";	
--signal REG53: std_logic_vector(7 downto 0) := x"FF";	
--signal REG54: std_logic_vector(7 downto 0) := x"00";	-- Subnet mask (LSB)
--signal REG55: std_logic_vector(7 downto 0) := x"AC";	-- Gateway IP address (MSB)
--signal REG56: std_logic_vector(7 downto 0) := x"10";	
--signal REG57: std_logic_vector(7 downto 0) := x"01";	
--signal REG58: std_logic_vector(7 downto 0) := x"03";	-- Gateway IP address (LSB)
--signal REG59: std_logic_vector(7 downto 0) := x"c8";	-- COM-350X controls
--signal REG60: std_logic_vector(7 downto 0) := x"10";	-- alternating I/Q bits, 1/2 symbol Q delay, COM-350X controls
--signal REG61: std_logic_vector(7 downto 0) := x"80";	-- modulator on, SQPN/BPSK, same/different data on I/Q
--signal REG62: std_logic_vector(7 downto 0) := x"12";	-- I-code (LSB)  code 40   2225o
--signal REG63: std_logic_vector(7 downto 0) := x"25";	-- MSB + modulator inputs selection
--signal REG64: std_logic_vector(7 downto 0) := x"9b"; -- Q-code (LSB)  code 40 1337o
--signal REG65: std_logic_vector(7 downto 0) := x"07";	-- MSB + modulator inputs selection
--signal REG66: std_logic_vector(7 downto 0) := x"41";	-- modulator chip rate (LSB)
--signal REG67: std_logic_vector(7 downto 0) := x"A7";	
--signal REG68: std_logic_vector(7 downto 0) := x"4D";	
--signal REG69: std_logic_vector(7 downto 0) := x"06";	-- modulator chip rate (MSB)
--signal REG70: std_logic_vector(7 downto 0) := x"a9";	-- modulator I symbol rate 100 Kbps
--signal REG71: std_logic_vector(7 downto 0) := x"a4";	
--signal REG72: std_logic_vector(7 downto 0) := x"4e";	
--signal REG73: std_logic_vector(7 downto 0) := x"00";	
--signal REG74: std_logic_vector(7 downto 0) := x"a9";    -- modulator Q symbol rate
--signal REG75: std_logic_vector(7 downto 0) := x"a4";
--signal REG76: std_logic_vector(7 downto 0) := x"4e";	
--signal REG77: std_logic_vector(7 downto 0) := x"00";	
--signal REG78: std_logic_vector(7 downto 0) := x"00";	-- output center frequency (LSB)
--signal REG79: std_logic_vector(7 downto 0) := x"00";	 
--signal REG80: std_logic_vector(7 downto 0) := x"00";
--signal REG81: std_logic_vector(7 downto 0) := x"00";	-- output center frequency (MSB)
--


signal REG255: std_logic_vector(7 downto 0) := (others => '0');
signal REG236: std_logic_vector(7 downto 0) := (others => '0');	-- MAC address LSB (to be defined at manufacturing)

--// User-defined status Registers (add as needed)
signal SREG7: std_logic_vector(7 downto 0) := (others => '0');
signal SREG8: std_logic_vector(7 downto 0) := (others => '0');
signal SREG9: std_logic_vector(7 downto 0) := (others => '0');
signal SREG10: std_logic_vector(7 downto 0) := (others => '0');
signal SREG11: std_logic_vector(7 downto 0) := (others => '0');
signal SREG12: std_logic_vector(7 downto 0) := (others => '0');
signal SREG13: std_logic_vector(7 downto 0) := (others => '0');
signal SREG14: std_logic_vector(7 downto 0) := (others => '0');
signal SREG15: std_logic_vector(7 downto 0) := (others => '0');
signal SREG16: std_logic_vector(7 downto 0) := (others => '0');
signal SREG17: std_logic_vector(7 downto 0) := (others => '0');
signal SREG18: std_logic_vector(7 downto 0) := (others => '0');
signal SREG19: std_logic_vector(7 downto 0) := (others => '0');
signal SREG20: std_logic_vector(7 downto 0) := (others => '0');
signal SREG21: std_logic_vector(7 downto 0) := (others => '0');
signal SREG22: std_logic_vector(7 downto 0) := (others => '0');
signal SREG23: std_logic_vector(7 downto 0) := (others => '0');
signal SREG24: std_logic_vector(7 downto 0) := (others => '0');
signal SREG25: std_logic_vector(7 downto 0) := (others => '0');
signal SREG26: std_logic_vector(7 downto 0) := (others => '0');
signal SREG27: std_logic_vector(7 downto 0) := (others => '0');
signal SREG28: std_logic_vector(7 downto 0) := (others => '0');
signal SREG29: std_logic_vector(7 downto 0) := (others => '0');
signal SREG30: std_logic_vector(7 downto 0) := (others => '0');
signal SREG31: std_logic_vector(7 downto 0) := (others => '0');
signal SREG32: std_logic_vector(7 downto 0) := (others => '0');
signal SREG33: std_logic_vector(7 downto 0) := (others => '0');
signal SREG34: std_logic_vector(7 downto 0) := (others => '0');
signal SREG35: std_logic_vector(7 downto 0) := (others => '0');
signal SREG36: std_logic_vector(7 downto 0) := (others => '0');
signal SREG37: std_logic_vector(7 downto 0) := (others => '0');
signal SREG38: std_logic_vector(7 downto 0) := (others => '0');
signal SREG39: std_logic_vector(7 downto 0) := (others => '0');
signal SREG40: std_logic_vector(7 downto 0) := (others => '0');
signal SREG41: std_logic_vector(7 downto 0) := (others => '0');
signal SREG42: std_logic_vector(7 downto 0) := (others => '0');
signal SREG43: std_logic_vector(7 downto 0) := (others => '0');
signal SREG44: std_logic_vector(7 downto 0) := (others => '0');
signal SREG45: std_logic_vector(7 downto 0) := (others => '0');
signal SREG46: std_logic_vector(7 downto 0) := (others => '0');
signal SREG47: std_logic_vector(7 downto 0) := (others => '0');
signal SREG48: std_logic_vector(7 downto 0) := (others => '0');
signal SREG49: std_logic_vector(7 downto 0) := (others => '0');
signal SREG50: std_logic_vector(7 downto 0) := (others => '0');
signal SREG51: std_logic_vector(7 downto 0) := (others => '0');
signal SREG52: std_logic_vector(7 downto 0) := (others => '0');
signal SREG53: std_logic_vector(7 downto 0) := (others => '0');
signal SREG54: std_logic_vector(7 downto 0) := (others => '0');
signal SREG55: std_logic_vector(7 downto 0) := (others => '0');
signal SREG56: std_logic_vector(7 downto 0) := (others => '0');
signal SREG57: std_logic_vector(7 downto 0) := (others => '0');
signal SREG58: std_logic_vector(7 downto 0) := (others => '0');
signal SREG59: std_logic_vector(7 downto 0) := (others => '0');
signal SREG60: std_logic_vector(7 downto 0) := (others => '0');
signal SREG61: std_logic_vector(7 downto 0) := (others => '0');
signal SREG62: std_logic_vector(7 downto 0) := (others => '0');
signal SREG63: std_logic_vector(7 downto 0) := (others => '0');
signal SREG64: std_logic_vector(7 downto 0) := (others => '0');
signal SREG65: std_logic_vector(7 downto 0) := (others => '0');
signal SREG66: std_logic_vector(7 downto 0) := (others => '0');
signal SREG67: std_logic_vector(7 downto 0) := (others => '0');
signal SREG68: std_logic_vector(7 downto 0) := (others => '0');
signal SREG69: std_logic_vector(7 downto 0) := (others => '0');
signal SREG7_READ_TOGGLE: std_logic := '0';
signal SREG7_READ_TOGGLE_D: std_logic := '0';
signal SREG7_READ_TOGGLE_D2: std_logic := '0';
signal LATCH_MONITORING_PULSE: std_logic := '0';
signal SREG254_READ_TOGGLE: std_logic := '0';			

--// ComScope control registers
signal REG237: std_logic_vector(7 downto 0):= "00000000";
signal REG238: std_logic_vector(7 downto 0):= "00000000";
signal REG239: std_logic_vector(7 downto 0):= "00000000";
signal REG240: std_logic_vector(7 downto 0):= "00001101";	-- Trace 1 signal selection
signal REG241: std_logic_vector(7 downto 0):= "00000000";	-- Trigger position, decimation
signal REG242: std_logic_vector(7 downto 0):= "00001110";	-- Trace 2 signal selection
signal REG243: std_logic_vector(7 downto 0):= "00000000";	-- Trigger position, decimation
signal REG244: std_logic_vector(7 downto 0):= "00000000";	-- Trace 3 signal selection
signal REG245: std_logic_vector(7 downto 0):= "00000000";	-- Trigger position, decimation
signal REG246: std_logic_vector(7 downto 0):= "00000000";	-- Trace 4 signal selection
signal REG247: std_logic_vector(7 downto 0):= "00000000";	-- Trigger position, decimation
signal REG248: std_logic_vector(7 downto 0):= "10001101";	-- Trigger edge, trigger signal
signal REG249: std_logic_vector(7 downto 0):= "10111111";	-- Trigger threshold
signal REG250: std_logic_vector(7 downto 0):= "00000000";
signal REG251: std_logic_vector(7 downto 0):= "00000000";

--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin
--// CLOCKS, RESET ---------------------
-- if OPTION = 'A' or 'C' (ASCII 0x41/43), frequency reference is 19.2 MHz VCTCXO on the board.
-- Frequency plan: 19.2 MHz -> 10 MHz -> 125 MHz processing clock
-- if OPTION = 'B' or 'D' (ASCII 0x42/44), frequency reference is external 10 MHz VCTCXO on the board. Must be present at power up otherwise nothing will work.
-- Frequency plan: 10 MHz -> 125 MHz processing clock

CLK10_GEN: if(SIMULATION = '1') generate
	 -- 10 MHz
    process
    begin
        CLK10g <= '0';
        wait for 50 ns;
        CLK10g <= '1';
        wait for 50 ns;
    end process;
	 CLKGEN7C_LOCKED <= '1';
	 CLKGEN7C_INPUT_CLK_STOPPED <= '0';

    -- 19.2 MHz
    process
    begin
        CLKREF_TCXOg <= '0';
        wait for 26.04 ns;
        CLKREF_TCXOg <= '1';
        wait for 26.04 ns;
    end process;

--	 -- 25 MHz 
--    process
--    begin
--        CLKREF25Bg <= '0';
--        wait for 20.0 ns;
--        CLKREF25Bg <= '1';
--        wait for 20.0 ns;
--    end process;
	 
end generate;

---- regenerate the 25 MHz clock
--  plle2_adv_inst : PLLE2_ADV
--generic map
-- (BANDWIDTH            => "LOW",
--
--  
--  COMPENSATION         => "ZHOLD",
--  DIVCLK_DIVIDE        => 1,
--  CLKFBOUT_MULT        => 32,
--  CLKFBOUT_PHASE       => 0.000,
--  CLKOUT0_DIVIDE       => 32,
--  CLKOUT0_PHASE        => 0.000,
--  CLKOUT0_DUTY_CYCLE   => 0.500,
--  CLKIN1_PERIOD        => 40.0)
--port map
--  -- Output clocks
-- (
--  CLKFBOUT            => PLL25_CLKFB,
--  CLKOUT0             => CLKREF25Cg,
--  CLKOUT1             => open,
--  CLKOUT2             => open,
--  CLKOUT3             => open,
--  CLKOUT4             => open,
--  CLKOUT5             => open,
--  -- Input clock control
--  CLKFBIN             => PLL25_CLKFB,
--  CLKIN1              => CLKREF25Bg,
--  CLKIN2              => '0',
--  -- Tied to always select the primary input clock
--  CLKINSEL            => '1',
--  -- Ports for dynamic reconfiguration
--  DADDR               => (others => '0'),
--  DCLK                => '0',
--  DEN                 => '0',
--  DI                  => (others => '0'),
--  DO                  => open,
--  DRDY                => open,
--  DWE                 => '0',
--  -- Other control and status signals
--  LOCKED              => PLL25_LOCKED,
--  PWRDWN              => '0',
--  RST                 => not RESET_COUNTER(17));
--

-- generate 10 MHz from 19.2 MHz VCTCXO + BUFG 25 MHz crystal oscillator
INTERNAL_FREQ_REF: if ((OPTION = x"41")or (OPTION = x"43")) and (SIMULATION = '0') generate
	BUFG_001: BUFG port map(I => CLKREF_TCXO, O=> CLKREF_TCXOg);
--	BUFG_002: BUFG port map(I => CLKREF25B, O=> CLKREF25Bg);
	BUFG_003: BUFG port map (I => CLK10, O => CLK10g);

	CLKGEN7C: CLKGEN7_MMCM_ADJ 
	GENERIC MAP(
		CLKFBOUT_MULT_F => 50.000,
        CLKOUT0_DIVIDE_F => 96.000,
        CLKIN1_PERIOD => 52.083
    ) 
    PORT MAP(
        CLK_IN1 => CLKREF_TCXOg,	-- 19.2 MHz TCXO clock 
        CLK_OUT1 => CLK10,	-- 10 MHz not global
        INPUT_CLK_STOPPED => CLKGEN7C_INPUT_CLK_STOPPED,
        LOCKED => CLKGEN7C_LOCKED
    );
end generate;

-- OR use external 10 MHz frequency reference
EXTERNAL_FREQ_REF: if((OPTION = x"42")or (OPTION = x"44")) and (SIMULATION = '0') generate
--	BUFG_002: BUFG port map(I => CLKREF25B, O=> CLKREF25Bg);
	BUFG_003: BUFG port map (I => CLKREF_EXT, O => CLK10g);
end generate;

-- generate 125 MHz processing clock from 10 MHz reference
CLKGEN7D: CLKGEN7_MMCM_ADJ 
GENERIC MAP(
	CLKFBOUT_MULT_F => 62.500,
	CLKOUT0_DIVIDE_F => 5.000,
	CLKIN1_PERIOD => 100.000
 ) 
PORT MAP(
	CLK_IN1 => CLK10g,	-- 10 MHz 
	CLK_OUT1 => CLK125_0,	-- 125 MHz not global
	INPUT_CLK_STOPPED => CLKGEN7D_INPUT_CLK_STOPPED,
	LOCKED => CLKGEN7D_LOCKED
);
BUFG_002: BUFG port map(I => CLK125_0, O => CLK_P);

-- generate multiple offsets for the 125 MHz clock 
-- Includes several delayed versions for LAN PHY and DAC 
PLLE2_RST <= not RESET_COUNTER(17);
  plle2_002 : PLLE2_ADV
generic map
 (BANDWIDTH            => "LOW",

  
  COMPENSATION         => "ZHOLD",
  DIVCLK_DIVIDE        => 1,
  CLKFBOUT_MULT        => 8,
  CLKFBOUT_PHASE       => 0.000,
  CLKOUT0_DIVIDE       => 8,	-- for LAN PHY 
  CLKOUT0_PHASE        => 22.5,	-- must be in the form 45deg*integer*125MHz/1GHz. 90deg = 2ns delay @125 MHz
  CLKOUT0_DUTY_CYCLE   => 0.500,
  CLKOUT1_DIVIDE       => 8,	-- for DAC clock
  CLKOUT1_PHASE        => 45.0,	-- FISHY.... UNITS ARE DEG..0.2 IS SO SMALL AS TO BE INCONSEQUENTIAL?
  CLKOUT1_DUTY_CYCLE   => 0.500,
  CLKOUT2_DIVIDE       => 40,	-- for LAN PHY 25 MHz clock
  CLKOUT2_PHASE        => 0.0,	
  CLKOUT2_DUTY_CYCLE   => 0.500,
  CLKIN1_PERIOD        => 8.0)
port map
  -- Output clocks
 (
  CLKFBOUT            => CLK_P_FB,
  CLKOUT0             => CLK125_1,
  CLKOUT1             => CLK125_2,
  CLKOUT2             => CLK25,
  CLKOUT3             => open,
  CLKOUT4             => open,
  CLKOUT5             => open,
  -- Input clock control
  CLKFBIN             => CLK_P_FB,
  CLKIN1              => CLK_P,
  CLKIN2              => '0',
  -- Tied to always select the primary input clock
  CLKINSEL            => '1',
  -- Ports for dynamic reconfiguration
  DADDR               => (others => '0'),
  DCLK                => '0',
  DEN                 => '0',
  DI                  => (others => '0'),
  DO                  => open,
  DRDY                => open,
  DWE                 => '0',
  -- Other control and status signals
  LOCKED              => open,
  PWRDWN              => '0',
  RST                 => PLLE2_RST
);
-- doubt: is the CLK125_1 signal propagation time nearly constant, or will it need to be compensated for every 
-- P&R? If so, maybe we should use a BUFG or BUFR to have more consistent timing control?

SREG9(2 downto 0) <= DDR3_PLL_LOCKED_OUT & CLKGEN7D_LOCKED & CLKGEN7C_LOCKED;


RESET_STATE_MACHINE_001A: if((OPTION = x"41")or (OPTION = x"43")) generate
    -- Generate miscellaneous global clocks and resets from the 
    -- reference 19.2 MHz clock (VCTCXO)
    RESET_STATE_MACHINE_001: process(CLKREF_TCXOg)
    begin
        if rising_edge(CLKREF_TCXOG) then
            -- PLL need time to lock. The reset of the application is still in reset
            if(RESET_COUNTER(17) = '0') and (SIMULATION = '0') then
                -- wait a bit before asserting the PLL lock
                RESET_COUNTER <= RESET_COUNTER + 1;
            elsif(RESET_COUNTER(5) = '0') and (SIMULATION = '1') then  
                -- make it short during simulations
                -- wait a bit before asserting the PLL lock
                RESET_COUNTER <= RESET_COUNTER + 1;
            elsif((CLKGEN7C_LOCKED = '1') or  (SIMULATION = '1')) and (CLKGEN7D_LOCKED = '1') 
				and ((DDR3_ENABLED = '0') or (DDR3_PLL_LOCKED_OUT = '1')) then
                -- wait until all used PLLs are locked
                RESET_STATE <= 1;
            end if;
            
            if(RESET_STATE = 1) then
                ASYNC_RESET <= '0';
            else
                ASYNC_RESET <= '1';
            end if;
        end if;
    end process;
end generate;

RESET_STATE_MACHINE_001B: if((OPTION = x"42")or (OPTION = x"44")) generate
    -- Generate miscellaneous global clocks and resets from the 
    -- external reference 10 MHz clock 
    RESET_STATE_MACHINE_001: process(CLK10g)
    begin
        if rising_edge(CLK10g) then
            -- PLL need time to lock. The reset of the application is still in reset
            if(RESET_COUNTER(17) = '0') and (SIMULATION = '0') then
                -- wait a bit before asserting the PLL lock
                RESET_COUNTER <= RESET_COUNTER + 1;
            elsif(RESET_COUNTER(5) = '0') and (SIMULATION = '1') then  
                -- make it short during simulations
                -- wait a bit before asserting the PLL lock
                RESET_COUNTER <= RESET_COUNTER + 1;
            elsif(CLKGEN7D_LOCKED = '1') and ((DDR3_ENABLED = '0') or (DDR3_PLL_LOCKED_OUT = '1')) then
                -- assert the PLL lock
                RESET_STATE <= 1;
            end if;
            
            if(RESET_STATE = 1) then
                ASYNC_RESET <= '0';
            else
                ASYNC_RESET <= '1';
            end if;
        end if;
    end process;
end generate;


-- generate a reset synchronous with CLK_P at the end of the ASYNC_RESET
SYNC_RESET_CLK_P_GEN: process(ASYNC_RESET, CLK_P)
begin
	if rising_edge(CLK_P) then
		ASYNC_RESET_D <= ASYNC_RESET;
		ASYNC_RESET_D2 <= ASYNC_RESET_D;
		
		if(ASYNC_RESET_D = '0') and (ASYNC_RESET_D2 = '1')  then
			SYNC_RESET_CLK_P <= '1';
		else
			SYNC_RESET_CLK_P <= '0';
		end if;
		
		-- '0' from power-up/async_reset until FPGA is ready
		if(SYNC_RESET_CLK_P = '1') then
			READY_FLAG_CLK_P <= '1';
		end if;
	end if;
end process;
READY_FLAG_CLK_Pn <= not READY_FLAG_CLK_P;

	-- external input clock
BUFG_006: BUFG  port map (I=> UC_WEB_IN, O=> UC_WEBG);	
	-- ARM WE#
BUFG_007: BUFG  port map (I=> UC_REB_IN, O=> UC_REBG);	
	-- ARM RE#

-- 1s tick
TICK1S_001: TIMER_4US 
GENERIC MAP(
	CLK_FREQUENCY => CLK_FREQUENCY
)
PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => SYNC_RESET_CLK_P,
	TICK_4US => TICK_4US,
	TICK_100MS => TICK_100MS
);
	
-- modulo-10 counter. 1s tick
TICK1S_002: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(SYNC_RESET_CLK_P = '1') then
			TICK_100MS_CNTR <= "0000";
			TICK_1S <= '0';
		elsif(TICK_100MS = '1') then
			if(TICK_100MS_CNTR = 0) then
				TICK_100MS_CNTR <= "1001";
				TICK_1S <= '1';
			else
				TICK_100MS_CNTR <= TICK_100MS_CNTR - 1;
				TICK_1S <= '0';
			end if;
		else
			TICK_1S <= '0';
		end if;
	end if;
end process;

--//-- ETHERNET MAC#1  -----------------------------------
LAN1_AVAILABLE <= '1' when ((OPTION = x"41") or (OPTION = x"42")) or (ADCs_EN = '0') else '0';
    -- LAN1 is not available when COM-30XX is plugged into the left connector
    -- In this case, we route all LAN1 signals to LAN2 and disable SDSS inputs
ETH1_GEN: if ((OPTION = x"41") or (OPTION = x"42")) or (ADCs_EN = '0') generate
    -- Use left connector for LAN1/user data interface when right connector goes to COM-3504
    -- Interface with COM-5401 PHY#1 or COM-5102 PHY. (Micrel KSZ9021)
    -- Limit support to 10/100 Mbps
    CLK_SKEW11 <= x"77C4";	-- re-optimized after swapping LAN ports 7/19/16  
    CLK_SKEW12 <= x"7777";	
        
    --MAC address automatically generated from unique DNA_ID
    LAN1_MAC_ADDR <= x"02" & DNA_ID_DATA(31 downto 0) & REG236(7 downto 1) & "1";    -- possible race condition: ARM vs DNA_ID?
    LAN1_RXC <= LEFT_CONNECTOR_A(1);
    LAN1_RX_CTL <= LEFT_CONNECTOR_A(2);
    LAN1_RXD(3 downto 0) <= LEFT_CONNECTOR_A(6 downto 3);
    LEFT_CONNECTOR_A(6 downto 1) <=  (others => 'Z');	-- Input-only: make sure that out is tri-stated.
    LEFT_CONNECTOR_A(7) <= LAN1_TXC;
    LEFT_CONNECTOR_A(8) <= LAN1_TX_CTL;
    LEFT_CONNECTOR_A(12 downto 9) <= LAN1_TXD(3 downto 0); 
    LEFT_CONNECTOR_A(14 downto 13) <= (others => 'Z');	-- Input-only: make sure that out is tri-stated.
    LEFT_CONNECTOR_A(15) <= LAN1_RESET_N;
    LEFT_CONNECTOR_A(16) <= LAN1_MCLK;
    
    -- IMPORTANT: CUSTOM MODIFICATION OF COM5401. Uses BUFR regional buffer instead of BUFG for RXC 
    -- input clock. Goal save a couple of ns timing. (PHY can only adjust timing over 15 steps of 0.2ns
    -- not enough for Artix-7 timing).
    LAN_001: COM5401 
    GENERIC MAP(
        MII_SEL => '0',   	   -- select which MII interface: 0 = RGMII, 1 = GMII/MII
        PHY_ADDR => "00100",   -- PHY_AD0/1 pulled-down by 1KOhm, PHY_AD2 pulled-up in .xdc file.
        CLK_FREQUENCY => CLK_FREQUENCY,
        PLATFORM => 7,	       -- 7 series Xilinx FPGA
        TARGET_PHY => 2,       -- target PHY: KSZ9021
        NO_1000 => '1',	-- limited to 10/100 Mbps
        INTERNAL_PHY_TX_CLKS_DELAYS => '1',
        INTERNAL_PHY_RX_CLKS_DELAYS => '0',
        SIMULATION => SIMULATION
    )
    PORT MAP(
        CLK => CLK_P,
        SYNC_RESET => READY_FLAG_CLK_Pn,	-- new 12/9/15 more reliable start
        CLK125_0 => CLK_P,
        CLK125_1 => CLK125_1,
        CLK25 => CLK25,
        MAC_TX_CONFIG => X"0003",	-- MAC must must provide pad + crc32
        MAC_RX_CONFIG => x"000F",	-- promiscuous mode, strip crc32, accept broadcast/multicast
        MAC_ADDR => LAN1_MAC_ADDR,
        PHY_CONFIG_CHANGE => LAN_ADDR_CHANGE_PULSE,		-- *080416
        PHY_RESET => '0',
        SPEED => "11",	-- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
        DUPLEX => '1',	-- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
        TEST_MODE => "00",	-- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
        POWER_DOWN => '0', -- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
        CLK_SKEW1 => CLK_SKEW11, -- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
        CLK_SKEW2 => CLK_SKEW12, -- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
        MAC_TX_DATA => LAN1_MAC_TX_DATA,
        MAC_TX_DATA_VALID => LAN1_MAC_TX_DATA_VALID,
        MAC_TX_EOF => LAN1_MAC_TX_EOF,
        MAC_TX_CTS => LAN1_MAC_TX_CTS,
        MAC_RX_DATA => LAN1_MAC_RX_DATA,	
        MAC_RX_DATA_VALID => LAN1_MAC_RX_DATA_VALID,
        MAC_RX_SOF => LAN1_MAC_RX_SOF,
        MAC_RX_EOF => LAN1_MAC_RX_EOF,
        MAC_RX_CTS => '1',  -- follow-on processing is expected to always accept data even at max speed.
        -- RGMII interface ----------------
        TXC => LAN1_TXC,	
        TXD => LAN1_TXD,
        TX_CTL => LAN1_TX_CTL,
        RXC => LAN1_RXC,
        RXD => LAN1_RXD,
        RX_CTL => LAN1_RX_CTL,
        RESET_N => LAN1_RESET_N,
        MCLK => LAN1_MCLK,
        MDIO => LEFT_CONNECTOR_A(17),	-- PHY#1
        -- end of RGMII interface --------
        MII_TX_CLK => '0',	-- MII interface is unused -----
        GMII_TX_CLK => open,
        GMII_MII_TXD => open,
        GMII_MII_TX_EN => open,
        GMII_MII_TX_ER => open,
        GMII_MII_CRS => '0',
        GMII_MII_COL => '0',
        GMII_MII_RX_CLK => '0',
        GMII_MII_RXD => x"00",
        GMII_MII_RX_DV => '0',
        GMII_MII_RX_ER => '0',  -- end of MII interface ------
        LINK_STATUS => LAN1_LINK_STATUS,
        SPEED_STATUS => LAN1_SPEED_STATUS,
        DUPLEX_STATUS => LAN1_DUPLEX_STATUS,
        PHY_ID => LAN1_PHY_ID,
        N_RX_FRAMES => LAN1_N_RX_FRAMES,
        N_RX_BAD_CRCS => LAN1_N_RX_BAD_CRCS,
        N_RX_FRAMES_TOO_SHORT => LAN1_N_RX_FRAMES_TOO_SHORT,
        N_RX_FRAMES_TOO_LONG => LAN1_N_RX_FRAMES_TOO_LONG,
        N_RX_WRONG_ADDR => LAN1_N_RX_WRONG_ADDR,
        N_RX_LENGTH_ERRORS => LAN1_N_RX_LENGTH_ERRORS,
        CS_CLKG => open,
        CS1 => open,
        CS1_CLK => open,
        CS2 => open,
        CS2_CLK => open,
        CT1 => open,
        CT1_CLK => open,
        TP => LAN1_TP
    );
    
    
    -- hardware test: read PHY_ID
    SREG7 <= LAN1_PHY_ID(7 downto 0);
end generate;    

--//-- ETHERNET MAC#2  -----------------------------------
-- Interface with on-board GbE PHY: Micrel KSZ9031
-- Support 10/100/1000 Ethernet LAN.
-- Note: COM-1800 hardware rev 0 and 1 are limited to 100 Mbps unless the 25 MHz MEMS oscillator is replaced with
-- a low-jitter crystal-based oscillator (done in hw rev2)
CLK_SKEW21 <= x"0310"; 	 --(INTERNAL_PHY_CLKS_DELAYS => '0')
CLK_SKEW22 <= x"0000";    -- future	

-- new: MAC address automatically generated from unique DNA_ID
LAN2_MAC_ADDR <= x"02" & DNA_ID_DATA(31 downto 0) & REG236(7 downto 1) & "0";    -- possible race condition: ARM vs DNA_ID?
LAN_002: COM5401 
GENERIC MAP(
	MII_SEL => '0',   	   -- select which MII interface: 0 = RGMII, 1 = GMII/MII
	PHY_ADDR => "00111",   -- PHY_AD0/1 pulled-up, PHY_AD2 pulled-up in .xdc file.
	CLK_FREQUENCY => CLK_FREQUENCY,
	PLATFORM => 7,	       -- 7 series Xilinx FPGA
	TARGET_PHY => 3,       -- target PHY: KSZ9031
	NO_1000 => '0',	-- advertize full 10/100/1000 Mbps
	INTERNAL_PHY_TX_CLKS_DELAYS => '0',
	INTERNAL_PHY_RX_CLKS_DELAYS => '0',
	SIMULATION => SIMULATION
)
PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => READY_FLAG_CLK_Pn,	-- new 12/9/15 more reliable start
	CLK125_0 => CLK_P,
	CLK125_1 => CLK125_1,
	CLK25 => CLK25,
	MAC_TX_CONFIG => X"0003",	-- MAC must must provide pad + crc32
	MAC_RX_CONFIG => x"000F",	-- promiscuous mode, strip crc32, accept broadcast/multicast
	MAC_ADDR => LAN2_MAC_ADDR,
	PHY_CONFIG_CHANGE => LAN_ADDR_CHANGE_PULSE,		-- *080416
	PHY_RESET => '0',
	SPEED => "11",	-- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
	DUPLEX => '1',	-- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
	TEST_MODE => "00",	-- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
	POWER_DOWN => '0', -- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
	CLK_SKEW1 => CLK_SKEW21, -- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
	CLK_SKEW2 => CLK_SKEW22, -- supersedes defaults within if PHY_CONFIG_CHANGE = '1'
	MAC_TX_DATA => LAN2_MAC_TX_DATA,
	MAC_TX_DATA_VALID => LAN2_MAC_TX_DATA_VALID,
	MAC_TX_EOF => LAN2_MAC_TX_EOF,
	MAC_TX_CTS => LAN2_MAC_TX_CTS,
	MAC_RX_DATA => LAN2_MAC_RX_DATA,	
	MAC_RX_DATA_VALID => LAN2_MAC_RX_DATA_VALID,
	MAC_RX_SOF => LAN2_MAC_RX_SOF,
	MAC_RX_EOF => LAN2_MAC_RX_EOF,
	MAC_RX_CTS => '1',  -- follow-on processing is expected to always accept data even at max speed.
	-- RGMII interface ----------------
	TXC => LAN_TXC,	
	TXD => LAN_TXD,
	TX_CTL => LAN_TX_CTL,
	RXC => LAN_RXC,
	RXD => LAN_RXD,
	RX_CTL => LAN_RX_CTL,
	RESET_N => LAN_RESET_N,
	MCLK => LAN_MCLK,
	MDIO => LAN_MDIO,	
	-- end of RGMII interface --------
	MII_TX_CLK => '0',	-- MII interface is unused -----
	GMII_TX_CLK => open,
	GMII_MII_TXD => open,
	GMII_MII_TX_EN => open,
	GMII_MII_TX_ER => open,
	GMII_MII_CRS => '0',
	GMII_MII_COL => '0',
	GMII_MII_RX_CLK => '0',
	GMII_MII_RXD => x"00",
	GMII_MII_RX_DV => '0',
	GMII_MII_RX_ER => '0',  -- end of MII interface ------
	LINK_STATUS => LAN2_LINK_STATUS,
	SPEED_STATUS => LAN2_SPEED_STATUS,
	DUPLEX_STATUS => LAN2_DUPLEX_STATUS,
	PHY_ID => LAN2_PHY_ID,
	N_RX_FRAMES => LAN2_N_RX_FRAMES,
	N_RX_BAD_CRCS => LAN2_N_RX_BAD_CRCS,
	N_RX_FRAMES_TOO_SHORT => LAN2_N_RX_FRAMES_TOO_SHORT,
	N_RX_FRAMES_TOO_LONG => LAN2_N_RX_FRAMES_TOO_LONG,
	N_RX_WRONG_ADDR => LAN2_N_RX_WRONG_ADDR,
	N_RX_LENGTH_ERRORS => LAN2_N_RX_LENGTH_ERRORS,
	CS_CLKG => open,
	CS1 => open,
	CS1_CLK => open,
	CS2 => open,
	CS2_CLK => open,
	CT1 => open,
	CT1_CLK => open,
	TP => LAN2_TP
);

SREG8 <= LAN2_PHY_ID(7 downto 0);
-- fake input (to prevent optimization out). We need the pu/pd in .xdc
SREG36(6) <= LAN_CLK125;

--//-- IP STACK #1  -----------------------------------
-- Connected to GbE (LAN2), always
-- 5 TCP connections: 
-- 0 = TCP Port 1028 for monitoring & control 
-- 1 = TCP Port 1024 for Doppler table input (rx only) 
-- 2 = TCP1 Port 1280 for modulator channel 1 input data (rx only) 
-- 3 = TCP2 Port 1281 for modulator channel 2 input data (rx only)
-- 4 = TCP Port 1026 for alternative SDDS-formatted input (with flow-control)
-- UDP rx at Port 29495 for SDDS-formatted input (no flow control, MUST use external 10 MHz frequency reference)
-- reclock with CLK_P for easier P&R

RECLOCK_IP1: process(CLK_P)
begin
    if rising_edge(CLK_P) then
        if(CONFIG_CHANGE_PULSE = '1') then
            IP1_ADDRv4(31 downto 0) <= REG37 & REG38 & REG39 & REG40;	-- local IP address
            MULTICAST_IP1_ADDR <= REG33 & REG34 & REG35 & REG36;   -- multicast IP address
        end if;
    end if;
end process;

IPSTACK_001: COM5402 
GENERIC MAP(
        NUDPTX => 1,	-- required because IGMP_EN = '1'
        NUDPRX => 1,
        IGMP_EN => '1',
        NTCPSTREAMS => NTCPSTREAMS1,  
        CLK_FREQUENCY => CLK_FREQUENCY,	-- CLK_P 125 MHz, as time reference
        TX_IDLE_TIMEOUT => 50,	-- 50*4us = 200us 
        TCP_KEEPALIVE_PERIOD => 60,
        SIMULATION => SIMULATION
)
PORT MAP(
    CLK => CLK_P,
    SYNC_RESET => RECEIVER_RESET,  -- reset after a configuration change 1/7/15
    MAC_ADDR => LAN2_MAC_ADDR,
    IPv4_ADDR => IP1_ADDRv4,
    IPv6_ADDR => x"00000000000000000000000000000000",
    MULTICAST_IP_ADDR => MULTICAST_IP1_ADDR,
    SUBNET_MASK => SUBNET_MASK,
    GATEWAY_IP_ADDR => GATEWAY_IP_ADDR,
    CONNECTION_RESET => (others => '0'),
    TCP_KEEPALIVE_EN => '0',
    -- MAC interface
    MAC_TX_DATA => LAN2_MAC_TX_DATA,
    MAC_TX_DATA_VALID => LAN2_MAC_TX_DATA_VALID,
    MAC_TX_SOF => open,
    MAC_TX_EOF => LAN2_MAC_TX_EOF,
    MAC_TX_CTS => LAN2_MAC_TX_CTS,
    MAC_TX_RTS => open,
    MAC_RX_DATA => LAN2_MAC_RX_DATA,
    MAC_RX_DATA_VALID => LAN2_MAC_RX_DATA_VALID,
    MAC_RX_SOF => LAN2_MAC_RX_SOF,
    MAC_RX_EOF => LAN2_MAC_RX_EOF,
    -- UDP rx
    UDP_RX_DATA => IP1_UDP_RX_DATA,
    UDP_RX_DATA_VALID => IP1_UDP_RX_DATA_VALID,
    UDP_RX_SOF => IP1_UDP_RX_SOF,
    UDP_RX_EOF => IP1_UDP_RX_EOF,
--	UDP_RX_DEST_PORT_NO => x"0500",
    UDP_RX_DEST_PORT_NO_IN => x"0000",    -- port filtering done below
    CHECK_UDP_RX_DEST_PORT_NO => '0',
    UDP_RX_DEST_PORT_NO_OUT => IP1_UDP_RX_DEST_PORT_NO,
    -- UDP tx
    UDP_TX_DATA => IP1_UDP_TX_DATA,
    UDP_TX_DATA_VALID => IP1_UDP_TX_DATA_VALID,
    UDP_TX_SOF => IP1_UDP_TX_SOF,
    UDP_TX_EOF => IP1_UDP_TX_EOF,
    UDP_TX_CTS => IP1_UDP_TX_CTS,
    UDP_TX_ACK => IP1_UDP_TX_ACK,
    UDP_TX_NAK => IP1_UDP_TX_NAK,
    UDP_TX_DEST_IP_ADDR => IP1_UDP_TX_DEST_IP_ADDR,
    UDP_TX_DEST_PORT_NO => IP1_UDP_TX_DEST_PORT_NO,
    UDP_TX_SOURCE_PORT_NO => x"0402",	-- 1026
    -- TCP rx streams
    TCP_RX_DATA => IP1_TCP_RX_DATA,	
    TCP_RX_DATA_VALID => IP1_TCP_RX_DATA_VALID,
    TCP_RX_RTS => open,
    TCP_RX_CTS => IP1_TCP_RX_CTS,	
    -- TCP tx streams
    TCP_TX_DATA => IP1_TCP_TX_DATA,
    TCP_TX_DATA_VALID => IP1_TCP_TX_DATA_VALID,
    TCP_TX_CTS => IP1_TCP_TX_CTS,	
    -- Monitoring
    TCP_CONNECTED_FLAG => IP1_TCP_CONNECTED_FLAG,
--	CS1 => S1_1,
--	CS1_CLK => S1_1_CLK,
--	CS2 => S2_1,
--	CS2_CLK => S2_1_CLK,
    TP => IP1_TP	
);

-- main taks is to reject bad UDP frames
-- filter UDP destination port number 29495
IP1_UDP_RX_DATA_VALID_29495 <= IP1_UDP_RX_DATA_VALID when (unsigned(IP1_UDP_RX_DEST_PORT_NO) = 29495) else '0';
PACKETS_2_STREAM_001: PACKETS_2_STREAM 
GENERIC MAP(
        NBUFS => 1    -- large enough to store one complete 1080 byte SDDS frame
)
PORT MAP(
    CLK => CLK_P,
    SYNC_RESET => SYNC_RESET_CLK_P,
    PACKET_DATA_IN => IP1_UDP_RX_DATA,
    PACKET_DATA_VALID_IN => IP1_UDP_RX_DATA_VALID_29495,
    PACKET_EOF_IN => IP1_UDP_RX_EOF,
    PACKET_CTS_OUT => open, -- no flow control here
    STREAM_DATA_OUT => IP1_UDP_RX_DATA2,
    STREAM_DATA_VALID_OUT => IP1_UDP_RX_DATA_VALID2,
    STREAM_SOF_OUT => IP1_UDP_RX_SOF2, -- reconstructed data frame (needed here)
    STREAM_EOF_OUT => IP1_UDP_RX_EOF2,
    STREAM_CTS_IN => '1',   -- no flow control here. Demod is expected to process in real time
    BAD_PACKET => open,
    TP => open
);

-- whenever the right connector is used for RF receiver, several IP signals are moved from IP Stack2/LAN1 to IP Stack1/LAN2
IP_STACK2_ALT: if ((OPTION /= x"41") and (OPTION /= x"42")) and (ADCs_EN = '1') generate

    -- Filter destination port 1029  = backdoor for reset command over UDP
    IP1_UDP_RX_DATA_VALID_1029 <= IP1_UDP_RX_DATA_VALID when (unsigned(IP1_UDP_RX_DEST_PORT_NO) = 1029) else '0';
    PACKETS_2_STREAM_002: PACKETS_2_STREAM 
    GENERIC MAP(
            NBUFS => 1    
    )
    PORT MAP(
        CLK => CLK_P,
        SYNC_RESET => READY_FLAG_CLK_Pn,
        PACKET_DATA_IN => IP1_UDP_RX_DATA,
        PACKET_DATA_VALID_IN => IP1_UDP_RX_DATA_VALID_1029,
        PACKET_EOF_IN => IP1_UDP_RX_EOF,
        PACKET_CTS_OUT => open, -- no flow control here
        STREAM_DATA_OUT => IP1_UDP_RX_DATA3,
        STREAM_DATA_VALID_OUT => IP1_UDP_RX_DATA_VALID3,
        STREAM_SOF_OUT => open, 
        STREAM_EOF_OUT => open,
        STREAM_CTS_IN => IP1_TCP_RX_CTS(0),
        BAD_PACKET => open,
        TP => open
    );

    -- one elastic buffer for each tcp rx stream
    -- M&C, TCP port 1028 (port is defined within COM5402 component) OR UDP port 1029 
    LAN2_RX_DATA0 <= IP1_UDP_RX_DATA3 when (IP1_UDP_RX_DATA_VALID3 = '1') else IP1_TCP_RX_DATA(0);
    LAN2_RX_SAMPLE0_CLK <= IP1_UDP_RX_DATA_VALID3 or IP1_TCP_RX_DATA_VALID(0);

    ELASTIC_BUFFER_NRAMB2_001: ELASTIC_BUFFER_NRAMB2 
    generic map(
        DATA_WIDTH => 8,
        ADDR_WIDTH => 11,	-- 16Kb buffer 
        READ_AHEAD_1ADDRESS => '1'	-- no read latency, tricky timing ok because ARM is slower.
    )
    PORT MAP(
        CLK => CLK_P,
        SYNC_RESET => READY_FLAG_CLK_Pn,
        DATA_IN => LAN2_RX_DATA0,
        SAMPLE_CLK_IN => LAN2_RX_SAMPLE0_CLK,
        SAMPLE_CLK_IN_REQ => IP1_TCP_RX_CTS(0),
        DATA_OUT => RX_LAN,	
        SAMPLE_CLK_OUT => open,
        SAMPLE_CLK_OUT_E => EB1_SAMPLE_CLK_OUT_E,
        SAMPLE_CLK_OUT_REQ => RX_LAN_SAMPLE_CLK_REQ,
        BUFFER_EMPTY => RX_LAN_BUFFER_EMPTY,
        USED => open
    );
    IP1_TCP_TX_DATA(0) <= IP2_TCP_TX_DATA(0);
    IP1_TCP_TX_DATA_VALID(0) <= IP2_TCP_TX_DATA_VALID(0);
    IP2_TCP_TX_CTS(0) <= IP1_TCP_TX_CTS(0);
    
    -- Doppler tables. TCP port 1024
    IP1_TCP_RX_CTS(1) <= '1';
    IP2_TCP_RX_DATA(1) <= IP1_TCP_RX_DATA(1);
    IP2_TCP_RX_DATA_VALID(1) <= IP1_TCP_RX_DATA_VALID(1);
    IP1_TCP_TX_DATA_VALID(1) <= '0';    -- TCP stream 1 is receive-only
    
    -- TCP Port 1280 for modulator channel 1 input data (rx only) 
    IP1_TCP_RX_CTS(2) <= IP2_TCP_RX_CTS(2);
    IP2_TCP_RX_DATA(2) <= IP1_TCP_RX_DATA(2);
    IP2_TCP_RX_DATA_VALID(2) <= IP1_TCP_RX_DATA_VALID(2);
    IP1_TCP_TX_DATA_VALID(2) <= '0';    -- TCP stream 2 is receive-only

    -- TCP Port 1281 for modulator channel 2 input data (rx only)
    IP1_TCP_RX_CTS(3) <= IP2_TCP_RX_CTS(3);
    IP2_TCP_RX_DATA(3) <= IP1_TCP_RX_DATA(3);
    IP2_TCP_RX_DATA_VALID(3) <= IP1_TCP_RX_DATA_VALID(3);
    IP1_TCP_TX_DATA_VALID(3) <= '0';    -- TCP stream 3 is receive-only

    IP1_TCP_TX_DATA_VALID(4) <= '0';    -- TCP stream 4 is receive-only

    IP1_UDP_TX_DATA <= IP2_UDP_TX_DATA;
    IP1_UDP_TX_DATA_VALID <= IP2_UDP_TX_DATA_VALID;
    IP1_UDP_TX_SOF <= IP2_UDP_TX_SOF;
    IP1_UDP_TX_EOF <= IP2_UDP_TX_EOF;
    IP2_UDP_TX_CTS <= IP1_UDP_TX_CTS;
    IP2_UDP_TX_ACK <= IP1_UDP_TX_ACK;
    IP2_UDP_TX_NAK <= IP1_UDP_TX_NAK;
    IP1_UDP_TX_DEST_IP_ADDR <= IP2_UDP_TX_DEST_IP_ADDR;
    IP1_UDP_TX_DEST_PORT_NO <= IP2_UDP_TX_DEST_PORT_NO;
    
    
    
end generate;

--//-- IP STACK #2  -----------------------------------
-- LAN1/IP stack#2 are disabled if left connector is used for RF receiver
-- In that case, the network paths are routed through LAN2/IP stack#1
IP_STACK2_GEN_GEN: if ((OPTION = x"41") or (OPTION = x"42")) or (ADCs_EN = '0') generate

    -- 4 TCP connections
    -- TCP Port 1028 for monitoring & control
    -- TCP Port 1024 for Doppler table input
    -- TCP Port 1280 for modulator channel 1 input data (rx only) 
    -- TCP Port 1281 for modulator channel 2 input data (rx only)
    -- 1 tx UDP to send demodulated data
    -- reclock with CLK_P for easier P&R
    RECLOCK_IP2: process(CLK_P)
    begin
        if rising_edge(CLK_P) then
            if(CONFIG_CHANGE_PULSE = '1') then
                IP2_ADDRv4(31 downto 0) <= REG41 & REG42 & REG43 & REG44;	-- local IP address
                SUBNET_MASK <= REG51 & REG52 & REG53 & REG54;
                GATEWAY_IP_ADDR <= REG55 & REG56 & REG57 & REG58;
            end if;
        end if;
    end process;
    
    IPSTACK_002: COM5402 
    GENERIC MAP(
            NUDPTX => 1,
            NUDPRX => 1,
            IGMP_EN => '0',
            NTCPSTREAMS => NTCPSTREAMS2,  
            CLK_FREQUENCY => CLK_FREQUENCY,	-- CLK_P 125 MHz, as time reference
            TX_IDLE_TIMEOUT => 50,	-- 50*4us = 200us 
            TCP_KEEPALIVE_PERIOD => 60,
            SIMULATION => SIMULATION
    )
    PORT MAP(
        CLK => CLK_P,
        SYNC_RESET => SYNC_RESET_CLK_P,
        MAC_ADDR => LAN1_MAC_ADDR,
        IPv4_ADDR => IP2_ADDRv4,
        IPv6_ADDR => x"00000000000000000000000000000000",
        MULTICAST_IP_ADDR => x"00000000",  -- no multicast
        SUBNET_MASK => SUBNET_MASK,
       GATEWAY_IP_ADDR => GATEWAY_IP_ADDR,
        CONNECTION_RESET => (others => '0'),
        TCP_KEEPALIVE_EN => '0',
        -- MAC interface
        MAC_TX_DATA => LAN1_MAC_TX_DATA,
        MAC_TX_DATA_VALID => LAN1_MAC_TX_DATA_VALID,
        MAC_TX_SOF => open,
        MAC_TX_EOF => LAN1_MAC_TX_EOF,
        MAC_TX_CTS => LAN1_MAC_TX_CTS,
        MAC_TX_RTS => open,
        MAC_RX_DATA => LAN1_MAC_RX_DATA,
        MAC_RX_DATA_VALID => LAN1_MAC_RX_DATA_VALID,
        MAC_RX_SOF => LAN1_MAC_RX_SOF,
        MAC_RX_EOF => LAN1_MAC_RX_EOF,
        -- UDP rx
        UDP_RX_DATA => IP2_UDP_RX_DATA,
        UDP_RX_DATA_VALID => IP2_UDP_RX_DATA_VALID,
        UDP_RX_SOF => IP2_UDP_RX_SOF, -- unused
        UDP_RX_EOF => IP2_UDP_RX_EOF, 
        UDP_RX_DEST_PORT_NO_IN => x"0405",    -- 
        CHECK_UDP_RX_DEST_PORT_NO => '0',
        UDP_RX_DEST_PORT_NO_OUT => IP2_UDP_RX_DEST_PORT_NO,
    
        -- UDP tx
        UDP_TX_DATA => IP2_UDP_TX_DATA,
        UDP_TX_DATA_VALID => IP2_UDP_TX_DATA_VALID,
        UDP_TX_SOF => IP2_UDP_TX_SOF,
        UDP_TX_EOF => IP2_UDP_TX_EOF,
        UDP_TX_CTS => IP2_UDP_TX_CTS,
        UDP_TX_ACK => IP2_UDP_TX_ACK,
        UDP_TX_NAK => IP2_UDP_TX_NAK,
        UDP_TX_DEST_IP_ADDR => IP2_UDP_TX_DEST_IP_ADDR,
        UDP_TX_DEST_PORT_NO => IP2_UDP_TX_DEST_PORT_NO,
        UDP_TX_SOURCE_PORT_NO => x"0402",	-- 1026
        -- TCP rx streams
        TCP_RX_DATA => IP2_TCP_RX_DATA,
        TCP_RX_DATA_VALID => IP2_TCP_RX_DATA_VALID,
        TCP_RX_RTS => open,
        TCP_RX_CTS => IP2_TCP_RX_CTS,	
        -- TCP tx streams
        TCP_TX_DATA => IP2_TCP_TX_DATA,
        TCP_TX_DATA_VALID => IP2_TCP_TX_DATA_VALID,
        TCP_TX_CTS => IP2_TCP_TX_CTS,	
        -- Monitoring
        TCP_CONNECTED_FLAG => IP2_TCP_CONNECTED_FLAG,
    --	CS1 => S1_1,
    --	CS1_CLK => S1_1_CLK,
    --	CS2 => S2_1,
    --	CS2_CLK => S2_1_CLK,
        TP => IPSTACK2_TP	
    );
    
    -- main taks is to reject bad UDP frames
    -- Filter destination port 1029  = backdoor for reset command over UDP
    IP2_UDP_RX_DATA_VALID_1029 <= IP2_UDP_RX_DATA_VALID when (unsigned(IP2_UDP_RX_DEST_PORT_NO) = 1029) else '0';
    PACKETS_2_STREAM_002: PACKETS_2_STREAM 
    GENERIC MAP(
            NBUFS => 1    
    )
    PORT MAP(
        CLK => CLK_P,
        SYNC_RESET => READY_FLAG_CLK_Pn,
        PACKET_DATA_IN => IP2_UDP_RX_DATA,
        PACKET_DATA_VALID_IN => IP2_UDP_RX_DATA_VALID_1029,
        PACKET_EOF_IN => IP2_UDP_RX_EOF,
        PACKET_CTS_OUT => open, -- no flow control here
        STREAM_DATA_OUT => IP2_UDP_RX_DATA2,
        STREAM_DATA_VALID_OUT => IP2_UDP_RX_DATA_VALID2,
        STREAM_SOF_OUT => open, 
        STREAM_EOF_OUT => open,
        STREAM_CTS_IN => IP2_TCP_RX_CTS(0),
        BAD_PACKET => open,
        TP => open
    );
    
    -- one elastic buffer for each tcp rx stream
    -- M&C, TCP port 1028 (port is defined within COM5402 component) OR UDP port 1029 
    LAN2_RX_DATA0 <= IP2_UDP_RX_DATA2 when (IP2_UDP_RX_DATA_VALID2 = '1') else IP2_TCP_RX_DATA(0);
    LAN2_RX_SAMPLE0_CLK <= IP2_UDP_RX_DATA_VALID2 or IP2_TCP_RX_DATA_VALID(0);
    
    ELASTIC_BUFFER_NRAMB2_001: ELASTIC_BUFFER_NRAMB2 
    generic map(
        DATA_WIDTH => 8,
        ADDR_WIDTH => 11,	-- 16Kb buffer 
        READ_AHEAD_1ADDRESS => '1'	-- no read latency, tricky timing ok because ARM is slower.
    )
    PORT MAP(
        CLK => CLK_P,
        SYNC_RESET => READY_FLAG_CLK_Pn,
        DATA_IN => LAN2_RX_DATA0,
        SAMPLE_CLK_IN => LAN2_RX_SAMPLE0_CLK,
        SAMPLE_CLK_IN_REQ => IP2_TCP_RX_CTS(0),
        DATA_OUT => RX_LAN,	
        SAMPLE_CLK_OUT => open,
        SAMPLE_CLK_OUT_E => EB1_SAMPLE_CLK_OUT_E,
        SAMPLE_CLK_OUT_REQ => RX_LAN_SAMPLE_CLK_REQ,
        BUFFER_EMPTY => RX_LAN_BUFFER_EMPTY,
        USED => open
    );
    
    -- Doppler tables. TCP port 1024
    IP2_TCP_RX_CTS(1) <= '1';
    
    
end generate;

--//-- FREQUENCY TABLE ----------------------------------

-- Input on LAN2 from TCP port 1024
-- Store frequency table in 8 block rams. Up to 4096 frequency samples.
--FT_SIM: if(SIMULATION = '1') generate
--    SDDS_RX_TIMETAG <= x"0000000000000001";
--    process 
--    begin
--        IP2_TCP_CONNECTED_FLAG(1) <= '0';
--        wait for 100000 ns;
--        IP2_TCP_CONNECTED_FLAG(1) <= '1';
--        wait for 100000 ns;
--        IP2_TCP_CONNECTED_FLAG(1) <= '0';
--        wait;
--    end process;
--    process 
--    begin
--        IP2_TCP_RX_DATA_VALID(1) <= '0';
--       wait for 101000 ns;
--       for I in 0 to 100 loop
--        IP2_TCP_RX_DATA_VALID(1) <= '0';
--        wait for 92 ns;
--        IP2_TCP_RX_DATA_VALID(1) <= '1';
--        wait for 8 ns;
--       wait for 1000 ns;
--       end loop;
--       wait;
--    end process;
--    process 
--    begin
--        IP2_TCP_RX_DATA(1) <= x"00";
--       wait for 100100 ns;
--        IP2_TCP_RX_DATA(1) <= x"01";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"02";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"03";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"04";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"05";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"06";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"07";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"08";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"09";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"0a";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"0b";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"0c";
--       wait for 100 ns;
--        IP2_TCP_RX_DATA(1) <= x"0d";
--       wait for 100 ns;
--       wait;
--    end process;
--end generate;

-- for timing purposes, assess this complex statement -- *111516
FT_STATE_000: process(CLK_P) 
begin
	if rising_edge(CLK_P) then
		if (unsigned(SDDS_RX_TIMETAG) >= FT_START_TIME_final) and (unsigned(SDDS_RX_TIMETAG) /= 0) then
			FT_PLAYBACK <= '1';
		else
			FT_PLAYBACK <= '0';
		end if;
	end if;
end process;


FT_STATE_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(SYNC_RESET_CLK_P = '1') then
			FT_STATE <= 0;  -- idle. No upload, no playback
			FT_WPTR <= (others => '0');
			FT_WPTR_D <= (others => '1');
			FT_WRITE_FULL <= '0';
            FT_READ_SAMPLE_CLK <= '0';
		elsif(FT_STATE = 0) then
		  -- idle state 
		  if (IP2_TCP_CONNECTED_FLAG(1) = '1') then 
		    -- new TCP upload session
			FT_STATE <= 1;  -- upload started, collect start time
			FT_WPTR <= (others => '0');
			FT_WPTR_D <= (others => '1');
			FT_WRITE_FULL <= '0';
		    FT_READ_SAMPLE_CLK <= '0';
		  elsif (FT_PLAYBACK = '1') then -- *111516
              -- triggers playback
              FT_STATE <= 3;
              FT_RPTR <= (others => '1');
          end if;
		elsif(FT_STATE = 1) then
		    -- uploading the start time and first frequency sample
		    if (IP2_TCP_RX_DATA_VALID(1) = '1') then 
                -- one more upload byte
                if(FT_WPTR <= 7) then
                    -- collect start time
                    FT_START_TIME <= FT_START_TIME(55 downto 0) & IP2_TCP_RX_DATA(1);  -- MSB first
                else
                    FT_START_TIME_final <= unsigned(FT_START_TIME);
                    -- collect first frequency sample
                    FT_FREQ0 <= FT_FREQ0(23 downto 0) & IP2_TCP_RX_DATA(1);  -- MSB first
                end if;
                if(FT_WPTR = 11) then
                  -- finished collecting first 2 fields. continue with frequency table upload
                 FT_STATE <= 2;  -- upload frequency table
                 FT_WPTR <= (others => '0');
                 FT_WPTR_D <= (others => '1');
                else
                  -- continue collecting first 2 fields
                  FT_WPTR <= FT_WPTR + 1;
                end if;
		     elsif  (IP2_TCP_CONNECTED_FLAG(1) = '0') then
                  -- end of TCP upload session. Back to idle
                   FT_STATE <= 0;  
             end if;
 		elsif(FT_STATE = 2) then
		  -- uploading the frequency table 
		  if (IP2_TCP_RX_DATA_VALID(1) = '1') and (FT_WRITE_FULL = '0')  then 
		     -- do not write past the 
            FT_DIA <= FT_DIA(23 downto 0) & IP2_TCP_RX_DATA(1);  -- MSB first
   		    FT_WPTR <= FT_WPTR + 1;
            -- every 4 bytes, write to block RAM
            if(FT_WPTR(1 downto 0) = 3) then
                FT_WRITE_SAMPLE_CLK <= '1';
                 -- remember the last full-word wptr
                 FT_WPTR_D <= FT_WPTR;
            else
                FT_WRITE_SAMPLE_CLK <= '0';
            end if;
            if((not FT_WPTR) = 0) then
                -- reached the ceiling of the 8 block rams
                FT_WRITE_FULL <= '1';
            end if;
		 elsif  (IP2_TCP_CONNECTED_FLAG(1) = '0') then
		    -- end of TCP upload session. Back to idle
			 FT_STATE <= 0;  
		  end if;
		elsif(FT_STATE = 3) then
		  -- playback
		  if (IP2_TCP_CONNECTED_FLAG(1) = '1') then 
              -- new TCP upload session. back to idle
		      FT_STATE <= 0; 
		  elsif(FT_1s_TICK = '1') then
		      if(FT_RPTR = FT_WPTR_D(13 downto 2)) then
		          -- end of playback 
		          FT_STATE <= 4;  -- playback is complete
		      else
		          FT_RPTR <= FT_RPTR + 1;
		          FT_READ_SAMPLE_CLK <= '1';
		      end if;
		   else
              FT_READ_SAMPLE_CLK <= '0';
		   end if;
		elsif(FT_STATE = 4) then
		  -- re-arm playback if new FT_START_TIME is in the future
		  if (IP2_TCP_CONNECTED_FLAG(1) = '1') then 
              -- new TCP upload session. back to idle
              FT_STATE <= 0; 
          end if;
 	    end if;
	end if;
end process;

-- (1/64)s timer. Only during playback
FT_TIME_GEN: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(SYNC_RESET_CLK_P = '1') then
		  FT_1_64s_CNTR <= (others => '0');
		  FT_1s_CNTR <= (others => '0');
	      FT_1_64s_TICK <= '0';
	      FT_1s_TICK <= '0';
		elsif  (FT_STATE = 0) and  (FT_PLAYBACK = '1') then	-- *111516
		  -- reset (1/64)s timer when starting playback
	      FT_1_64s_TICK <= '1';
	      FT_1s_TICK <= '1';
	      FT_1_64s_CNTR <=  (others => '0');
		  FT_1s_CNTR <= (others => '0');
		elsif(FT_STATE = 3) then
		  if(FT_1_64s_CNTR = x"1DCD64") or ((SIMULATION = '1') and (FT_1_64s_CNTR = x"000100")) then
		      FT_1_64s_CNTR <=  (others => '0');
		      FT_1s_CNTR <= FT_1s_CNTR + 1;
		      FT_1_64s_TICK <= '1';
		      if(FT_1s_CNTR = 63) then
    		      FT_1s_TICK <= '1';
		      else
		          FT_1s_TICK <= '0';
		      end if;
		  else
		      FT_1_64s_CNTR <= FT_1_64s_CNTR + 1;
		      FT_1_64s_TICK <= '0';
		      FT_1s_TICK <= '0';
		  end if;
        end if;
    end if;
end process;

FT_WRITE_001: process(FT_WPTR_D, FT_WRITE_SAMPLE_CLK)
begin
    for I in 0 to 7 loop
        if(FT_WPTR_D(13 downto 11) = I) then
            FT_WEA(I) <= FT_WRITE_SAMPLE_CLK;
        else
            FT_WEA(I) <= '0';
        end if; 
    end loop;
end process;

-- table
RAMB16_X: for I in 0 to 7 generate
	RAMB16_S32_S32_001: BRAM_DP2 
	GENERIC MAP(
		DATA_WIDTHA => 32,		
		ADDR_WIDTHA => 9,
		DATA_WIDTHB => 32,		 
		ADDR_WIDTHB => 9
	)
	PORT MAP(
		CSA => '1',
		CLKA => CLK_P,
		WEA => FT_WEA(I),      -- Port A Write Enable Input
		ADDRA => std_logic_vector(FT_WPTR_D(10 downto 2)),  -- Port A 9-bit Address Input
		DIA => FT_DIA,      -- Port A 32-bit Data Input
		OEA => '0',
		DOA => open,
		CSB => '1',
		CLKB => CLK_P,
		WEB => '0',
		ADDRB => std_logic_vector(FT_RPTR(8 downto 0)),  -- Port B 9-bit Address Input
		DIB => x"00000000",      -- Port B 32-bit Data Input
		OEB => '1',
		DOB => FT_DOB(I)      -- Port B 32-bit Data Output
	);
end generate;

-- read frequency table
RPTR_MEMINDEX <= to_integer(unsigned(FT_RPTR(11 downto 9)));
READ_FT_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
	   FT_1_64s_TICK_D <= FT_1_64s_TICK;
	   FT_1_64s_TICK_D2 <= FT_1_64s_TICK_D;
	   
	    FT_READ_SAMPLE_CLK_D <= FT_READ_SAMPLE_CLK;    -- one CLK delay to read frequency from the table

        if(SYNC_RESET_CLK_P = '1') then
           FT_FREQ <= (others => '0');
	    elsif(FT_STATE = 2) then
	       FT_FREQ_END <= signed(FT_FREQ0);  -- first sample in 
	    elsif(FT_READ_SAMPLE_CLK_D = '1') then
	       -- two points at the 1s interpolation boundaries
	       FT_FREQ_START <= FT_FREQ_END;
 	       FT_FREQ <= FT_FREQ_END;  
	       FT_FREQ_END <= signed(FT_DOB(RPTR_MEMINDEX));
 	    elsif(FT_1_64s_TICK_D2 = '1') then
	       -- 1/64 increment
	       FT_FREQ <= FT_FREQ + resize(FT_FREQ_DIFF(23 downto 6),FT_FREQ'length);
	    end if;
        FT_FREQ_DIFF <= FT_FREQ_END - FT_FREQ_START;    -- difference between 2 frequency samples, 1s apart
	    
    end if;
end process;

-- chip rate is also affected by Doppler. Scale FT_FREQ by the fixed ratio 2.2875 GHz / 3.0777995 MChips/s = 743.22580142078
READ_CFT_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		-- reclock before and after multiplication for easier P&R timing
		-- resize multiplier operands to 18-bits to match 18x18 hardware multiplier
		CFT_A <= FT_FREQ(23 downto 6);	-- KEY ASSUMPTION: MAX FREQ OFFSET IS +/- 244 KHz = +/- 106ppm
		CFT_B <= to_signed(11287,CFT_B'length);
		CFT_AB <= CFT_A * CFT_B;	-- signed multiplication
   end if;
end process;
CFT_FREQ <= resize(CFT_AB(34 downto 17),CFT_FREQ'length);



-- monitoring
MONITORING_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
 		if(LATCH_MONITORING_PULSE = '1') then
			SREG41 <= std_logic_vector(RECEIVER_CENTER_FREQ_DYNAMIC(7 downto 0));
			SREG42 <= std_logic_vector(RECEIVER_CENTER_FREQ_DYNAMIC(15 downto 8));
			SREG43 <= std_logic_vector(RECEIVER_CENTER_FREQ_DYNAMIC(23 downto 16));
			SREG44 <= std_logic_vector(RECEIVER_CENTER_FREQ_DYNAMIC(31 downto 24));
 		end if;
	end if;
end process;


--//-- SDDS input (SIMULATION) ----------------------------------
READFILE_SIM: if(SIMULATION = '1') generate
	READFILE_001: process(CLK_P)
		variable c : character;
		variable FDATA_VALID: std_logic := '0';
	begin
		if rising_edge(CLK_P) then
			if(unsigned(REG28(7 downto 5)) = 0) then
				-- only if simulation and input selection = SDDS/LAN
				if(SYNC_RESET_CLK_P = '1') then
					file_open(SDDS_RX_FILE, SDDS_FILENAME, read_mode);
					FDATA_VALID := '0';
				elsif(READY_FLAG_CLK_P = '1') and (SDDS_RX_CTS = '1') then
					if(not endfile(SDDS_RX_FILE)) then
						read(SDDS_RX_FILE, c);
						FDATA_VALID := '1';
					else
						c := 'z';	-- continue simulation past the end of the stimulus file.
						FDATA_VALID := '0';
					end if;
				else
					FDATA_VALID := '0';
				end if;
			else
				FDATA_VALID := '0';
		  end if;
		end if;

		SDDS_FILE_RX_DATA <= std_logic_vector(to_unsigned(character'pos(c),8));
		SDDS_FILE_RX_DATA_VALID <= FDATA_VALID;
	end process;
end generate;

--//-- SDDS deframing ----------------------------------
SDDS_IN_001: if ((OPTION = x"41") or (OPTION = x"42")) and (ADCs_EN = '0') generate
    -- Input on IP stack #1/LAN2 (GbE) from one of two ports:
    -- UDP port 1280, or
    -- TCP port 1028 
    
    -- Input mux and frame sync regeneration
    -- Select UDP or TCP as input protocol
    -- TCP has built-in flow control, UDP has not.
    -- 10 MHz frequency reference MUST be used when selecting UDP to prevent underflow/overflow at SDDS input elastic buffer.
    -- With TCP, one must reconstruct the 1080-byte SOF/EOF frame boundaries.
    INPUT_UDP_TCPN <= REG0(0);	
    INPUT_MUX_001: process(CLK_P)
    begin
        if rising_edge(CLK_P) then	
            if(SYNC_RESET_CLK_P = '1') or (CONFIG_CHANGE_PULSE = '1') then	-- *051716
                SDDS_RX_BYTE_CNTR <= (others => '0');
                SDDS_RX_DATA_VALID_IN <= '0';
                SDDS_RX_SOF_IN <= '0';
                SDDS_RX_EOF_IN <= '0';
            elsif(SIMULATION = '1') then	-- *051716
                -- read from SDDS-formatted file
                SDDS_RX_DATA_IN <= SDDS_FILE_RX_DATA;
                SDDS_RX_DATA_VALID_IN <= SDDS_FILE_RX_DATA_VALID;
                if(SDDS_FILE_RX_DATA_VALID = '1') then
                    if(SDDS_RX_BYTE_CNTR = 1079) then
                        SDDS_RX_BYTE_CNTR <= (others => '0');
                        SDDS_RX_EOF_IN <= '1';
                    else
                        SDDS_RX_BYTE_CNTR <= SDDS_RX_BYTE_CNTR + 1;
                        SDDS_RX_EOF_IN <= '0';
                    end if;
                    if(SDDS_RX_BYTE_CNTR = 0) then
                        SDDS_RX_SOF_IN <= '1';
                    else
                        SDDS_RX_SOF_IN <= '0';
                    end if;
                else
                    SDDS_RX_EOF_IN <= '0';
                    SDDS_RX_EOF_IN <= '0';
                end if;
                
            elsif(INPUT_UDP_TCPN = '1') then
                -- SDDS UDP input via IP Stack #1 / LAN2
                SDDS_RX_DATA_IN <= IP1_UDP_RX_DATA2;
                SDDS_RX_DATA_VALID_IN <= IP1_UDP_RX_DATA_VALID2;
                SDDS_RX_SOF_IN <= IP1_UDP_RX_SOF2;
                SDDS_RX_EOF_IN <= IP1_UDP_RX_EOF2;
            else
                -- SDDS TCP input via IP Stack #1 / LAN2 (port 1028)
                -- TCP port 1028 (options A/B only)
                SDDS_RX_DATA_IN <= IP1_TCP_RX_DATA(0);
                SDDS_RX_DATA_VALID_IN <= IP1_TCP_RX_DATA_VALID(0);
                if(IP1_TCP_RX_DATA_VALID(0) = '1') then
                    if(SDDS_RX_BYTE_CNTR = 1079) then
                        SDDS_RX_BYTE_CNTR <= (others => '0');
                        SDDS_RX_EOF_IN <= '1';
                    else
                        SDDS_RX_BYTE_CNTR <= SDDS_RX_BYTE_CNTR + 1;
                        SDDS_RX_EOF_IN <= '0';
                    end if;
                    if(SDDS_RX_BYTE_CNTR = 0) then
                        SDDS_RX_SOF_IN <= '1';
                    else
                        SDDS_RX_SOF_IN <= '0';
                    end if;
                else
                    SDDS_RX_EOF_IN <= '0';
                    SDDS_RX_EOF_IN <= '0';
                end if;
            end if;
        end if;
    end process;
    
    -- input frame counter
    SDDS_RX_FRAME_CNTR_001: process(CLK_P)
    begin
        if rising_edge(CLK_P) then	
            if(SYNC_RESET_CLK_P = '1') then
                SDDS_RX_FRAME_CNTR <= (others => '0');
            elsif(SDDS_RX_EOF_IN = '1') then
                SDDS_RX_FRAME_CNTR <= SDDS_RX_FRAME_CNTR + 1;
            end if;
        end if;
    end process;
            
    
    -- TCP flow control
    IP1_TCP_RX_CTS(0) <= SDDS_RX_CTS when (INPUT_UDP_TCPN = '0') else '0';
    
    
    SDDS_rx_001: SDDS_rx 
    generic map(
        NBUFS_LOG2 => 5,	-- tested. sufficient margins for TCP to respond in a timely manner. No need to go to 64 or 128 buffers.
        SIMULATION => SIMULATION
        ) 
    PORT MAP(
        CLK => CLK_P,
        SYNC_RESET => SYNC_RESET_CLK_P,
        DATA_IN => SDDS_RX_DATA_IN,
        DATA_VALID_IN => SDDS_RX_DATA_VALID_IN,
        SOF_IN => SDDS_RX_SOF_IN,
        EOF_IN => SDDS_RX_EOF_IN,
        CTS => SDDS_RX_CTS,
        DATA_I_OUT => RX_DATA1_I,
        DATA_Q_OUT => RX_DATA1_Q,
        DATA_VALID_OUT => RX_SAMPLE1_CLK,
        SAMPLING_RATE_OUT => SDDS_RX_SAMPLING_RATE,
        TIMETAG_OUT => SDDS_RX_TIMETAG,
        N_MISSING_FRAMES => SDDS_N_MISSING_FRAMES,
        TP => SDDS_TP
    );
end generate;

--//-- DSSS MODULATOR -------------------------------------
MODULATOR_GEN: if(MODULATOR_EN = '1') generate
	--//-- INPUTS SELECTION -------------------------------------
	CONTROLS_001: process(CLK_P)
	begin
	  if rising_edge(CLK_P) then
			INPUTS_SEL <= "00" & REG65(5 downto 4) & "00" & REG63(5 downto 4);
				-- bits 1:0 = input selection for channel 1
				-- bits 5:4 = input selection for channel 2
	  end if;
	end process;

	-- Generate a pseudo-random binary sequence PRBS11 (to compute BER at the receiving end)
	-- two PRBS11 sequence generators
	PRBS11_SYNC_RESET1 <= '1' when (unsigned(INPUTS_SEL(1 downto 0)) /= 2) else (not READY_FLAG_CLK_P);
	LFSR11P_001: LFSR11P PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => PRBS11_SYNC_RESET1,
		DATA_OUT => PRBS11_DATA1,
		SAMPLE_CLK_OUT => PRBS11_DATA1_VALID,
		SOF_OUT => open,
		SAMPLE_CLK_OUT_REQ => PRBS11_CTS1
	);

	PRBS11_SYNC_RESET2 <= '1' when (unsigned(INPUTS_SEL(5 downto 4)) /= 2) else (not READY_FLAG_CLK_P);
	LFSR11P_002: LFSR11P PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => PRBS11_SYNC_RESET2,
		DATA_OUT => PRBS11_DATA2,
		SAMPLE_CLK_OUT => PRBS11_DATA2_VALID,
		SOF_OUT => open,
		SAMPLE_CLK_OUT_REQ => PRBS11_CTS2
	);

	INPUT_SEL_001: process(CLK_P)
	begin
	  if rising_edge(CLK_P) then
		if(READY_FLAG_CLK_P = '0') then
			CENC1_DATA8b_IN_VALID <= '0';
		elsif(INPUTS_SEL(1 downto 0) = "01") then
			-- LAN TCP input, port 1280 (0x500)
			CENC1_DATA8b_IN <= IP2_TCP_RX_DATA(2);
			CENC1_DATA8b_IN_VALID <= IP2_TCP_RX_DATA_VALID(2);
		elsif(INPUTS_SEL(1 downto 0) = "10") then
			-- PRBS11 test sequence
			CENC1_DATA8b_IN <= PRBS11_DATA1;
			CENC1_DATA8b_IN_VALID <= PRBS11_DATA1_VALID;
		elsif(INPUTS_SEL(1 downto 0) = "11") then
			-- zeros
			CENC1_DATA8b_IN <= (others => '0');
			CENC1_DATA8b_IN_VALID <= CENC1_DATA8b_IN_CTS;
		else
			-- disabled
			--CENC1_DATA8b_IN <= (others => '0');
			CENC1_DATA8b_IN_VALID <= '0';
		end if;
	  end if;
	end process;
	PRBS11_CTS1 <= CENC1_DATA8b_IN_CTS when (INPUTS_SEL(1 downto 0) = "10") else '0';
	-- convolutional encoder 1. TCP port 1280
	IP2_TCP_RX_CTS(2) <= CENC1_DATA8b_IN_CTS when (INPUTS_SEL(1 downto 0) = "01") else '0';


	INPUT_SEL_002: process(CLK_P)
	begin
	  if rising_edge(CLK_P) then
		if(READY_FLAG_CLK_P = '0') then
			CENC2_DATA8b_IN_VALID <= '0';
		elsif(INPUTS_SEL(5 downto 4) = "01") then
			-- LAN TCP input, port 1281 (0x501)
			CENC2_DATA8b_IN <= IP2_TCP_RX_DATA(3);
			CENC2_DATA8b_IN_VALID <= IP2_TCP_RX_DATA_VALID(3);
		elsif(INPUTS_SEL(5 downto 4) = "10") then
			-- PRBS11 test sequence
			CENC2_DATA8b_IN <= PRBS11_DATA2;
			CENC2_DATA8b_IN_VALID <= PRBS11_DATA2_VALID;
		elsif(INPUTS_SEL(5 downto 4) = "11") then
			-- zeros
			CENC2_DATA8b_IN <= (others => '0');
			CENC2_DATA8b_IN_VALID <= CENC2_DATA8b_IN_CTS;
		else
			-- disabled
			--CENC2_DATA8b_IN <= (others => '0');
			CENC2_DATA8b_IN_VALID <= '0';
		end if;
	  end if;
	end process;
	PRBS11_CTS2 <= CENC2_DATA8b_IN_CTS when (INPUTS_SEL(5 downto 4) = "10") else '0';
	-- convolutional encoder 2. TCP port 1281
	IP2_TCP_RX_CTS(3) <= CENC1_DATA8b_IN_CTS when (INPUTS_SEL(5 downto 4) = "01") else '0';

--//-- PARALLEL TO SERIAL CONVERSION ----------------------------
	P8_TO_S1_CONVERSION_001: P8_TO_S1_CONVERSION PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => SYNC_RESET_CLK_P,
		DATA8_IN => CENC1_DATA8b_IN,
		SAMPLE8_CLK_IN => CENC1_DATA8b_IN_VALID,
		SAMPLE8_CLK_IN_REQ => CENC1_DATA8b_IN_CTS,
		DATA1_OUT => TX_DATA1b11,
		SAMPLE1_CLK_OUT => TX_DATA1b11_VALID,
		SAMPLE1_CLK_OUT_REQ => TX_DATA1b11_CTS,
		BUF_EMPTY => P2S_BUF_EMPTY1
	);

	P8_TO_S1_CONVERSION_002: P8_TO_S1_CONVERSION PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => SYNC_RESET_CLK_P,
		DATA8_IN => CENC2_DATA8b_IN,
		SAMPLE8_CLK_IN => CENC2_DATA8b_IN_VALID,
		SAMPLE8_CLK_IN_REQ => CENC2_DATA8b_IN_CTS,
		DATA1_OUT => TX_DATA1b12,
		SAMPLE1_CLK_OUT => TX_DATA1b12_VALID,
		SAMPLE1_CLK_OUT_REQ => TX_DATA1b12_CTS,
		BUF_EMPTY => P2S_BUF_EMPTY2
	);


--//-- I/Q DEMUX --------------------------------------------------
	-- special case: alternating I/Q bits
	TOGGLE_IQ_001: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			if(SYNC_RESET_CLK_P = '1') or (CONFIG_CHANGE_PULSE = '1') or (REG60(7) = '0') then
				TOGGLE_QIn <= '0';
			elsif(TX_DATA1b11_VALID = '1') then
				TOGGLE_QIn <= not TOGGLE_QIn;
			end if;
		end if;
	end process;
	NRZ1_TX_DATA1_VALID_IN <= TX_DATA1b11_VALID and (not TOGGLE_QIn);
	NRZ1_TX_DATA1_IN <= TX_DATA1b11;

	NRZ1_TX_DATA2_VALID_IN <= TX_DATA1b11_VALID and TOGGLE_QIn when (REG60(7) = '1') else TX_DATA1b12_VALID;
	NRZ1_TX_DATA2_IN <= TX_DATA1b11 when (REG60(7) = '1') else TX_DATA1b12;


--//-- DATA FORMAT CONVERTER --------------------------------------
-- converts NRZ-L to NRZ-L/M/S
-- Two converters, for I and Q channels respectively

	NRZ_TX_CONTROL_001: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			case REG61(5 downto 3) is
				when "000" => NRZ1_TX_CONTROL <= "000";	-- NRZ-L unchanged
				when "001" => NRZ1_TX_CONTROL <= "001";	-- NRZ-L to NRZ_M
				when others => NRZ1_TX_CONTROL <= "010";	-- NRZ-L to NRZ_S
			end case;
		end if;
	end process;

	NRZ1_TX_001: NRZ1 PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => SYNC_RESET_CLK_P,
		DATA_IN => NRZ1_TX_DATA1_IN,
		DATA_VALID_IN => NRZ1_TX_DATA1_VALID_IN,
		CONTROL => NRZ1_TX_CONTROL,
		DATA_OUT => CENC1_DATA_IN,
		DATA_VALID_OUT => CENC1_SAMPLE_CLK_IN
	);

	NRZ1_TX_002: NRZ1 PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => SYNC_RESET_CLK_P,
		DATA_IN => NRZ1_TX_DATA2_IN,
		DATA_VALID_IN => NRZ1_TX_DATA2_VALID_IN,
		CONTROL => NRZ1_TX_CONTROL,
		DATA_OUT => CENC2_DATA_IN,
		DATA_VALID_OUT => CENC2_SAMPLE_CLK_IN
	);


--//-- FEC ENCODING --------------------------------------
-- two convolutional encoders
	ENCODER_ENABLED <= "11" when (REG61(6) = '1') else "00";
	CENC_CONTROL(0) <= '0';	-- N/A
	CENC_CONTROL(4 downto 1) <= "1011";	-- K=7,R=1/2, CCSDS
	CENC_CONTROL(5) <= '0';	-- no differential encoding
	CENC_CONTROL(6) <= '0';	-- continuous mode only
	CENC_CONTROL(7) <= '0';	-- N/A
	CENC_CONTROL(9 downto 8) <= "00";	-- 1-bit wide output
	CENC_CONTROL(11 downto 10) <= "00";	-- N/A
	CENC_CONTROL(12) <= '0';	-- flow control set by modulator symbol rate
	CENC_CONTROL(15 downto 13) <= "000";	-- N/A
	
	ENCODER_ROOT_1: ENCODER_ROOT PORT MAP(
		CLK => CLK_P,
		ASYNC_RESET => ASYNC_RESET,
		DATA_IN => CENC1_DATA_IN,	
		SAMPLE_CLK_IN => CENC1_SAMPLE_CLK_IN,	
		SAMPLE_CLK_IN_REQ => CENC1_SAMPLE_CLK_IN_REQ, 
		SOF_RESET => '0',
		DATA_OUT => CENC1_DATA_OUT,
		SAMPLE_CLK_OUT => CENC1_SAMPLE_CLK_OUT,
		SAMPLE_CLK_OUT_REQ => MOD_TX_CTS(0),
		CONTROL => CENC_CONTROL,
		TP => open
	);

	ENCODER_ROOT_2: ENCODER_ROOT PORT MAP(
		CLK => CLK_P,
		ASYNC_RESET => ASYNC_RESET,
		DATA_IN => CENC2_DATA_IN,	
		SAMPLE_CLK_IN => CENC2_SAMPLE_CLK_IN,	
		SAMPLE_CLK_IN_REQ => CENC2_SAMPLE_CLK_IN_REQ, 
		SOF_RESET => '0',
		DATA_OUT => CENC2_DATA_OUT,
		SAMPLE_CLK_OUT => CENC2_SAMPLE_CLK_OUT,
		SAMPLE_CLK_OUT_REQ => MOD_TX_CTS(1),
		CONTROL => CENC_CONTROL,
		TP => open
	);
	
	-- bypass encoder? 
	MOD_TX_DATA(0) <= CENC1_DATA_OUT(0) when (ENCODER_ENABLED(0) = '1') else CENC1_DATA_IN;
	MOD_TX_DATA(1) <= CENC2_DATA_OUT(0) when (ENCODER_ENABLED(1) = '1') else CENC2_DATA_IN;
	MOD_TX_DATA_SAMPLE_CLK(0) <= CENC1_SAMPLE_CLK_OUT when (ENCODER_ENABLED(0) = '1') else CENC1_SAMPLE_CLK_IN;
	MOD_TX_DATA_SAMPLE_CLK(1) <= CENC2_SAMPLE_CLK_OUT when (ENCODER_ENABLED(1) = '1') else CENC2_SAMPLE_CLK_IN;
	TX_DATA1b11_CTS <= CENC1_SAMPLE_CLK_IN_REQ when (ENCODER_ENABLED(0) = '1') else MOD_TX_CTS(0);
	TX_DATA1b12_CTS <= CENC2_SAMPLE_CLK_IN_REQ when (ENCODER_ENABLED(1) = '1') else MOD_TX_CTS(1);

    RECLOCK_001: process(CLK_P)
    begin
        if rising_edge(CLK_P) then
				MOD_LFSRA_INIT <= REG63(2 downto 0) & REG62;
					-- "10010010101",	-- NASA code 40 Mode2 return link 2225o
				MOD_LFSRC_INIT <= REG65(2 downto 0) & REG64;
					-- "01011011111",	-- 1337o
				MOD_CODE_MODE <= REG65(3);
					-- '0' forward command link, '1' return mode 2 link
            MOD_CHIP_RATE <= REG69 & REG68 & REG67 & REG66;	
					-- x"064DA741",		-- 3.077799479166 MChips/s
            MOD_SYMBOL_RATE1 <= REG73 & REG72 & REG71 & REG70;
            MOD_SYMBOL_RATE2 <= REG77 & REG76 & REG75 & REG74;
                -- symbol rates for I and Q channels. Not necessarily an integer number of chips.
                -- expressed as (processing clock frequency)/(symbol rate) * 2^32 
					-- "00346DC6",		-- 100 KSymbols/s
            MOD_CENTER_FREQ <= REG81 & REG80 & REG79 & REG78;
                -- Modulator center frequency (fine tuning)
            MOD_SINE_FREQ_OFFSET_AMPLITUDE <= x"00000000";
            MOD_SINE_FREQ_OFFSET_FREQUENCY <= x"00000000";
                -- test feature: sinusoidal frequency offset to test the demodulator
				MOD_CONTROL(0) <= REG61(0);	-- spectrum inversion
				MOD_CONTROL(1) <= REG61(1);	-- bpsk/sqpn
				MOD_CONTROL(2) <= REG61(2);	-- dual source, identical data on I/Q
				MOD_CONTROL(3) <= REG60(6);	-- 1/2 symbol delay on Q bit
            MOD_CONTROL(15 downto 4) <= (others => '0');
            MOD_GAIN <= REG30 & REG29;  -- Modulator gain, unsigned. 
        end if;
    end process;
    
    DSSS_MODULATOR_001: DSSS_MODULATOR_TDRSS
    generic map(
        SIMULATION => SIMULATION
        ) 
    PORT MAP(
        CLK => CLK_P,		
        SYNC_RESET => RECEIVER_RESET,  -- reset is MANDATORY to load the code generator initial condition
        TX_DATA => MOD_TX_DATA,
        TX_DATA_SAMPLE_CLK => MOD_TX_DATA_SAMPLE_CLK,
        TX_CTS => MOD_TX_CTS,
        CHIP_RATE => MOD_CHIP_RATE,
        SYMBOL_RATE1 => MOD_SYMBOL_RATE1,
        SYMBOL_RATE2 => MOD_SYMBOL_RATE2,
        LFSRA_INIT => MOD_LFSRA_INIT,
        LFSRC_INIT => MOD_LFSRC_INIT,
		  CODE_MODE => MOD_CODE_MODE,
        CODE_START_OUT => open,
        GAIN => MOD_GAIN,
        CENTER_FREQ => MOD_CENTER_FREQ,
        SINE_FREQ_OFFSET_AMPLITUDE => MOD_SINE_FREQ_OFFSET_AMPLITUDE,
        SINE_FREQ_OFFSET_FREQUENCY => MOD_SINE_FREQ_OFFSET_FREQUENCY,
        CONTROL => MOD_CONTROL,
        CONFIG_CHANGE_TOGGLE => CONFIG_CHANGE_TOGGLE,
        DATA_I_OUT => MOD_DATA_I,
        DATA_Q_OUT => MOD_DATA_Q,
        SATURATION => open,
        TP => MOD_TP
    );
    
	 -- enable/disable the modulated signal based on REG61(7)
	 MOD_DATA2_I <= MOD_DATA_I when (REG61(7) = '1') else (others => '0');
	 MOD_DATA2_Q <= MOD_DATA_Q when (REG61(7) = '1') else (others => '0');
	 
--    -- generate 6.25 MSamples/s sampling clock (to mimic the SDDS_rx component)
--    MOD_SAMPLING_CLK_GEN: process(CLK_P)
--    begin
--        if rising_edge(CLK_P) then
--				-- TODO: 6.25 MHz when receiver is receiving SDDS at 6.25 MHz, 
--				-- otherwise..... other frequencies or even 125 MHz
--            if(NCO_MOD_SAMPLING_CNTR = 0) or (SYNC_RESET_CLK_P = '1') then
--                -- re-arm counter
--                NCO_MOD_SAMPLING_CNTR <= 19;    -- divide by 20
--                MOD_SAMPLE_CLK <= '1';
--            else
--                NCO_MOD_SAMPLING_CNTR <= NCO_MOD_SAMPLING_CNTR - 1;
--                MOD_SAMPLE_CLK <= '0';
--            end if;
--        end if;
--    end process;
	MOD_SAMPLE_CLK <= '1';

    -- measure power (modulated signal)
    POWER_MEASUREMENT_001: POWER_MEASUREMENT PORT MAP(
        CLK => CLK_P,
        SYNC_RESET => SYNC_RESET_CLK_P,
        SAMPLE_CLK_IN => MOD_SAMPLE_CLK,
        DATA_I_IN => MOD_DATA2_I,
        DATA_Q_IN => MOD_DATA2_Q,
        SAMPLE_CLK_OUT => open,
        POWER_OUT => MOD_SIGNAL_POWER
    );

    -- report power measurements through status registers
    -- monitoring
   MONITORING_002a: process(CLK_P)
    begin
        if rising_edge(CLK_P) then
            if(LATCH_MONITORING_PULSE = '1') then
                SREG61 <= MOD_SIGNAL_POWER(7 downto 0);
                SREG62 <= MOD_SIGNAL_POWER(15 downto 8);
                SREG63 <= MOD_SIGNAL_POWER(23 downto 16);
            end if;
        end if;
    end process;
    
    --// ADDITIVE WHITE GAUSSIAN NOISE -------------------------------------
	AWGN_001: if(AWGN_EN = '1') generate
		 RECLOCK_002: process(CLK_P)
		 begin
			  if rising_edge(CLK_P) then
					-- maximum gain: x4.0
					NOISE_GAIN <= "0" & REG32 & REG31;   
			  end if;
		 end process;

		 -- Add noise for test purposes. 
		 -- latency 6 CLKs
		 AWGN_001: AWGN PORT MAP(
			  CLK => CLK_P,
			  SAMPLE_CLK_REQ => MOD_SAMPLE_CLK,    -- independent noise sample (complex) at 6.25 MSamples/s
			  SYNC_RESET => SYNC_RESET_CLK_P,
			  SAMPLE_CLK_OUT => open,
			  NOISE_SAMPLE1_OUT => NOISE_DATA1_I,
			  NOISE_SAMPLE2_OUT => NOISE_DATA1_Q
		 );

		 -- reclock before multiplier for better timing
		 GAIN_000: process(CLK_P)
		 begin
			  if rising_edge(CLK_P) then
					MOD_SAMPLE_CLK_SHIFT(9 downto 1) <= MOD_SAMPLE_CLK_SHIFT(8 downto 0);
					MOD_SAMPLE_CLK_SHIFT(0) <= MOD_SAMPLE_CLK;
					
					if(SIMULATION = '0') or (NOISE_DATA1_I(0) /= 'X') then
						NOISE_DATA1_I_D <= signed(NOISE_DATA1_I);  
					end if;
					if(SIMULATION = '0') or (NOISE_DATA1_Q(0) /= 'X') then
						NOISE_DATA1_Q_D <= signed(NOISE_DATA1_Q); 
					end if;
			  end if;
		 end process;
		 
		 NOISE_DATA2_I <= NOISE_DATA1_I_D * signed(NOISE_GAIN);
		 NOISE_DATA2_Q <= NOISE_DATA1_Q_D * signed(NOISE_GAIN);
		 
		 -- reclock for better timing
		 NOISE_RECLOCK_I1: process(CLK_P)
		 begin
			  if rising_edge(CLK_P) then
					if(NOISE_DATA2_I(32) = '0') and (NOISE_DATA2_I(31 downto 29) /= 0) then
						 -- positive saturation
						 NOISE_DATA3_I <= (17 => '0', others => '1');
						 NOISE_GAIN_I_SATURATION <= '1';
					elsif(NOISE_DATA2_I(32) = '1') and ((not NOISE_DATA2_I(31 downto 29)) /= 0) then
						 -- negative saturation
						 NOISE_DATA3_I <= (17 => '1', 0 => '1', others => '0');
						 NOISE_GAIN_I_SATURATION <= '1';
					else
						 NOISE_DATA3_I <= NOISE_DATA2_I(29 downto 12);
						 NOISE_GAIN_I_SATURATION <= '0';
					end if;
			  end if;
		 end process;
	 
		 NOISE_RECLOCK_Q1: process(CLK_P)
		 begin
			  if rising_edge(CLK_P) then
					if(NOISE_DATA2_Q(32) = '0') and (NOISE_DATA2_Q(31 downto 29) /= 0) then
						 -- positive saturation
						 NOISE_DATA3_Q <= (17 => '0', others => '1');
						 NOISE_GAIN_Q_SATURATION <= '1';
					elsif(NOISE_DATA2_Q(32) = '1') and ((not NOISE_DATA2_Q(31 downto 29)) /= 0) then
						 -- negative saturation
						 NOISE_DATA3_Q <= (17 => '1', 0 => '1', others => '0');
						 NOISE_GAIN_Q_SATURATION <= '1';
					else
						 NOISE_DATA3_Q <= NOISE_DATA2_Q(29 downto 12);
						 NOISE_GAIN_Q_SATURATION <= '0';
					end if;
			  end if;
		 end process;

		 SIGNAL_PLUS_NOISE: process(CLK_P)
		 begin
			  if rising_edge(CLK_P) then
					-- add signal and noise
					SN1_I <= resize(NOISE_DATA3_I,19) + resize(signed(MOD_DATA2_I),19);
					SN1_Q <= resize(NOISE_DATA3_Q,19) + resize(signed(MOD_DATA2_Q),19);
					
					-- detect saturation if any
					if(SN1_I(18) = '0') and (SN1_I(17) = '1') then  -- positive saturation
						 SN2_I <= (17 => '0', others => '1');
						 SN_I_SATURATION <= '1';
					elsif(SN1_I(18) = '1') and (SN1_I(17) = '0') then  -- negative saturation
						 SN2_I <= (17 => '1', 0 => '1', others => '0');
						 SN_I_SATURATION <= '1';
					else
						 SN2_I <= std_logic_vector(SN1_I(17 downto 0));
						 SN_I_SATURATION <= '0';
					end if;
					if(SN1_Q(18) = '0') and (SN1_Q(17) = '1') then  -- positive saturation
						 SN2_Q <= (17 => '0', others => '1');
						 SN_Q_SATURATION <= '1';
					elsif(SN1_Q(18) = '1') and (SN1_Q(17) = '0') then  -- negative saturation
						 SN2_Q <= (17 => '1', 0 => '1', others => '0');
						 SN_Q_SATURATION <= '1';
					else
						 SN2_Q <= std_logic_vector(SN1_Q(17 downto 0));
						 SN_Q_SATURATION <= '0';
					end if;
					
			  end if;
		 end process;
		 
		 SN2_SAMPLE_CLK <= MOD_SAMPLE_CLK_SHIFT(9);	-- MOD_SAMPLE_CLK_D10
		 
		 -- measure powers (noise, modulated signal)
		 POWER_MEASUREMENT_002b: POWER_MEASUREMENT PORT MAP(
			  CLK => CLK_P,
			  SYNC_RESET => SYNC_RESET_CLK_P,
			  SAMPLE_CLK_IN => MOD_SAMPLE_CLK_SHIFT(7),	-- MOD_SAMPLE_CLK_D8
			  DATA_I_IN => std_logic_vector(NOISE_DATA3_I),
			  DATA_Q_IN => std_logic_vector(NOISE_DATA3_Q),
			  SAMPLE_CLK_OUT => open,
			  POWER_OUT => NOISE_POWER
		 );

		 -- report power measurements through status registers
		 -- monitoring
		MONITORING_002: process(CLK_P)
		 begin
			  if rising_edge(CLK_P) then
					if(LATCH_MONITORING_PULSE = '1') then
						 SREG64 <= NOISE_POWER(7 downto 0);
						 SREG65 <= NOISE_POWER(15 downto 8);
						 SREG66 <= NOISE_POWER(23 downto 16);
					end if;
			  end if;
		 end process;
	end generate;	-- AWGN_EN = '1'

	AWGN_OFF: if(AWGN_EN = '0') generate
		-- no AWGN
		SN2_I <= MOD_DATA2_I;
		SN2_Q <= MOD_DATA2_Q;
		SN2_SAMPLE_CLK <= MOD_SAMPLE_CLK;
	end generate;
    
end generate;

--//--------------------------------------------------------------------------
--//	RIGHT CONNECTOR COM-3504 interface (Options -A/-B)
--//--------------------------------------------------------------------------
OUTPUT_OPTION_AB: if((OPTION = x"41") or (OPTION = x"42")) and (MODULATOR_EN = '1') and (DACs_EN = '1') generate
	--// COM-3504 BASEBAND TRANSCEIVER DRIVER (1/3: HIGH-SPEED DUAL DACs )------------------
	-- The COM-3504 plug-in module includes dual 250 MSamples/s 16-bit DACs
	-- and dual 150 MSamples/s 12-bit ADCs.
	-- Two auxiliary 12-bit DACs and one auxiliary 12-bit ADC are also available for
	-- gain control and power measurement.

	-- DAC clock output CLK125_2
	-- control the clock phase to minimize glitches
	-- regenerate the 125 MHz clock
	
	-- It is recommended to only use a BUFG resource to drive clock loads.
	-- It is recommended to use a Clock Forwarding technique to create a reliable and repeatable 
	-- low skew solution, i.e. use ODDR to regenerate the output clock.
	-- + invert DAC clock to create a delay between output data 
	-- to meet the tDBS = 400ps setup, tDBH = 1200ps hold requirements.
	DAC_CLKOUT_GEN_001P : ODDR
	generic map(
	  DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" 
	  INIT => '0',   -- Initial value for Q port ('1' or '0')
	  SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
	port map (
	  Q => RIGHT_CONNECTOR_A(19),   -- 1-bit DDR output
	  C => CLK125_2,    -- 1-bit clock input
	  CE => '1',  -- 1-bit clock enable input
	  D1 => '0',  -- 1-bit data input (positive edge)
	  D2 => '1',  -- 1-bit data input (negative edge)
	  R => '0',    -- 1-bit reset input
	  S => '0'     -- 1-bit set input
	);			
		
	-- fake differential output (LVDS_33 is incompatible with LVCMOS33 in the same bank!)
	DAC_CLKOUT_GEN_001N : ODDR
	generic map(
	  DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" 
	  INIT => '0',   -- Initial value for Q port ('1' or '0')
	  SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
	port map (
	  Q => RIGHT_CONNECTOR_A(20),   -- 1-bit DDR output
	  C => CLK125_2,    -- 1-bit clock input
	  CE => '1',  -- 1-bit clock enable input
	  D1 => '1',  -- 1-bit data input (positive edge)
	  D2 => '0',  -- 1-bit data input (negative edge)
	  R => '0',    -- 1-bit reset input
	  S => '0'     -- 1-bit set input
	);

	DAC_RECLOCK_001: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			-- map COM-3504 interface
			RIGHT_CONNECTOR_A(3) <= not SN2_I(17);	-- to unsigned (offset binary) format
			RIGHT_CONNECTOR_A(4) <= SN2_I(16);
			RIGHT_CONNECTOR_A(5) <= SN2_I(15);
			RIGHT_CONNECTOR_A(6) <= SN2_I(14);
			RIGHT_CONNECTOR_A(7) <= SN2_I(13);
			RIGHT_CONNECTOR_A(8) <= SN2_I(12);
			RIGHT_CONNECTOR_A(9) <= SN2_I(11);
			RIGHT_CONNECTOR_A(10) <= SN2_I(10);
			RIGHT_CONNECTOR_A(11) <= SN2_I(9);
			RIGHT_CONNECTOR_A(12) <= SN2_I(8);
			RIGHT_CONNECTOR_A(13) <= SN2_I(7);
			RIGHT_CONNECTOR_A(14) <= SN2_I(6);
			RIGHT_CONNECTOR_A(15) <= SN2_I(5);
			RIGHT_CONNECTOR_A(16) <= SN2_I(4);
			RIGHT_CONNECTOR_A(17) <= SN2_I(3);
			RIGHT_CONNECTOR_A(18) <= SN2_I(2);

			RIGHT_CONNECTOR_A(21) <= not SN2_Q(17);	-- to unsigned (offset binary) format
			RIGHT_CONNECTOR_A(22) <= SN2_Q(16);
			RIGHT_CONNECTOR_A(23) <= SN2_Q(15);
			RIGHT_CONNECTOR_A(24) <= SN2_Q(14);
			RIGHT_CONNECTOR_A(25) <= SN2_Q(13);
			RIGHT_CONNECTOR_A(26) <= SN2_Q(12);
			RIGHT_CONNECTOR_A(27) <= SN2_Q(11);
			RIGHT_CONNECTOR_A(28) <= SN2_Q(10);
			RIGHT_CONNECTOR_A(29) <= SN2_Q(9);
			RIGHT_CONNECTOR_A(30) <= SN2_Q(8);
			RIGHT_CONNECTOR_A(31) <= SN2_Q(7);
			RIGHT_CONNECTOR_A(32) <= SN2_Q(6);
			RIGHT_CONNECTOR_A(33) <= SN2_Q(5);
			RIGHT_CONNECTOR_A(34) <= SN2_Q(4);
			RIGHT_CONNECTOR_A(35) <= SN2_Q(3);
			RIGHT_CONNECTOR_A(36) <= SN2_Q(2);
		end if;
	end process;
	
	RECLOCK_CTRLS_002: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			TX_GAIN_DAC(7 downto 0) <= REG59;	-- latch tx gain control
			TX_GAIN_DAC(11 downto 8) <= REG60(3 downto 0);
			RIGHT_CONNECTOR_B4(33) <= REG60(4);	-- TX_ENB
			RIGHT_CONNECTOR_B4(34) <= '1';	-- RX_TXn. Does not matter because COM-3506 operates in full duplex
		end if;
	end process;
	
end generate;


--//--------------------------------------------------------------------------
--//	RIGHT CONNECTOR COM-4009 interface (Options C, D)
--//--------------------------------------------------------------------------
-- Same design for all COM-18xx (1805,1806,1827,etc)
-- Verified I/Q order and frequency translation sign 10/28/18

OUTPUT_OPTION_CD: if((OPTION = x"43") or (OPTION = x"44")) and (MODULATOR_EN = '1') and (DACs_EN = '1') generate
	--// COM-4009 RF MODULATOR DRIVER ------------------
	RIGHT_CONNECTOR_A(1) <= READY_FLAG_CLK_P;	-- modulator PDN
	RIGHT_CONNECTOR_A(2) <= READY_FLAG_CLK_P;	-- modulator TX_EN
	RIGHT_CONNECTOR_A(3) <= '0';	-- modulator FREQ_HOP


	-- This interfaces a dual DAC up to 160 MSamples/s 2*16-bit
	-- DAC_REFCLK rising edge at center of I data, ideally
	DAC_REFCLK_001 : ODDR
	generic map(
	  DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" 
	  INIT => '0',   -- Initial value for Q port ('1' or '0')
	  SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
	port map (
	  Q => DAC_REFCLK,   -- 1-bit DDR output
	  C => CLK_P,    -- 1-bit clock input
	  CE => '1',  -- 1-bit clock enable input
	  D1 => '0',  -- 1-bit data input (positive edge)  
	  D2 => '1',  -- 1-bit data input (negative edge)	rising edge to latch I
	  R => '0',    -- 1-bit reset input
	  S => '0'     -- 1-bit set input
	);			

	-- LVDS25 output
	DAC_REFCLK_002 : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_B3(22),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_B3(21),   -- Diff_n output (connect directly to top-level port)
		I => DAC_REFCLK     -- Buffer input 
	);

	-- DAC_DCI, 1 for I, 0 for Q. Aligned with DDR data
	-- Verified I/Q order and frequency translation sign 10/28/18
	DAC_DCI_001 : ODDR
	generic map(
	  DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" 
	  INIT => '0',   -- Initial value for Q port ('1' or '0')
	  SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
	port map (
	  Q => DAC_DCI,   -- 1-bit DDR output
	  C => CLK_P,    -- 1-bit clock input
	  CE => '1',  -- 1-bit clock enable input
	  D1 => '1',  -- 1-bit data input (positive edge)	-- 1 for I, 0 for Q
	  D2 => '0',  -- 1-bit data input (negative edge)
	  R => '0',    -- 1-bit reset input
	  S => '0'     -- 1-bit set input
	);			

	-- LVDS25 output
	DAC_DCI_002 : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_A(22),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_A(21),   -- Diff_n output (connect directly to top-level port)
		I => DAC_DCI     -- Buffer input 
	);

	-- LVDS DCO  Maybe unused.
	DAC_CLKIN_GEN_001 : IBUFDS
	generic map (
		DIFF_TERM => FALSE, -- Differential Termination 
		IBUF_LOW_PWR => TRUE, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
		IOSTANDARD => "LVDS_25" -- Specify the output I/O standard
		)          -- Specify the output slew rate
	port map (
		I => RIGHT_CONNECTOR_A(20),     -- Diff_p output (connect directly to top-level port)
		IB => RIGHT_CONNECTOR_A(19),   -- Diff_n output (connect directly to top-level port)
		O => DAC_DCO      -- Buffer input 
	);

	-- Note: output is 2's complement
	-- COM-4009 currently uses 12-bit DAC AD9780. Change if AD9781 or AD9783
	--DAC_DX_001: for I in 0 to 15 generate
	DAC_DX_001: for I in 4 to 15 generate
		DAC_D_001: ODDR
		generic map(
		  DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" 
		  INIT => '0',   -- Initial value for Q port ('1' or '0')
		  SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
		port map (
		  Q => DAC_D(I),   -- 1-bit DDR output
		  C => CLK_P,    -- 1-bit clock input
		  CE => '1',  -- 1-bit clock enable input
		  D1 => SN2_I(I+2),  -- 1-bit data input (positive edge)
		  D2 => SN2_Q(I+2),  -- 1-bit data input (negative edge)
		  R => '0',    -- 1-bit reset input
		  S => '0'     -- 1-bit set input
		);			
	end generate;

	DAC_D15_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_B4(39),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_B4(38),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(15)     -- Buffer input 
	);

	DAC_D14_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_A(38),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_A(37),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(14)     -- Buffer input 
	);

	DAC_D13_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_B4(37),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_B4(36),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(13)     -- Buffer input 
	);

	DAC_D12_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_A(36),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_A(35),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(12)     -- Buffer input 
	);

	DAC_D11_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_B4(35),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_B4(34),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(11)     -- Buffer input 
	);

	DAC_D10_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_A(34),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_A(33),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(10)     -- Buffer input 
	);

	DAC_D9_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_B4(33),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_B4(32),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(9)     -- Buffer input 
	);

	DAC_D8_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_A(32),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_A(31),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(8)     -- Buffer input 
	);

	DAC_D7_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_B3(30),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_B3(29),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(7)     -- Buffer input 
	);

	DAC_D6_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_A(30),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_A(29),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(6)     -- Buffer input 
	);

	DAC_D5_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_B3(28),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_B3(27),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(5)     -- Buffer input 
	);

	DAC_D4_GEN : OBUFDS
	generic map (
		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
		SLEW => "SLOW")          -- Specify the output slew rate
	port map (
		O => RIGHT_CONNECTOR_A(28),     -- Diff_p output (connect directly to top-level port)
		OB => RIGHT_CONNECTOR_A(27),   -- Diff_n output (connect directly to top-level port)
		I => DAC_D(4)     -- Buffer input 
	);

-- COM-4009 currently uses 12-bit DAC AD9780. Change if AD9781 or AD9783
--	DAC_D3_GEN : OBUFDS
--	generic map (
--		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
--		SLEW => "SLOW")          -- Specify the output slew rate
--	port map (
--		O => RIGHT_CONNECTOR_B3(26),     -- Diff_p output (connect directly to top-level port)
--		OB => RIGHT_CONNECTOR_B3(25),   -- Diff_n output (connect directly to top-level port)
--		I => DAC_D(3)     -- Buffer input 
--	);
--
--	DAC_D2_GEN : OBUFDS
--	generic map (
--		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
--		SLEW => "SLOW")          -- Specify the output slew rate
--	port map (
--		O => RIGHT_CONNECTOR_A(26),     -- Diff_p output (connect directly to top-level port)
--		OB => RIGHT_CONNECTOR_A(25),   -- Diff_n output (connect directly to top-level port)
--		I => DAC_D(2)     -- Buffer input 
--	);
--
--	DAC_D1_GEN : OBUFDS
--	generic map (
--		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
--		SLEW => "SLOW")          -- Specify the output slew rate
--	port map (
--		O => RIGHT_CONNECTOR_B3(24),     -- Diff_p output (connect directly to top-level port)
--		OB => RIGHT_CONNECTOR_B3(23),   -- Diff_n output (connect directly to top-level port)
--		I => DAC_D(1)     -- Buffer input 
--	);
--
--	DAC_D0_GEN : OBUFDS
--	generic map (
--		IOSTANDARD => "LVDS_25", -- Specify the output I/O standard
--		SLEW => "SLOW")          -- Specify the output slew rate
--	port map (
--		O => RIGHT_CONNECTOR_A(24),     -- Diff_p output (connect directly to top-level port)
--		OB => RIGHT_CONNECTOR_A(23),   -- Diff_n output (connect directly to top-level port)
--		I => DAC_D(0)     -- Buffer input 
--	);
end generate;

--//==============================================================================
--//==============================================================================
--// RECEIVER SECTION
--//==============================================================================
--//==============================================================================


--//--------------------------------------------------------------------------
--//	LEFT CONNECTOR COM-30XX interface (Options C,D)
--//--------------------------------------------------------------------------
INPUT_OPTIONS_CD: if((OPTION = x"43") or (OPTION = x"44")) and (DEMODULATOR_EN = '1') and (ADCs_EN = '1') generate
	
	LEFT_CONNECTOR_A(13 downto 2) <= (others => 'Z'); 
	LEFT_CONNECTOR_B1(4 downto 1) <= (others => 'Z'); 
	LEFT_CONNECTOR_B2(14 downto 6) <= (others => 'Z'); 
	-- make sure LEFT_CONNECTOR_A(13) is understood as an input. Connect to an unused dummy test point 
	SREG36(7) <= LEFT_CONNECTOR_A(13);	-- dummy, for COM-3010
	
	BUFG_001: BUFG port map(I => LEFT_CONNECTOR_A(1), O => CLK_RX);

	-- select reference clock
	BUFGMUX_001 : BUFGMUX
	port map (
		O => CLK_RXg,   -- 1-bit output: Clock output
		I0 => CLK_RX, -- COM-30XX clock
		I1 => CLK_P, -- 1-bit input: Clock input (S=1)
		S => LOOPBACK_MODE    -- 1-bit input: Clock select
	);


	-- Immediately resample inputs at the rising edge of the input clock
	RX_INPUT_RECLOCK_001: process(CLK_RXg)
	begin
		if rising_edge(CLK_RXg) then
			--data enable (ignore) <= LEFT_CONNECTOR_B1(1);
			RX_DATA0CD_I(11) <= not LEFT_CONNECTOR_A(2); -- convert to 2's complement signed
			RX_DATA0CD_I(10) <= LEFT_CONNECTOR_B1(2);
			RX_DATA0CD_I(9) <= LEFT_CONNECTOR_A(3);
			RX_DATA0CD_I(8) <= LEFT_CONNECTOR_B1(3);
			RX_DATA0CD_I(7) <= LEFT_CONNECTOR_A(4);
			RX_DATA0CD_I(6) <= LEFT_CONNECTOR_B1(4);
			RX_DATA0CD_I(5) <= LEFT_CONNECTOR_A(5);
			RX_DATA0CD_I(4) <= LEFT_CONNECTOR_A(6);
			RX_DATA0CD_I(3) <= LEFT_CONNECTOR_B2(6);
			RX_DATA0CD_I(1) <= LEFT_CONNECTOR_B2(14);
			RX_DATA0CD_I(2) <= LEFT_CONNECTOR_A(7);
			--RX_DATA0CD_I(0) <= LEFT_CONNECTOR_A(15);

			-- complex I/Q
			RX_DATA0CD_Q(11) <= not LEFT_CONNECTOR_B2(7);    -- convert to 2's complement signed
			RX_DATA0CD_Q(10) <= LEFT_CONNECTOR_A(8);
			RX_DATA0CD_Q(9) <= LEFT_CONNECTOR_B2(8);
			RX_DATA0CD_Q(8) <= LEFT_CONNECTOR_A(9);
			RX_DATA0CD_Q(7) <= LEFT_CONNECTOR_B2(9);
			RX_DATA0CD_Q(6) <= LEFT_CONNECTOR_A(10);
			RX_DATA0CD_Q(5) <= LEFT_CONNECTOR_A(11);
			RX_DATA0CD_Q(4) <= LEFT_CONNECTOR_B2(11);
			RX_DATA0CD_Q(3) <= LEFT_CONNECTOR_A(12);
			RX_DATA0CD_Q(2) <= LEFT_CONNECTOR_B2(12);
			--RX_DATA0CD_Q(1) <= LEFT_CONNECTOR_A(16);
			RX_DATA0CD_Q(0) <= LEFT_CONNECTOR_B2(16);
		end if;
	end process;

--	RX_INPUT_RECLOCK_001b: if(OPTION /= x"44") generate
--		-- alleviate incompatibility Bank35 can't have both LVDS and LVCMOS33
--		RX_INPUT_RECLOCK_001b: process(CLK_RXg)
--		begin
--			if rising_edge(CLK_RXg) then
--				RX_DATA0CD_I(0) <= LEFT_CONNECTOR_A(15);	
--				RX_DATA0CD_Q(1) <= LEFT_CONNECTOR_A(16);
--			end if;
--		end process;
--		LEFT_CONNECTOR_A(15) <= 'Z';
--		LEFT_CONNECTOR_A(16) <= 'Z';
--	end generate;

--	-- optional ADC sampling clock output
--	-- Beware: in some cases (COM-3010 for instance), one must remove a resistor to prevent clock conflicts.  
--	LEFT_CONNECTOR_A14_GEN: process(CLK_RX_OUTg, CLK_RX_GEN_EN)
--	begin
--		if (CLK_RX_GEN_EN = '1') then
--			LEFT_CONNECTOR_A(14) <= CLK_RX_OUTg;	
--		else
			LEFT_CONNECTOR_A(14) <= 'Z';
--		end if;
--	end process;

    -- cross clock domains from CLK_RXg to CLK_P
    RX_DATA0CD <= RX_DATA0CD_I & RX_DATA0CD_Q;
	CROSS_CLK_DOMAINS_001: CROSS_CLK_DOMAINS 
	GENERIC MAP(
		NBITS => 24	
	)
	PORT MAP(
		CLK_A => CLK_RXg,
		CLK_B => CLK_P,
		ASYNC_RESET => ASYNC_RESET,
		DATA_IN => RX_DATA0CD,
		DATA_OUT => RX_DATA0	
	);
	RX_DATA0_I <= RX_DATA0(23 downto 12);
	RX_DATA0_Q <= RX_DATA0(11 downto 0);
	
	-- serial DAC driver
	-- A 12-bit DAC/Analog output is built-in for gain control. 
	-- The DAC output is connected to pin "B13" of the left connector. 
	-- The DAC can be disabled in software to a high impedance state or 
	-- physically disabled by removing the 0. Ohm R73 resistor. The DAC can 
	-- typically operate at a 0.5V/µsec slew rate. The output voltage range 
	-- is from 0 to 3.3 V. The driver provided in the code template allows 
	-- for approximate refresh rate of up to 1.765 MHz (slew rate limited.)
	AUX_DAC1: DAC_AD5621 
		GENERIC MAP(
			CLK_FREQUENCY => 104	-- maximum frequency for CLK_RXg
		)
		PORT MAP(
		CLK => CLK_RXg,							-- synchronous clock
		DATA_IN => AGC_DAC,		-- user 12-bit input data
		DATA_IN_CLK => AGC_DAC_SAMPLE_CLK,		-- user enable
		OP_MODE(0) => AUX_DAC1_OP_MODE(0),			-- "00" for normal DAC operation, "11" for high impedance output
		OP_MODE(1) => AUX_DAC1_OP_MODE(1),
		DONE => open,				-- tell user when the DAC is ready for the next input sample
		--// DAC interface, left connector
		SYNC_B => DAC_SYNC_B,					
		SCLK => DAC_SCLK,						
		SDIN => DAC_SDIN						
		);
		AUX_DAC1_OP_MODE <= "00";	-- J4.b13 output always on.
	
end generate;

--//--------------------------------------------------------------------------
--//	RIGHT CONNECTOR COM-3504 interface  (Options A,B)
--//--------------------------------------------------------------------------
INPUT_OPTIONS_AB: if((OPTION = x"41") or (OPTION = x"42")) and (DEMODULATOR_EN = '1') and (ADCs_EN = '1') generate

	-- send differential clock to the dual ADC
	ADC_CLK_OUT_P : ODDR
	generic map(
	  DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" 
	  INIT => '0',   -- Initial value for Q port ('1' or '0')
	  SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
	port map (
	  Q => RIGHT_CONNECTOR_B3(29),   -- 1-bit DDR output
	  C => CLK_P,    -- 1-bit clock input
	  CE => '1',  -- 1-bit clock enable input
	  D1 => '1',  -- 1-bit data input (positive edge)
	  D2 => '0',  -- 1-bit data input (negative edge)
	  R => '0',    -- 1-bit reset input
	  S => '0'     -- 1-bit set input
	);			

	ADC_CLK_OUT_N : ODDR
	generic map(
	  DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" 
	  INIT => '0',   -- Initial value for Q port ('1' or '0')
	  SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
	port map (
	  Q => RIGHT_CONNECTOR_B3(30),   -- 1-bit DDR output
	  C => CLK_P,    -- 1-bit clock input
	  CE => '1',  -- 1-bit clock enable input
	  D1 => '0',  -- 1-bit data input (positive edge)
	  D2 => '1',  -- 1-bit data input (negative edge)
	  R => '0',    -- 1-bit reset input
	  S => '0'     -- 1-bit set input
	);			


	--COM3504_ADC_DCO(0) <= RIGHT_CONNECTOR_B2(1);	-- clock from ADC1
	COM3504_ADC1_DIN(11) <= not RIGHT_CONNECTOR_B1(2);
	COM3504_ADC1_DIN(10) <= RIGHT_CONNECTOR_B1(3);
	COM3504_ADC1_DIN(9) <= RIGHT_CONNECTOR_B1(4);
	COM3504_ADC1_DIN(8) <= RIGHT_CONNECTOR_B2(6);
	COM3504_ADC1_DIN(7) <= RIGHT_CONNECTOR_B2(7);
	COM3504_ADC1_DIN(6) <= RIGHT_CONNECTOR_B2(8);
	COM3504_ADC1_DIN(5) <= RIGHT_CONNECTOR_B2(9);
	COM3504_ADC1_DIN(4) <= RIGHT_CONNECTOR_B2(10);
	COM3504_ADC1_DIN(3) <= RIGHT_CONNECTOR_B2(11);
	COM3504_ADC1_DIN(2) <= RIGHT_CONNECTOR_B2(12);
	COM3504_ADC1_DIN(1) <= RIGHT_CONNECTOR_B2(13);
	COM3504_ADC1_DIN(0) <= RIGHT_CONNECTOR_B2(14);
	--COM3504_ADC_DCO(1) <= RIGHT_CONNECTOR_B2(15);	-- clock from ADC2
	COM3504_ADC2_DIN(11) <= not RIGHT_CONNECTOR_B2(16);
	COM3504_ADC2_DIN(10) <= RIGHT_CONNECTOR_B2(17);
	COM3504_ADC2_DIN(9) <= RIGHT_CONNECTOR_B2(18);
	COM3504_ADC2_DIN(8) <= RIGHT_CONNECTOR_B2(19);
	COM3504_ADC2_DIN(7) <= RIGHT_CONNECTOR_B3(21);
	COM3504_ADC2_DIN(6) <= RIGHT_CONNECTOR_B3(22);
	COM3504_ADC2_DIN(5) <= RIGHT_CONNECTOR_B3(23);
	COM3504_ADC2_DIN(4) <= RIGHT_CONNECTOR_B3(24);
	COM3504_ADC2_DIN(3) <= RIGHT_CONNECTOR_B3(25);
	COM3504_ADC2_DIN(2) <= RIGHT_CONNECTOR_B3(26);
	COM3504_ADC2_DIN(1) <= RIGHT_CONNECTOR_B3(27);
	COM3504_ADC2_DIN(0) <= RIGHT_CONNECTOR_B3(28);
	RIGHT_CONNECTOR_B1(4 downto 1) <= (others => 'Z');
	RIGHT_CONNECTOR_B2(19 downto 6) <= (others => 'Z');
	RIGHT_CONNECTOR_B3(28 downto 21) <= (others => 'Z');

	-- reclock input samples at the rising edge of ADC_DCO() = CLK_P 
	RECLOCK_ADC_INPUTS: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			RX_DATA0_I <= COM3504_ADC1_DIN;
			RX_DATA0_Q <= COM3504_ADC2_DIN;
		end if;
	end process;
end generate;

--//-- COM-3504 BASEBAND TRANSCEIVER DRIVER (2/3 EXTERNAL TX CONTROLS)------------------
COM3504_002: if((OPTION = x"41") or (OPTION = x"42")) and ((DACs_EN = '1') or (ADCs_EN = '1')) generate
							
	-- AGC signal to auxiliary DAC
	-- SPI bus sharing logic. 
	Inst_AUX_DACS_ADC: AUX_DACS_ADC 
	generic map(
		CLK_FREQUENCY => CLK_FREQUENCY	-- CLK_P frequency 
	)
	PORT MAP(
		CLK => CLK_P,
		ASYNC_RESET => ASYNC_RESET,
		AUXDAC1_DIN => AGC_DAC,
		AUXDAC2_DIN => TX_GAIN_DAC,
		AUXADC1_DOUT => open,
		TIMESLOTS_AUXDAC1 => x"7FFF",	-- AGC_DAC transactions (15/16 timeslots)
		TIMESLOTS_AUXDAC2 => x"8000",	-- 1/16 timeslot
		TIMESLOTS_AUXADC1 => x"0000", -- 0/16 timeslot
		AUX_SPI1 => RIGHT_CONNECTOR_B4(37), --SPI_SDATA,
		AUX_SPI2 => RIGHT_CONNECTOR_B4(38), --SPI_SCLK,
		AUX_SPI3 => RIGHT_CONNECTOR_B4(39), --SPI_DAC1_SYNC,
		AUX_SPI4 => RIGHT_CONNECTOR_A(37), --SPI_DAC2_SYNC,
		AUX_SPI5 => RIGHT_CONNECTOR_A(38) --SPI_ADC_SYNC
	);
end generate;

						
--//-- DSSS DEMODULATOR ----------------------------------------
-- Includes AGC, frequency translation to baseband, decimation, LPF, demodulation, BER measurement, etc.
RECEIVER_RESET <= SYNC_RESET_CLK_P or CONFIG_CHANGE_PULSE;
-- reclock with CLK_P for easier P&R
RECLOCK_DEMOD_CONFIG_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		DEMOD_LFSRA_INIT <= REG2(2 downto 0) & REG1;
			-- "10010010101",	-- NASA code 40 Mode2 return link 2225o
		DEMOD_LFSRC_INIT <= REG4(2 downto 0) & REG3;
			-- "01011011111",	-- 1337o
		DEMOD_CODE_MODE <= REG27(4);
			-- '0' forward command link, '1' return mode 2 link
		NOMINAL_CHIP_RATE <= REG8 & REG7 & REG6 & REG5;	 -- x"064DA741",		-- 3.077799479166 MChips/s
		NOMINAL_CHIP_RATE_DYNAMIC <= signed(NOMINAL_CHIP_RATE) + CFT_FREQ;
		if(REG4(7 downto 3) = "00000") and (REG2(7 downto 3) = "00000") then
			CIC_R <= x"0001";	-- min value 1
		else
			CIC_R <= "000000" & REG4(7 downto 3) & REG2(7 downto 3);
				-- CIC_R largest integer < 4*input sampling rate/chip rate
				-- 0 illegal, 1 min value
		end if;
		NOMINAL_SYMBOL_RATE1 <= REG12 & REG11 & REG10 & REG9;
		NOMINAL_SYMBOL_RATE2 <= REG16 & REG15 & REG14 & REG13;
			-- "00346DC6",		-- 100 KSymbols/s
		SPREADING_FACTOR1 <= REG18(4 downto 0) & REG17;
		SPREADING_FACTOR2 <= REG20(4 downto 0) & REG19;
			-- "0000000011111",	-- 31
		RECEIVER_CENTER_FREQ <= REG24 & REG23 & REG22 & REG21;
		RECEIVER_CENTER_FREQ_DYNAMIC <= signed(RECEIVER_CENTER_FREQ) + FT_FREQ;
		FREQ_SCAN_N_COARSE_STEPS <= x"00"; 
		DEMOD_CONTROL(0) <= REG26(0);	-- bit 0: spectrum inversion off (0), on (1)
		DEMOD_CONTROL(1) <= REG26(1);	-- bit 1: BPSK (0) vs SQPN(1)
		DEMOD_CONTROL(2) <= REG26(2);	-- bit 2: independent symbol rates on I/Q (0),or identical synchronized symbol rates on I/Q(1)
		DEMOD_CONTROL(5 downto 3) <= "000";	-- bits 3-5: encoding (done after Viterbi decoding), unless it is biphase (TODO future)
		DEMOD_CONTROL(6) <= REG26(6);	-- bit 6: 1/2 symbol Q delay at modulator (=1/2 symbol I delay at demod)
		DEMOD_CONTROL(7) <= REG26(7);	-- bit 7: alternating I/Q bits (yes = 1, no = 0)
		DEMOD_CONTROL(15 downto 8) <= "0000001" & REG27(0);	-- always serial soft-quantized output
		FEC_DEC_ENABLE <= REG27(1);
		FEC_G1_INVERSION <= REG27(2);
		RECEIVER_AGC_RESPONSE <= REG28(4 downto 0);
		LOOPBACK_MODE <= REG28(7) and MODULATOR_EN;
	end if;
end process;

-- demodulator input selection: SDDS or loopback?
DEMOD_INPUT_SEL: process(CLK_P)
begin
    if rising_edge(CLK_P) then
        
        if(LOOPBACK_MODE = '1') then
            -- modulated waveform samples generated within (in dsss_modulator_tdrss)
            RX_DATA2_I <= SN2_I(17 downto 4);
            RX_DATA2_Q <= SN2_Q(17 downto 4);
            RX_SAMPLE2_CLK <= SN2_SAMPLE_CLK;
         elsif(REG28(7 downto 5) = "010") then
				-- A/D converters input samples, baseband I/Q
            RX_DATA2_I <= RX_DATA0_I & "00";
            RX_DATA2_Q <= RX_DATA0_Q & "00";
            RX_SAMPLE2_CLK <= '1';
         elsif(REG28(7 downto 5) = "011") then
				-- A/D converters input samples, IF undersampling
            RX_DATA2_I <= RX_DATA0_I & "00";
            RX_DATA2_Q <= (others => '0');
            RX_SAMPLE2_CLK <= '1';
        else
            -- modulated waveform samples through SDDS
            RX_DATA2_I <= RX_DATA1_I(15 downto 2);
            RX_DATA2_Q <= RX_DATA1_Q(15 downto 2);
            RX_SAMPLE2_CLK <= RX_SAMPLE1_CLK;
        end if;
    end if;
end process;

--// DSSS demodulator ------------------------------	
COM1826_001: COM1826 
generic map(
	BER_EN => '0',	-- BER is done at top level (after FEC decoding)
	SIMULATION => SIMULATION
	) 
PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => RECEIVER_RESET,  -- reset is MANDATORY to load the code generator initial condition
	ADC_DATA_I_IN => RX_DATA2_I,
	ADC_DATA_Q_IN => RX_DATA2_Q,
	ADC_SAMPLE_CLK_IN => RX_SAMPLE2_CLK,
	AGC_DAC => AGC_DAC,
	AGC_DAC_SAMPLE_CLK => AGC_DAC_SAMPLE_CLK,
	AGC_RESPONSE => RECEIVER_AGC_RESPONSE,
	RECEIVER_CENTER_FREQ => std_logic_vector(RECEIVER_CENTER_FREQ_DYNAMIC),	
	NOMINAL_CHIP_RATE => std_logic_vector(NOMINAL_CHIP_RATE_DYNAMIC),	
	CIC_R => CIC_R,
	NOMINAL_SYMBOL_RATE1 => NOMINAL_SYMBOL_RATE1,
	NOMINAL_SYMBOL_RATE2 => NOMINAL_SYMBOL_RATE2,
	SPREADING_FACTOR1 => SPREADING_FACTOR1, 
	SPREADING_FACTOR2 => SPREADING_FACTOR2,
	LFSRA_INIT => DEMOD_LFSRA_INIT, 
	LFSRC_INIT => DEMOD_LFSRC_INIT, 
	CODE_MODE => DEMOD_CODE_MODE,
	FREQ_SCAN_N_COARSE_STEPS => FREQ_SCAN_N_COARSE_STEPS,
	DEMOD_CONTROL => DEMOD_CONTROL,			
	RESET_DEMOD_IN_FALSE_LOCK => '0',
	DATA_I_OUT => DATA_I_OUT,
	DATA_Q_OUT => DATA_Q_OUT,
	SAMPLE_I_CLK_OUT => SAMPLE_I_CLK_OUT,
	SAMPLE_Q_CLK_OUT => SAMPLE_Q_CLK_OUT,
	SYNC_PULSE => open,
	CARRIER_LOCK_OUT => CARRIER_LOCK_OUT,
	CODE_LOCK_OUT => CODE_LOCK_OUT,
	SIGNAL_PRESENT_OUT => SIGNAL_PRESENT_OUT,
	CARRIER_FREQUENCY_ERROR1 => CARRIER_FREQUENCY_ERROR1,
	CARRIER_FREQUENCY_ERROR2 => CARRIER_FREQUENCY_ERROR2,
	POWER_S_AVERAGE_OUT => POWER_S_AVERAGE_OUT,
	POWER_N_AVERAGE_OUT => POWER_N_AVERAGE_OUT,
	SNR1_LOCKED_OUT => SNR1_LOCKED_OUT,
	SNR2_LOCKED_OUT => SNR2_LOCKED_OUT,
	DESPREAD1_I_OUT => open,
	DESPREAD1_Q_OUT => open,
	DESPREAD1_SAMPLE_CLK => open,
	BER_SYNC => open,
	BER_ERROR_COUNT => open,
	BYTE_ERROR => open,
	CS0 => open,
	CS0_CLK => open,	
	CS1 => open,	--  spread I-channel after frequency scanning, resampling and channel LPF filter
	CS1_CLK => open,
	CS2 => S1_3,	--  despread I-channel after coherent I&D, 2 samples/symbol
	CS2_CLK => S1_3_CLK,
	CS3 => open,	-- despread Q-channel after coherent I&D
	CS3_CLK => open,
	CS4 =>  S2_3,		-- demodulated I, 1 sample/symbol
	CS4_CLK => S2_3_CLK,
	CS5 => S1_2,	-- demodulated Q
	CS5_CLK => S1_2_CLK,
	CS6 => open,	--  agc18 scaling gain
	CS6_CLK => open,
	CS7 => S2_2,	-- code replica, 2 samples/chip
	CS7_CLK => S2_2_CLK,
	CS8 =>  S3_1,		-- accumulated code tracking phase correction (8 MSbs)
	CS8_CLK => S3_1_CLK,
	CS9 => S3_2,	-- accumulated carrier phase correction(8 MSBs)
	CS9_CLK => S3_2_CLK,
	CS10 =>  S3_3,		-- accumulated symbol timing phase correction (8 MSbs)
	CS10_CLK => S3_3_CLK,
	CS11 =>  S1_4,		-- 2(S+N)/N, valid only if code lock. Linear, not in dBs.
	CS11_CLK => S1_4_CLK,
	T1 => 	T1,			-- start of code replica
	T1_CLK => T1_CLK,
	T2 => T2,			-- code lock (1-bit). assessed once per code-sweep period
	T2_CLK => T2_CLK,
	TP => DEMOD_TP
);

-- create a 1s hysteresis for fast toggling status signals
STATUS_1S: process(CLK_P)
begin
    if rising_edge(CLK_P) then
        if(RECEIVER_RESET = '1') then
            CODE_LOCK_FLAG <= '0';    -- clear
            CODE_LOCK_1S <= '0';    -- clear
        elsif(TICK_1S = '1') then
            CODE_LOCK_FLAG <= CODE_LOCK_OUT;    -- code lock at start of 1s window
            CODE_LOCK_1S <= CODE_LOCK_FLAG;     -- code lock with hysteresis at end of 1s window
        elsif(CODE_LOCK_OUT = '0') then
            -- lost lock within a 1s window
            CODE_LOCK_FLAG <= '0';    -- clear
        end if;            
    end if;
end process;


--//-- VITERBI FEC DECODERS -------------------------------------------
-- Rate R = R1/R2
FEC_DEC_R1 <= 1;
FEC_DEC_R2 <= 2;
FEC_DEC_STANDARD <= 1; -- CCSDS 
FEC_DEC_G(8 downto 0) <= O"171";
FEC_DEC_G(17 downto 9) <= O"133";
FEC_DEC_DIFF_ENC_ON <= '0';

-- FEC DECODER#1  I-CHANNEL -------------------
-- Adjust FEC threshold BER as a function of the measured SNR (measured in the demod).
-- This provides a better tradeoff between missed out of lock at high SNR and false out of lock at low SNR.
FEC_DECODER_001: process(CLK_P) 
begin
	if rising_edge(CLK_P) then
		if(unsigned(SNR1_LOCKED_OUT) < 40) then	-- heuristic threshold for low SNR  (10 dB)
			FEC_DEC1_HIGH_SNR <= '0';
		else
			FEC_DEC1_HIGH_SNR <= '1';
		end if;
	end if;
end process;


-- pack 8 soft-quantized samples into a 32-bit word
FEC_DECODER_002: process(CLK_P) 
begin
	if rising_edge(CLK_P) then
		if(RECEIVER_RESET ='1') or (FEC_DEC_ENABLE = '0') then
			FEC_DEC1_DATAIN <= (others => '0');
			FEC_DEC1_DATAIN_CNTR <= (others => '0');
			FEC_DEC1_DATAIN_VALID <= '0';
		elsif(SAMPLE_I_CLK_OUT = '1') then
			-- shift in next 4-bit soft-quantized sample
			FEC_DEC1_DATAIN(3 downto 0) <= DATA_I_OUT(3 downto 0);
			FEC_DEC1_DATAIN(31 downto 4) <= FEC_DEC1_DATAIN(27 downto 0);
			FEC_DEC1_DATAIN_CNTR <= FEC_DEC1_DATAIN_CNTR + 1;
			if(FEC_DEC1_DATAIN_CNTR = 7) then
				-- modulo-8 counter
				-- vector is packed. Pass to Viterbi decoder.
				FEC_DEC1_DATAIN_VALID <= '1';
			else
				FEC_DEC1_DATAIN_VALID <= '0';
			end if;
		else
			FEC_DEC1_DATAIN_VALID <= '0';
		end if;
	end if;
end process;

FEC_DECODER_003: VITERBI_DECODER 
	GENERIC MAP(
		K_MAX => 7,
		N_PARITY_BITS_MAX => 2,
		NDEC => 1,
		HARD_SOFTN_DECISION => '0',
		TB_DEPTH => 88,	-- TEST TEST TEST
		SIMULATION => '0'
	)
	PORT MAP (
	 CLK => CLK_P,
	 SYNC_RESET => RECEIVER_RESET,  -- reset is MANDATORY to initialize configuration within.
	 DATAIN => FEC_DEC1_DATAIN,
	 DATAIN_VALID => FEC_DEC1_DATAIN_VALID,
	 SKIP1BIT_PULSE => '0',
	 SYNC_CONTROL => '0',
	 G => FEC_DEC_G, 	-- encoder generator polynomials
	 N_PARITY_BITS => 2, -- fixed. 2 generator polynomials G0/G1
	 K => 7,	-- fixed constraint length K=7
	 R1 => FEC_DEC_R1,
	 R2 => FEC_DEC_R2,
	 STANDARD => FEC_DEC_STANDARD,	
	 DIFF_ENC_ON => FEC_DEC_DIFF_ENC_ON,
	 HIGH_SNR => FEC_DEC1_HIGH_SNR,
	 FEC_G1_INVERSION => FEC_G1_INVERSION,
	 DATAIN_READY => open,	-- no input flow control
	 DATAOUT1b => FEC_DEC1_BIT,
	 DATAOUT1b_VALID => FEC_DEC1_BIT_VALID,
	 DATAOUT8b => FEC_DEC8b1,	-- unused
	 DATAOUT8b_VALID => FEC_DEC8b1_VALID, -- unused
	 BER => FEC_DEC1_BER_COUNT,
	 BER_VALID => FEC_DEC1_BER_VALID,
	 BIT_ERROR => FEC_DEC1_BIT_ERROR,
	 IN_SYNC => FEC_DEC1_IN_SYNC,
	 OUT_OF_SYNC => FEC_DEC1_OUT_OF_SYNC,
	 LOCK_STATUS => open
  );

-- generate a FEC lock confidence level (more reliable at threshold SNR)
-- A kind of flywheel. We will not declare 'FEC out of lock' for just one bad report.
-- Very sensitive trigger: just one report is sufficient to declare FEC decoder lock, at least temporarily.
FEC_DEC1_LOCK_CONFIDENCE_GEN_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(RECEIVER_RESET = '1') then
			FEC_DEC1_LOCK_CONFIDENCE <= (others => '0');
		elsif(FEC_DEC1_IN_SYNC = '1') and ((not FEC_DEC1_LOCK_CONFIDENCE) /= 0) then
			FEC_DEC1_LOCK_CONFIDENCE <= FEC_DEC1_LOCK_CONFIDENCE + 1;
		elsif(FEC_DEC1_OUT_OF_SYNC = '1') and (FEC_DEC1_LOCK_CONFIDENCE /= 0) then
			FEC_DEC1_LOCK_CONFIDENCE <= FEC_DEC1_LOCK_CONFIDENCE - 1;
		end if;
	end if;
end process;
FEC_DEC1_LOCK_STATUS <= '0' when (FEC_DEC1_LOCK_CONFIDENCE = 0) else '1';	
	-- Very sensitive trigger: just one report is sufficient to declare FEC decoder lock, at least temporarily.
FEC_DEC1_CONFIRMED_LOCK <= '1' when ((not FEC_DEC1_LOCK_CONFIDENCE) = 0) else '0';
	-- highest degree of confidence that Viterbi decoder is in sync,


-- monitoring
MONITORING_003: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(REG28(7 downto 5) = "000") and (SDDS_TP(1) = '1') then
			SREG36(2) <= '0';	-- force to zero when no input (SDDS rx underflow)
		else
			SREG36(2) <= FEC_DEC1_CONFIRMED_LOCK;
		end if;
		if(LATCH_MONITORING_PULSE = '1') then
			SREG37 <= FEC_DEC1_BER_COUNT(7 downto 0);
			SREG38 <= FEC_DEC1_BER_COUNT(15 downto 8);
			SREG59 <= BER_ERROR_COUNT(7 downto 0);
			SREG60 <= BER_ERROR_COUNT(15 downto 8);
		end if;
		SREG36(5) <= BER_SYNC;    -- BERT synchronized?
	end if;
end process;

-- FEC DECODER#2  Q-CHANNEL -------------------
-- Adjust FEC threshold BER as a function of the measured SNR (measured in the demod).
-- This provides a better tradeoff between missed out of lock at high SNR and false out of lock at low SNR.
FEC_DECODER_011: process(CLK_P) 
begin
	if rising_edge(CLK_P) then
		if(unsigned(SNR2_LOCKED_OUT) < 40) then	-- heuristic threshold for low SNR  (10 dB)
			FEC_DEC2_HIGH_SNR <= '0';
		else
			FEC_DEC2_HIGH_SNR <= '1';
		end if;
	end if;
end process;

-- pack 8 soft-quantized samples into a 32-bit word
FEC_DECODER_012: process(CLK_P) 
begin
	if rising_edge(CLK_P) then
		if(RECEIVER_RESET ='1') or (FEC_DEC_ENABLE = '0') then
			FEC_DEC2_DATAIN <= (others => '0');
			FEC_DEC2_DATAIN_CNTR <= (others => '0');
			FEC_DEC2_DATAIN_VALID <= '0';
		elsif(SAMPLE_Q_CLK_OUT = '1') then
			-- shift in next 4-bit soft-quantized sample
			FEC_DEC2_DATAIN(3 downto 0) <= DATA_Q_OUT(3 downto 0);
			FEC_DEC2_DATAIN(31 downto 4) <= FEC_DEC2_DATAIN(27 downto 0);
			FEC_DEC2_DATAIN_CNTR <= FEC_DEC2_DATAIN_CNTR + 1;
			if(FEC_DEC2_DATAIN_CNTR = 7) then
				-- modulo-8 counter
				-- vector is packed. Pass to Viterbi decoder.
				FEC_DEC2_DATAIN_VALID <= '1';
			else
				FEC_DEC2_DATAIN_VALID <= '0';
			end if;
		else
			FEC_DEC2_DATAIN_VALID <= '0';
		end if;
	end if;
end process;

-- Synchronize both Viterbi decoders (dec1 is master, dec2 is slave) in the case of SQPN alternating i/q mode
FEC_DEC2_SKIP1BIT_PULSE <= FEC_DEC1_OUT_OF_SYNC when (REG26(1) = '1') and (REG26(7) = '1') else '0';
FEC_DEC2_SYNC_CONTROL <= '1' when (REG26(1) = '1') and (REG26(7) = '1') else '0';


FEC_DECODER_013: VITERBI_DECODER 
	GENERIC MAP(
		K_MAX => 7,
		N_PARITY_BITS_MAX => 2,
		NDEC => 1,
		HARD_SOFTN_DECISION => '0',
		TB_DEPTH => 88,	
		SIMULATION => '0'
	)
	PORT MAP (
	 CLK => CLK_P,
	 SYNC_RESET => RECEIVER_RESET,  -- reset is MANDATORY to initialize configuration within.
	 DATAIN => FEC_DEC2_DATAIN,
	 DATAIN_VALID => FEC_DEC2_DATAIN_VALID,
	 SKIP1BIT_PULSE => FEC_DEC2_SKIP1BIT_PULSE,
	 SYNC_CONTROL => FEC_DEC2_SYNC_CONTROL,
	 G => FEC_DEC_G, 	-- encoder generator polynomials
	 N_PARITY_BITS => 2, -- fixed. 2 generator polynomials G0/G1
	 K => 7,	-- fixed constraint length K=7
	 R1 => FEC_DEC_R1,
	 R2 => FEC_DEC_R2,
	 STANDARD => FEC_DEC_STANDARD,	
	 DIFF_ENC_ON => FEC_DEC_DIFF_ENC_ON,
	 HIGH_SNR => FEC_DEC2_HIGH_SNR,
	 FEC_G1_INVERSION => FEC_G1_INVERSION,
	 DATAIN_READY => open,	-- no input flow control
	 DATAOUT1b => FEC_DEC2_BIT,
	 DATAOUT1b_VALID => FEC_DEC2_BIT_VALID,
	 DATAOUT8b => open,
	 DATAOUT8b_VALID => open,
	 BER => FEC_DEC2_BER_COUNT,
	 BER_VALID => FEC_DEC2_BER_VALID,
	 BIT_ERROR => FEC_DEC2_BIT_ERROR,
	 IN_SYNC => FEC_DEC2_IN_SYNC,
	 OUT_OF_SYNC => FEC_DEC2_OUT_OF_SYNC,
	 LOCK_STATUS => open
  );

-- generate a FEC lock confidence level (more reliable at threshold SNR)
-- A kind of flywheel. We will not declare 'FEC out of lock' for just one bad report.
-- Very sensitive trigger: just one report is sufficient to declare FEC decoder lock, at least temporarily.
FEC_DEC2_LOCK_CONFIDENCE_GEN_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(RECEIVER_RESET = '1') then
			FEC_DEC2_LOCK_CONFIDENCE <= (others => '0');
		elsif(FEC_DEC2_IN_SYNC = '1') and ((not FEC_DEC2_LOCK_CONFIDENCE) /= 0) then
			FEC_DEC2_LOCK_CONFIDENCE <= FEC_DEC2_LOCK_CONFIDENCE + 1;
		elsif(FEC_DEC2_OUT_OF_SYNC = '1') and (FEC_DEC2_LOCK_CONFIDENCE /= 0) then
			FEC_DEC2_LOCK_CONFIDENCE <= FEC_DEC2_LOCK_CONFIDENCE - 1;
		end if;
	end if;
end process;
FEC_DEC2_LOCK_STATUS <= '0' when (FEC_DEC2_LOCK_CONFIDENCE = 0) else '1';	
	-- Very sensitive trigger: just one report is sufficient to declare FEC decoder lock, at least temporarily.
FEC_DEC2_CONFIRMED_LOCK <= '1' when ((not FEC_DEC2_LOCK_CONFIDENCE) = 0) else '0';
	-- highest degree of confidence that Viterbi decoder is in sync,

-- monitoring
MONITORING_004: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(REG28(7 downto 5) = "000") and (SDDS_TP(1) = '1') then
			SREG36(3) <= '0';	-- force to zero when no input (SDDS rx underflow)
		else
			SREG36(3) <= FEC_DEC2_CONFIRMED_LOCK;
		end if;
		if(LATCH_MONITORING_PULSE = '1') then
            SREG39 <= FEC_DEC2_BER_COUNT(7 downto 0);
            SREG40 <= FEC_DEC2_BER_COUNT(15 downto 8);
        end if;
	end if;
end process;

--//-- DATA FORMAT CONVERTER (RX) --------------------------------------
-- converts NRZ-L/M/S to NRZ-L
-- Two converters, for I and Q channels respectively

	NRZ1_RX_CONTROL_001: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			case REG26(5 downto 3) is
				when "000" => NRZ1_RX_CONTROL <= "000";	-- NRZ-L unchanged
				when "001" => NRZ1_RX_CONTROL <= "011";	-- NRZ_M to NRZ-L
				when others => NRZ1_RX_CONTROL <= "100";	-- NRZ_S to NRZ-L
			end case;
		end if;
	end process;

	-- bypass FEC decoding?
	NRZ1_RX_INPUT_SEL: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			if(FEC_DEC_ENABLE = '0') then
				-- FEC decoders are bypassed
				NRZ1_RX_DATA1_IN <= DATA_I_OUT(3);
				NRZ1_RX_DATA1_VALID_IN <= SAMPLE_I_CLK_OUT;
				NRZ1_RX_DATA2_IN <= DATA_Q_OUT(3);
				NRZ1_RX_DATA2_VALID_IN <= SAMPLE_Q_CLK_OUT;
			else
				NRZ1_RX_DATA1_IN <= FEC_DEC1_BIT;
				NRZ1_RX_DATA1_VALID_IN <= FEC_DEC1_BIT_VALID;
				NRZ1_RX_DATA2_IN <= FEC_DEC2_BIT;
				NRZ1_RX_DATA2_VALID_IN <= FEC_DEC2_BIT_VALID;
			end if;
		end if;
	end process;

	NRZ1_RX_001: NRZ1 PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => SYNC_RESET_CLK_P,
		DATA_IN => NRZ1_RX_DATA1_IN,
		DATA_VALID_IN => NRZ1_RX_DATA1_VALID_IN,
		CONTROL => NRZ1_RX_CONTROL,
		DATA_OUT => NRZ1_RX_DATA1_OUT,
		DATA_VALID_OUT => NRZ1_RX_DATA1_VALID_OUT
	);

	NRZ1_RX_002: NRZ1 PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => SYNC_RESET_CLK_P,
		DATA_IN => NRZ1_RX_DATA2_IN,
		DATA_VALID_IN => NRZ1_RX_DATA2_VALID_IN,
		CONTROL => NRZ1_RX_CONTROL,
		DATA_OUT => NRZ1_RX_DATA2_OUT,
		DATA_VALID_OUT => NRZ1_RX_DATA2_VALID_OUT
	);


--//-- SERIAL TO 8-BIT PARALLEL  ---------------------------------------------------------
	S2P_001: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			if(SYNC_RESET_CLK_P = '1') then
				S2P1_CNTR <= "000";	-- modulo-8 bit counter
				S2P1_DATA_VALID_IN <= '0';
				S2P1_DATA_IN <= x"00";
			elsif(NRZ1_RX_DATA1_VALID_OUT = '1') then
				if(REG26(7) = '1') then
					-- special case. Alternating I/Q modes, shift-in both I and Q bits, I first
					S2P1_CNTR(2 downto 1) <= unsigned(S2P1_CNTR(2 downto 1)) + 1;
					S2P1_CNTR(0) <= '0';	-- force even counter alignment
					S2P1_DATA_IN <= S2P1_DATA_IN(5 downto 0) & NRZ1_RX_DATA1_OUT & NRZ1_RX_DATA2_OUT;	-- shift left (MSb first)
					if(S2P1_CNTR = 6) then
						S2P1_DATA_VALID_IN <= '1';
					else
						S2P1_DATA_VALID_IN <= '0';
					end if;
				else
					S2P1_CNTR <= S2P1_CNTR + 1;
					S2P1_DATA_IN <= S2P1_DATA_IN(6 downto 0) & NRZ1_RX_DATA1_OUT;	-- shift left (MSb first)
					if(S2P1_CNTR = 7) then
						S2P1_DATA_VALID_IN <= '1';
					else
						S2P1_DATA_VALID_IN <= '0';
					end if;
				end if;
			else
				S2P1_DATA_VALID_IN <= '0';
			end if;
		end if;
	end process;
	
	S2P_002: process(CLK_P)
	begin
		if rising_edge(CLK_P) then
			if(SYNC_RESET_CLK_P = '1') then
				S2P2_CNTR <= "000";	-- modulo-8 bit counter
				S2P2_DATA_VALID_IN <= '0';
				S2P2_DATA_IN <= x"00";
			elsif(NRZ1_RX_DATA2_VALID_OUT = '1') then
				S2P2_CNTR <= S2P2_CNTR + 1;
				S2P2_DATA_IN <= S2P2_DATA_IN(6 downto 0) & NRZ1_RX_DATA2_OUT;	-- shift left (MSb first)
				if(S2P2_CNTR = 7) then
					S2P2_DATA_VALID_IN <= '1';
				else
					S2P2_DATA_VALID_IN <= '0';
				end if;
			else
				S2P2_DATA_VALID_IN <= '0';
			end if;
		end if;
	end process;
	
	
--//-- BER MEASUREMENT  ---------------------------------------------------------
-- Measure BER when a PRSB-11 test sequence is transmitted
-- BER measurement 8-bit parallel serial input selection
BER2_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(REG27(3) = '0') and (S2P1_DATA_VALID_IN = '1') then
			-- I-channel BER measurement
			BER2_DATA_IN <= S2P1_DATA_IN;
			BER2_SAMPLE_CLK_IN <= '1';
		elsif(REG27(3) = '1') and (S2P2_DATA_VALID_IN = '1') then
			-- Q-channel BER measurement
			BER2_DATA_IN <= S2P2_DATA_IN;
			BER2_SAMPLE_CLK_IN <= '1';
		else
			BER2_SAMPLE_CLK_IN <= '0';
		end if;
	end if;
end process;

BER_CONTROL(2 downto 0) <= "001"; -- BER measured over 80,000-bit window.
BER_CONTROL(7 downto 3) <= (others => '0'); -- unused

BER2_002: BER2 PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => SYNC_RESET_CLK_P,
	DATA_IN => BER2_DATA_IN,
	SAMPLE_CLK_IN => BER2_SAMPLE_CLK_IN,
	CONTROL => BER_CONTROL,
	MF_DETECT => BER_MF_DETECT,	-- useful test point
	MF_DETECT_CONFIRMED => BER_MF_DETECT_CONFIRMED,
	SYNC_LOCK => BER_SYNC,	-- useful test point
	BYTE_ERROR => BER_BYTE_ERROR,		-- useful test point
	DATA_REPLICA => open,
	SAMPLE_CLK_OUT => open,
	BER => BER_ERROR_COUNT,
	BER_SAMPLE_CLK => open,
	TP => BER_TEST_POINT
);

--// UDP OUTPUTS ------------------------------	

-- I-channel data
TX_PREAMBLE1 <= std_logic_vector(TX_FRAME_CNTR1) & x"00000000" & SDDS_RX_TIMETAG1;	-- preamble

STREAM_2_PACKETS_001: STREAM_2_PACKETS2 
generic map(
	NBUFS => 2,  -- number of 16Kb dual-port RAM buffers instantiated within.
	TIMEOUT => 125000, 	-- latency should always be less than 0.5s, even when data rate is low
	MAX_PACKET_SIZE => "00" & x"400",	-- in bytes. 1024 bytes
	SIMULATION => SIMULATION
	) 
PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => RECEIVER_RESET,
	TICK_4us => TICK_4US,
	DATA_IN => S2P1_DATA_IN,
	DATA_VALID_IN => S2P1_DATA_VALID_IN,
	CTS_OUT => open,
	PACKET_TX_PULSE => PACKET_TX_PULSE1,
	PREAMBLE_IN => TX_PREAMBLE1,
	DATA_OUT => IP2_UDP_TX_DATA1,
	DATA_VALID_OUT => IP2_UDP_TX_DATA1_VALID,
	SOF_OUT => IP2_UDP_TX_SOF1,
	EOF_OUT => IP2_UDP_TX_EOF1,
	RTS_OUT => IP2_UDP_TX_RTS1,
	CTS_IN => IP2_UDP_TX_CTS1,
	ACK_IN => IP2_UDP_TX_ACK,
	NAK_IN => IP2_UDP_TX_NAK,
	TP => open
);

-- Q-channel data 
TX_PREAMBLE2 <= std_logic_vector(TX_FRAME_CNTR2) & x"00000000" & SDDS_RX_TIMETAG2;	-- preamble
STREAM_2_PACKETS_002: STREAM_2_PACKETS2 
generic map(
	NBUFS => 2,  -- number of 16Kb dual-port RAM buffers instantiated within.
	TIMEOUT => 125000, 	-- latency should always be less than 0.5s, even when data rate is low
	MAX_PACKET_SIZE => "00" & x"400",	-- in bytes. 1024 bytes
	SIMULATION => SIMULATION
	) 
PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => RECEIVER_RESET,
	TICK_4us => TICK_4US,
	DATA_IN => S2P2_DATA_IN,
    DATA_VALID_IN => S2P2_DATA_VALID_IN,
	CTS_OUT => open,
	PACKET_TX_PULSE => PACKET_TX_PULSE2,
	PREAMBLE_IN => TX_PREAMBLE2,
	DATA_OUT => IP2_UDP_TX_DATA2,
	DATA_VALID_OUT => IP2_UDP_TX_DATA2_VALID,
	SOF_OUT => IP2_UDP_TX_SOF2,
	EOF_OUT => IP2_UDP_TX_EOF2,
	RTS_OUT => IP2_UDP_TX_RTS2,
	CTS_IN => IP2_UDP_TX_CTS2,
	ACK_IN => IP2_UDP_TX_ACK,
	NAK_IN => IP2_UDP_TX_NAK,
	TP => open
);

-- latch next tx frame counter and timestamp (to send as preamble to the data packet)
UDP_TX2_003: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		-- increment the tx frame counter
		if(RECEIVER_RESET = '1') then
			TX_FRAME_CNTR1 <= (others => '0');
			FIRST_BYTE1_FLAG <= '0';
		elsif(FIRST_BYTE1_FLAG = '0') and (S2P1_DATA_VALID_IN = '1') then
		  -- first byte in first output frame
			FIRST_BYTE1_FLAG <= '1';
			SDDS_RX_TIMETAG1 <= SDDS_RX_TIMETAG;
		elsif(IP2_UDP_TX_EOF1 = '1') then
		    -- shortly before the first byte in the next output frame
			TX_FRAME_CNTR1 <= TX_FRAME_CNTR1 + 1;
			SDDS_RX_TIMETAG1 <= SDDS_RX_TIMETAG;
		end if;
		
		if(RECEIVER_RESET = '1') then
            TX_FRAME_CNTR2 <= (others => '0');
            FIRST_BYTE2_FLAG <= '0';
        elsif(FIRST_BYTE2_FLAG = '0') and (S2P2_DATA_VALID_IN = '1') then
          -- first byte in first output frame
            FIRST_BYTE2_FLAG <= '1';
            SDDS_RX_TIMETAG2 <= SDDS_RX_TIMETAG;
        elsif(IP2_UDP_TX_EOF2 = '1') then
            -- shortly before the first byte in the next output frame
            TX_FRAME_CNTR2 <= TX_FRAME_CNTR2 + 1;
            SDDS_RX_TIMETAG2 <= SDDS_RX_TIMETAG;
        end if;
	end if;
end process;

-- UDP tx multiplexer
IP2_UDP_TX_MUX_001: process(CLK_P)
begin
	if rising_edge(CLK_P) then
        if(CONFIG_CHANGE_PULSE = '1') then
            IP2_UDP_TX_DEST_IP_ADDR(31 downto 0) <= REG45 & REG46 & REG47 & REG48; 
            IP2_UDP_TX_DEST_PORT_NO1 <= REG50 & REG49;
            IP2_UDP_TX_DEST_PORT_NO2 <= REG50 & std_logic_vector(unsigned(REG49) + 1);
        end if;
	
		if(IP2_UDP_TX_MUX_STATE = 0) and (IP2_UDP_TX_CTS = '1') then
			-- from idle state to ...
			if (IP2_UDP_TX_RTS1 = '1') then
				IP2_UDP_TX_MUX_STATE <= 1;
				-- latch in destination port
			    IP2_UDP_TX_DEST_PORT_NO <= IP2_UDP_TX_DEST_PORT_NO1;
			elsif (IP2_UDP_TX_RTS2 = '1') then
				IP2_UDP_TX_MUX_STATE <= 2;
				-- latch in destination port
                IP2_UDP_TX_DEST_PORT_NO <= IP2_UDP_TX_DEST_PORT_NO2;
			end if;
		-- Done transmitting. go from ... to idle
		elsif(IP2_UDP_TX_MUX_STATE = 1) and (IP2_UDP_TX_EOF1 = '1') then
			IP2_UDP_TX_MUX_STATE <= 0;	-- idle
		elsif(IP2_UDP_TX_MUX_STATE = 2) and (IP2_UDP_TX_EOF2 = '1') then
			IP2_UDP_TX_MUX_STATE <= 0;	-- idle
		end if;
	end if;
end process;
		
TX_MUX_002: process(IP2_UDP_TX_MUX_STATE, 
							IP2_UDP_TX_DATA1_VALID, IP2_UDP_TX_SOF1, IP2_UDP_TX_EOF1, 
							IP2_UDP_TX_DATA2_VALID, IP2_UDP_TX_SOF2, IP2_UDP_TX_EOF2)
begin
	case(IP2_UDP_TX_MUX_STATE) is
		when (1) =>
			IP2_UDP_TX_DATA_VALID <= IP2_UDP_TX_DATA1_VALID;
			IP2_UDP_TX_SOF <= IP2_UDP_TX_SOF1;
			IP2_UDP_TX_EOF <= IP2_UDP_TX_EOF1;
			IP2_UDP_TX_CTS1 <= IP2_UDP_TX_CTS;
			IP2_UDP_TX_CTS2 <= '0';
		when (2) =>
			IP2_UDP_TX_DATA_VALID <= IP2_UDP_TX_DATA2_VALID;
			IP2_UDP_TX_SOF <= IP2_UDP_TX_SOF2;
			IP2_UDP_TX_EOF <= IP2_UDP_TX_EOF2;
			IP2_UDP_TX_CTS1 <= '0';
			IP2_UDP_TX_CTS2 <= IP2_UDP_TX_CTS;
		when others =>
            IP2_UDP_TX_DATA_VALID <= '0';
            IP2_UDP_TX_SOF <= '0';
            IP2_UDP_TX_EOF <= '0';
            IP2_UDP_TX_CTS1 <= '0';
            IP2_UDP_TX_CTS2 <= '0';
    end case;
end process;

-- direct I/Q demodulated data streams to distinct IP addresses/ports
TX_MUX_003: process(IP2_UDP_TX_MUX_STATE, 
							IP2_UDP_TX_DATA1, IP2_UDP_TX_DATA2)
begin
	case(IP2_UDP_TX_MUX_STATE) is
		when (1) =>
			IP2_UDP_TX_DATA <= IP2_UDP_TX_DATA1;
		when others =>
			IP2_UDP_TX_DATA <= IP2_UDP_TX_DATA2;
	end case;
end process;
		


-- monitoring
MONITORING_005: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(LATCH_MONITORING_PULSE = '1') then
			-- latch in multi-byte status registers upon reading status register SREG7
			SREG10 <= SDDS_RX_SAMPLING_RATE(7 downto 0);
			SREG11 <= SDDS_RX_SAMPLING_RATE(15 downto 8);
			SREG12 <= SDDS_RX_SAMPLING_RATE(23 downto 16);
			SREG13 <= SDDS_RX_SAMPLING_RATE(31 downto 24); 
			SREG14 <= SDDS_RX_TIMETAG(7 downto 0);
			SREG15 <= SDDS_RX_TIMETAG(15 downto 8);
			SREG16 <= SDDS_RX_TIMETAG(23 downto 16);
			SREG17 <= SDDS_RX_TIMETAG(31 downto 24);
			SREG18 <= SDDS_RX_TIMETAG(39 downto 32);
			SREG19 <= SDDS_RX_TIMETAG(47 downto 40);
			SREG20 <= SDDS_RX_TIMETAG(55 downto 48);
			SREG21 <= SDDS_RX_TIMETAG(63 downto 56);
			SREG22 <= std_logic_vector(SDDS_RX_FRAME_CNTR(7 downto 0));
			SREG23 <= std_logic_vector(SDDS_RX_FRAME_CNTR(15 downto 8));
			SREG24 <= std_logic_vector(SDDS_RX_FRAME_CNTR(23 downto 16));
			SREG25 <= std_logic_vector(SDDS_RX_FRAME_CNTR(31 downto 24));
			SREG26 <= std_logic_vector(SDDS_N_MISSING_FRAMES(7 downto 0));
			SREG27 <= std_logic_vector(SDDS_N_MISSING_FRAMES(15 downto 8));
			SREG28 <= LAN2_N_RX_BAD_CRCS(7 downto 0);
			SREG29 <= LAN2_N_RX_BAD_CRCS(15 downto 8);
			SREG30 <= LAN2_MAC_ADDR(47 downto 40);
			SREG31 <= LAN2_MAC_ADDR(39 downto 32);
			SREG32 <= LAN2_MAC_ADDR(31 downto 24);
			SREG33 <= LAN2_MAC_ADDR(23 downto 16);
			SREG34 <= LAN2_MAC_ADDR(15 downto 8);
			SREG35 <= LAN2_MAC_ADDR(7 downto 0);
			SREG45 <= CARRIER_FREQUENCY_ERROR1(7 downto 0);
			SREG46 <= CARRIER_FREQUENCY_ERROR1(15 downto 8);
			SREG47 <= CARRIER_FREQUENCY_ERROR1(23 downto 16);
			SREG48 <= CARRIER_FREQUENCY_ERROR1(31 downto 24);
			SREG49 <= CARRIER_FREQUENCY_ERROR2(7 downto 0);
			SREG50 <= CARRIER_FREQUENCY_ERROR2(15 downto 8);
			SREG51 <= CARRIER_FREQUENCY_ERROR2(23 downto 16);
			SREG52 <= CARRIER_FREQUENCY_ERROR2(31 downto 24);
			SREG53 <= POWER_S_AVERAGE_OUT(7 downto 0);
			SREG54 <= POWER_S_AVERAGE_OUT(15 downto 8);
			SREG55 <= POWER_N_AVERAGE_OUT(7 downto 0);
			SREG56 <= POWER_N_AVERAGE_OUT(15 downto 8);
			SREG57 <= SNR1_LOCKED_OUT(7 downto 0);
			SREG58 <= SNR1_LOCKED_OUT(15 downto 8);
--			SREG27 <= BER_ERROR_COUNT(7 downto 0);
--			SREG28 <= BER_ERROR_COUNT(15 downto 8);
--			SREG29 <= BER_ERROR_COUNT(23 downto 16);
--			SREG30 <= BER_ERROR_COUNT(31 downto 24);
			SREG67(4 downto 0) <= DEMODULATOR_EN & AWGN_EN & DACs_EN & ADCs_EN & MODULATOR_EN;	-- report FPGA generic configuration options
			SREG68 <= SNR2_LOCKED_OUT(7 downto 0);
			SREG69 <= SNR2_LOCKED_OUT(15 downto 8);
		end if;
	end if;
end process;
-- report status. forced to zero when there is no input data (persistent SDDS rx underflow)
SREG36(1 downto 0) <= 	"00" when (REG28(7 downto 5) = "000") and (SDDS_TP(1) = '1') else 
								CODE_LOCK_1S & CARRIER_LOCK_OUT;

SREG36(4) <= 	'0' when (REG28(7 downto 5) = "000") and (SDDS_TP(1) = '1') else   
					SIGNAL_PRESENT_OUT;

--// TEST POINTS  -----------------------------------------------
-- Warning: test points can make timing much worse!
-- Disable the RIGHT_CONNECTOR test points when the COM-3504 dual ADC dual DAC module is enabled

TP_GEN_001: if(DACs_EN = '0') and (ADCs_EN = '0') generate
	TP_GEN_00X: process(CLK_P)
	begin
		 if rising_edge(CLK_P) then
		    if(LOOPBACK_MODE = '1')  then
		        -- loopback test mode
                RIGHT_CONNECTOR_A(1) <= MOD_SAMPLE_CLK;	-- sampling rate
                RIGHT_CONNECTOR_A(2) <= MOD_DATA2_I(17);    
            else
                -- data from SDDS
                RIGHT_CONNECTOR_A(1) <= SDDS_RX_DATA_VALID_IN;	-- SDDS data from the network (helpful to trigger acquisition time start)
                RIGHT_CONNECTOR_A(2) <= SDDS_TP(1);    -- underflow condition in SDDS elastic buffer
            end if;
 			RIGHT_CONNECTOR_A(13 downto 3) <= DEMOD_TP(11 downto 1);
--			-- test test test
-- 			RIGHT_CONNECTOR_A(3) <= SAMPLE_I_CLK_OUT;
-- 			RIGHT_CONNECTOR_A(4) <= SAMPLE_Q_CLK_OUT;
-- 			RIGHT_CONNECTOR_A(5) <= DATA_I_OUT(3);
-- 			RIGHT_CONNECTOR_A(6) <= DATA_Q_OUT(3);
-- 			RIGHT_CONNECTOR_A(7) <= MOD_TP(8);
-- 			RIGHT_CONNECTOR_A(8) <= MOD_TP(9);
-- 			RIGHT_CONNECTOR_A(9) <= FEC_DEC1_DATAIN_VALID;
-- 			RIGHT_CONNECTOR_A(10) <= FEC_DEC2_DATAIN_VALID;
-- 			RIGHT_CONNECTOR_A(11) <= FEC_DEC1_DATAIN_CNTR(2);
-- 			RIGHT_CONNECTOR_A(12) <= FEC_DEC2_DATAIN_CNTR(2);
-- 			RIGHT_CONNECTOR_A(13) <= '0';
			

 			RIGHT_CONNECTOR_A(14) <= BER_SYNC;
 			RIGHT_CONNECTOR_A(15) <= BER_BYTE_ERROR;
			RIGHT_CONNECTOR_A(16) <= FEC_DEC1_IN_SYNC;
			RIGHT_CONNECTOR_A(17) <= FEC_DEC2_IN_SYNC;
			RIGHT_CONNECTOR_A(19) <= BER_MF_DETECT;
			
-- 			-- SDDS UDP test points
-- 			RIGHT_CONNECTOR_B1(1) <= INPUT_UDP_TCPN;
-- 			RIGHT_CONNECTOR_B1(2) <= LAN1_UDP_RX_DATA_VALID2; 
-- 			RIGHT_CONNECTOR_B1(3) <= LAN1_UDP_RX_SOF2;
-- 			RIGHT_CONNECTOR_B1(4) <= LAN1_UDP_RX_EOF2;
--			RIGHT_CONNECTOR_B2(6) <= SDDS_TP(5); -- wptr msb
--			RIGHT_CONNECTOR_B2(7) <= SDDS_TP(6); -- rptr msb
--			
--			RIGHT_CONNECTOR_B2(8) <= LAN1_UDP_RX_DATA_VALID;
--			RIGHT_CONNECTOR_B2(9) <= LAN1_UDP_RX_EOF;
--			RIGHT_CONNECTOR_B2(11) <= LAN1_N_RX_FRAMES(0);
----			RIGHT_CONNECTOR_B2(12) <= LAN2_N_RX_BAD_CRCS(0);
----			RIGHT_CONNECTOR_B2(13) <= LAN2_N_RX_WRONG_ADDR(0);
----			RIGHT_CONNECTOR_B2(14) <= LAN2_N_RX_LENGTH_ERRORS(0);
----			RIGHT_CONNECTOR_B2(16) <= LAN2_N_RX_FRAMES_TOO_SHORT(0);
----			RIGHT_CONNECTOR_B2(17) <= LAN2_N_RX_FRAMES_TOO_LONG(0);
--
--			RIGHT_CONNECTOR_B2(12) <= LAN1_MAC_RX_DATA_VALID;
--			RIGHT_CONNECTOR_B2(13) <= LAN1_MAC_RX_EOF;
--			RIGHT_CONNECTOR_B2(14) <= LAN1_MAC_TX_DATA_VALID;
--			RIGHT_CONNECTOR_B2(16) <= LAN1_TP(1);
--			RIGHT_CONNECTOR_B2(17) <= LAN1_TP(2);
		
			-- saturation
-- 			RIGHT_CONNECTOR_B1(1) <= DEMOD_TP(12);
-- 			RIGHT_CONNECTOR_B1(2) <= DEMOD_TP(13);
-- 			RIGHT_CONNECTOR_B1(3) <= DEMOD_TP(14);
-- 			RIGHT_CONNECTOR_B1(4) <= DEMOD_TP(15);
--			RIGHT_CONNECTOR_B2(6) <= DEMOD_TP(16);
--			RIGHT_CONNECTOR_B2(7) <= DEMOD_TP(17);
--			RIGHT_CONNECTOR_B2(8) <= DEMOD_TP(18);
--			RIGHT_CONNECTOR_B2(9) <= DEMOD_TP(19);
--			RIGHT_CONNECTOR_B2(11) <= DEMOD_TP(20);
		 end if;
	end process;
end generate;
	
--// COMSCOPE2 -----------------------------------------------------
COMSCOPE_GEN: if (SIMULATION = '0') generate
	--  Comment in/out as needed. unused during simulation
	-- 
	-- Define Comscope traces here 
	-- Trace 1
	S1_1 <= RX_DATA2_I(13 downto 6);		-- input samples
	S1_1_CLK <= RX_SAMPLE2_CLK;
	--S1_2 reserved	
	--S1_3 reserved 
	--S1_4 reserved 

	-- Trace 2
	S2_1 <= RX_DATA2_Q(13 downto 6);		-- 8-bit signal
	S2_1_CLK <= RX_SAMPLE2_CLK;
	
	--S2_2 reserved	
	--S2_3 reserved 
	S2_4 <=  POWER_S_AVERAGE_OUT(14 downto 7);
	S2_4_CLK <= '1';

	-- Trace 3
	--S3_1  reserved 
	--S3_2  reserved 
	--S3_3  reserved  
	S3_4 <=  POWER_N_AVERAGE_OUT(11 downto 4);
	S3_4_CLK <= '1';

	-- Trigger (1-bit format)


	COMSCOPE2_001: COMSCOPE2 
	generic map(
		TRACE1_ENABLED => '1',    -- enable as many simultaneous traces as needed
		TRACE2_ENABLED => '1',
		TRACE3_ENABLED => '1',
		TRACE4_ENABLED => '0',
		DATA_WIDTH1A => 8,
		ADDR_WIDTH1A => 9,
		ADDR_WIDTH1B => 9,
		DATA_WIDTH2A => 8,
		ADDR_WIDTH2A => 9,
		ADDR_WIDTH2B => 9,
		DATA_WIDTH3A => 8,
		ADDR_WIDTH3A => 9,
		ADDR_WIDTH3B => 9,
		DATA_WIDTH4A => 8,
		ADDR_WIDTH4A => 9,
		ADDR_WIDTH4B => 9
	)
	PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => SYNC_RESET_CLK_P,
		REG238 => REG238,
		REG239 => x"00", --REG239,  acquire mode: sample
		REG240 => REG240,
		REG241 => REG241,
		REG242 => REG242,
		REG243 => REG243,
		REG244 => REG244,
		REG245 => REG245,
		REG246 => REG246,
		REG247 => REG247,
		REG248 => REG248,
		REG249 => REG249,
		S1_1 => S1_1,
		S1_1_VALID => S1_1_CLK,
		S1_2 => S1_2,
		S1_2_VALID => S1_2_CLK,
		S1_3 => S1_3,
		S1_3_VALID => S1_3_CLK,
		S1_4 => S1_4,
		S1_4_VALID => S1_4_CLK,
		S2_1 => S2_1,
		S2_1_VALID => S2_1_CLK,
		S2_2 => S2_2,
		S2_2_VALID => S2_2_CLK,
		S2_3 => S2_3,
		S2_3_VALID => S2_3_CLK,
		S2_4 => S2_4,
		S2_4_VALID => S2_4_CLK,
		S3_1 => S3_1,
		S3_1_VALID => S3_1_CLK,
		S3_2 => S3_2,
		S3_2_VALID => S3_2_CLK,
		S3_3 => S3_3,
		S3_3_VALID => S3_3_CLK,
		S3_4 => S3_4,
		S3_4_VALID => S3_4_CLK,
		S4_1 => (others => '0'),
		S4_1_VALID => '0',
		S4_2 => (others => '0'),
		S4_2_VALID => '0',
		S4_3 => (others => '0'),
		S4_3_VALID => '0',
		S4_4 => (others => '0'),
		S4_4_VALID => '0',
		T16b_1 => (others => '0'),
		T16b_1_VALID => '0',
		T16b_2 => (others => '0'),
		T16b_2_VALID => '0',
		T16b_3 => (others => '0'),
		T16b_3_VALID => '0',
		T16b_4 => (others => '0'),
		T16b_4_VALID => '0',
		SREG250 => REG250,
		SREG251 => REG251,
		TRIGGER_REARM_TOGGLE => TRIGGER_REARM_TOGGLE,
		FORCE_TRIGGER_TOGGLE => FORCE_TRIGGER_TOGGLE,
		SREG250_READ_TOGGLE => SREG250_READ_TOGGLE,
		START_CAPTURE_TOGGLE => START_CAPTURE_TOGGLE,
		TP => open
	);
end generate;


--// ARM CO-PROCESSOR INTERFACE ---------------------------------------------------
-- Primarily used for monitoring and control.
-- 8-bit shared address/data bus. clock synchronous.
-- PART OF THE FRAMEWORK. DO NOT CHANGE unless you want to add more control registers 
--(see UC_WRITE_001) or status registers (see UC_READ_001).
-- 
-- Address latch
UC_ADDR_001: process(UC_CSIB_IN, UC_WEBG, UC_ALE_IN, UC_AD)
begin
	if rising_edge(UC_WEBG) then
		if (UC_CSIB_IN = '0') and (UC_ALE_IN = '1') then
			UC_ADDRESS <= unsigned(UC_AD);
	  	end if;
  	end if;
end process;

-- Read status registers 
-- User can define additional control registers using the same pattern. 
UC_READ_001: process(UC_ADDRESS, REG255, RX_USB_LAN, REG251, REG250, SREG7, SREG8, SREG9, 
	SREG10, SREG11, SREG12, SREG13, SREG14, SREG15, SREG16, SREG17, SREG18, SREG19,
	SREG20, SREG21, SREG22, SREG23, SREG24, SREG25, SREG26, SREG27, SREG28, SREG29,
	SREG30, SREG31, SREG32, SREG33, SREG34, SREG35, SREG36, SREG37, SREG38, SREG39,
	SREG40, SREG41, SREG42, SREG43, SREG44, SREG45, SREG46, SREG47, SREG48, SREG49,
	SREG50, SREG51, SREG52, SREG53, SREG54, SREG55, SREG56, SREG57, SREG58, SREG59,
	SREG60, SREG61, SREG62, SREG63, SREG64, SREG65, SREG66, SREG67, SREG68, SREG69
	)
begin
	case(UC_ADDRESS) is
		-- ComBlock-reserved addresses ----
		when "11111111" => UC_AD_LOCAL <= REG255;		-- reg 255. Async serial from 3 connectors
		when "11111110" => UC_AD_LOCAL <= RX_USB_LAN;-- reg 254 = 8-bit data from USB or LAN M&C channel
		when "11111101" => UC_AD_LOCAL <= REVISION;	-- reg 253 = fpga revision
		when "11111100" => UC_AD_LOCAL <= OPTION;		-- reg 252 = fpga option
		when "11111011" => UC_AD_LOCAL <= REG251;		-- reg 251 =comscope  status
		when "11111010" => UC_AD_LOCAL <= REG250;		-- reg 250 = comscope data byte
		
		-- User-defined status registers -------
		-- SREG0-6 reserved for use by the ARM microcontroller
		when "00000111" => UC_AD_LOCAL <= SREG7;
		when "00001000" => UC_AD_LOCAL <= SREG8;
		when "00001001" => UC_AD_LOCAL <= SREG9;
		when "00001010" => UC_AD_LOCAL <= SREG10;
		when "00001011" => UC_AD_LOCAL <= SREG11;
		when "00001100" => UC_AD_LOCAL <= SREG12;
		when "00001101" => UC_AD_LOCAL <= SREG13;
		when "00001110" => UC_AD_LOCAL <= SREG14;
		when "00001111" => UC_AD_LOCAL <= SREG15;
		when "00010000" => UC_AD_LOCAL <= SREG16;
		when "00010001" => UC_AD_LOCAL <= SREG17;
		when "00010010" => UC_AD_LOCAL <= SREG18;
		when "00010011" => UC_AD_LOCAL <= SREG19;
		when "00010100" => UC_AD_LOCAL <= SREG20;
		when "00010101" => UC_AD_LOCAL <= SREG21;
		when "00010110" => UC_AD_LOCAL <= SREG22;
		when "00010111" => UC_AD_LOCAL <= SREG23;
		when "00011000" => UC_AD_LOCAL <= SREG24;
		when "00011001" => UC_AD_LOCAL <= SREG25;
		when "00011010" => UC_AD_LOCAL <= SREG26;
		when "00011011" => UC_AD_LOCAL <= SREG27;
		when "00011100" => UC_AD_LOCAL <= SREG28;
		when "00011101" => UC_AD_LOCAL <= SREG29;
		when "00011110" => UC_AD_LOCAL <= SREG30;
		when "00011111" => UC_AD_LOCAL <= SREG31;
		when "00100000" => UC_AD_LOCAL <= SREG32;
		when "00100001" => UC_AD_LOCAL <= SREG33;
		when "00100010" => UC_AD_LOCAL <= SREG34;
		when "00100011" => UC_AD_LOCAL <= SREG35;
		when "00100100" => UC_AD_LOCAL <= SREG36;
		when "00100101" => UC_AD_LOCAL <= SREG37;
		when "00100110" => UC_AD_LOCAL <= SREG38;
		when "00100111" => UC_AD_LOCAL <= SREG39;
		when "00101000" => UC_AD_LOCAL <= SREG40;
		when "00101001" => UC_AD_LOCAL <= SREG41;
		when "00101010" => UC_AD_LOCAL <= SREG42;
		when "00101011" => UC_AD_LOCAL <= SREG43;
		when "00101100" => UC_AD_LOCAL <= SREG44;
		when "00101101" => UC_AD_LOCAL <= SREG45;
		when "00101110" => UC_AD_LOCAL <= SREG46;
		when "00101111" => UC_AD_LOCAL <= SREG47;
		when "00110000" => UC_AD_LOCAL <= SREG48;
		when "00110001" => UC_AD_LOCAL <= SREG49;
		when "00110010" => UC_AD_LOCAL <= SREG50;
		when "00110011" => UC_AD_LOCAL <= SREG51;
		when "00110100" => UC_AD_LOCAL <= SREG52;
		when "00110101" => UC_AD_LOCAL <= SREG53;
		when "00110110" => UC_AD_LOCAL <= SREG54;
		when "00110111" => UC_AD_LOCAL <= SREG55;
		when "00111000" => UC_AD_LOCAL <= SREG56;
		when "00111001" => UC_AD_LOCAL <= SREG57;
		when "00111010" => UC_AD_LOCAL <= SREG58;
		when "00111011" => UC_AD_LOCAL <= SREG59;
		when "00111100" => UC_AD_LOCAL <= SREG60;
		when "00111101" => UC_AD_LOCAL <= SREG61;
		when "00111110" => UC_AD_LOCAL <= SREG62;
		when "00111111" => UC_AD_LOCAL <= SREG63;
		when "01000000" => UC_AD_LOCAL <= SREG64;
		when "01000001" => UC_AD_LOCAL <= SREG65;
		when "01000010" => UC_AD_LOCAL <= SREG66;
		when "01000011" => UC_AD_LOCAL <= SREG67;
		when "01000100" => UC_AD_LOCAL <= SREG68;
		when "01000101" => UC_AD_LOCAL <= SREG69;
		
		-- user can add more status registers as needed (200+)
		when others => UC_AD_LOCAL <= (others => '0');
	end case;
end process;

UC_AD <= UC_AD_LOCAL when (UC_CSIB_IN = '0') and (UC_REB_IN = '0') else (others => 'Z');
	-- when to drive the data bus between ARM and FPGA
	
-- toggle a few flags upon reading specific status registers
UC_READ_002: process(ASYNC_RESET, UC_REBG, UC_CSIB_IN, UC_ADDRESS, 
						SREG250_READ_TOGGLE, SREG254_READ_TOGGLE)
begin
	if(ASYNC_RESET = '1') then
		SREG250_READ_TOGGLE <= '0';
		SREG254_READ_TOGGLE <= '0';
	elsif rising_edge(UC_REBG) then
		if (UC_CSIB_IN = '0')  then
			if (UC_ADDRESS = 7) then
				SREG7_READ_TOGGLE <= not SREG7_READ_TOGGLE;
			end if;
			if (UC_ADDRESS = 250) then
				SREG250_READ_TOGGLE <= not SREG250_READ_TOGGLE;
			end if;
			if (UC_ADDRESS = 254) then
				SREG254_READ_TOGGLE <= not SREG254_READ_TOGGLE;
			end if;
		end if;
	end if;
end process;

-- reclock with CLK_P
RECLOCK_SREG9_TOGGLE: process(CLK_P,SREG7_READ_TOGGLE)
begin
	if rising_edge(CLK_P) then
		SREG7_READ_TOGGLE_D <= SREG7_READ_TOGGLE;
		SREG7_READ_TOGGLE_D2 <= SREG7_READ_TOGGLE_D;
		if(SREG7_READ_TOGGLE_D /= SREG7_READ_TOGGLE_D2) then
			LATCH_MONITORING_PULSE <= '1';
		else
			LATCH_MONITORING_PULSE <= '0';
		end if;
	end if;
end process;
	
-- write to FPGA control registers
UC_WRITE_001x: if (SIMULATION = '0') generate
	UC_WRITE_001: process(UC_CSIB_IN, UC_WEBG, UC_ALE_IN, UC_REB_IN, UC_AD)
	begin
		if rising_edge(UC_WEBG) then
			if (UC_CSIB_IN = '0') and (UC_ALE_IN = '0') and (UC_REB_IN = '1')  then
				case UC_ADDRESS is
					when x"00" => REG0 <= UC_AD;
					when x"01" => REG1 <= UC_AD;
					when x"02" => REG2 <= UC_AD;
					when x"03" => REG3 <= UC_AD;
					when x"04" => REG4 <= UC_AD;
					when x"05" => REG5 <= UC_AD;
					when x"06" => REG6 <= UC_AD;
					when x"07" => REG7 <= UC_AD;
					when x"08" => REG8 <= UC_AD;
					when x"09" => REG9 <= UC_AD;
					when x"0A" => REG10 <= UC_AD;
					when x"0B" => REG11 <= UC_AD;
					when x"0C" => REG12 <= UC_AD;
					when x"0D" => REG13 <= UC_AD;
					when x"0E" => REG14 <= UC_AD;
					when x"0F" => REG15 <= UC_AD;
					when x"10" => REG16 <= UC_AD;
					when x"11" => REG17 <= UC_AD;
					when x"12" => REG18 <= UC_AD;
					when x"13" => REG19 <= UC_AD;
					when x"14" => REG20 <= UC_AD;
					when x"15" => REG21 <= UC_AD;
					when x"16" => REG22 <= UC_AD;
					when x"17" => REG23 <= UC_AD;
					when x"18" => REG24 <= UC_AD;
					when x"19" => REG25 <= UC_AD;
					when x"1A" => REG26 <= UC_AD;
					when x"1B" => REG27 <= UC_AD;
					when x"1C" => REG28 <= UC_AD;
					when x"1D" => REG29 <= UC_AD;
					when x"1E" => REG30 <= UC_AD;
					when x"1F" => REG31 <= UC_AD;
					when x"20" => REG32 <= UC_AD;
					when x"21" => REG33 <= UC_AD;
					when x"22" => REG34 <= UC_AD;
					when x"23" => REG35 <= UC_AD;
					when x"24" => REG36 <= UC_AD;
					when x"25" => REG37 <= UC_AD;
					when x"26" => REG38 <= UC_AD;
					when x"27" => REG39 <= UC_AD;
					when x"28" => REG40 <= UC_AD;
					when x"29" => REG41 <= UC_AD;
					when x"2A" => REG42 <= UC_AD;
					when x"2B" => REG43 <= UC_AD;
					when x"2C" => REG44 <= UC_AD;
					when x"2D" => REG45 <= UC_AD;
					when x"2E" => REG46 <= UC_AD;
					when x"2F" => REG47 <= UC_AD;
					when x"30" => REG48 <= UC_AD;
					when x"31" => REG49 <= UC_AD;
					when x"32" => REG50 <= UC_AD;
					when x"33" => REG51 <= UC_AD;
					when x"34" => REG52 <= UC_AD;
					when x"35" => REG53 <= UC_AD;
					when x"36" => REG54 <= UC_AD;
					when x"37" => REG55 <= UC_AD;
					when x"38" => REG56 <= UC_AD;
					when x"39" => REG57 <= UC_AD;
					when x"3A" => REG58 <= UC_AD;
					when x"3B" => REG59 <= UC_AD;
					when x"3C" => REG60 <= UC_AD;
					when x"3D" => REG61 <= UC_AD;
					when x"3E" => REG62 <= UC_AD;
					when x"3F" => REG63 <= UC_AD;
					when x"40" => REG64 <= UC_AD;
					when x"41" => REG65 <= UC_AD;
					when x"42" => REG66 <= UC_AD;
					when x"43" => REG67 <= UC_AD;
					when x"44" => REG68 <= UC_AD;
					when x"45" => REG69 <= UC_AD;
					when x"46" => REG70 <= UC_AD;
					when x"47" => REG71 <= UC_AD;
					when x"48" => REG72 <= UC_AD;
					when x"49" => REG73 <= UC_AD;
					when x"4a" => REG74 <= UC_AD;
					when x"4b" => REG75 <= UC_AD;
					when x"4c" => REG76 <= UC_AD;
					when x"4d" => REG77 <= UC_AD;
					when x"4E" => REG78 <= UC_AD;
					when x"4F" => REG79 <= UC_AD;
					when x"50" => REG80 <= UC_AD;
					when x"51" => REG81 <= UC_AD;
					when others => null;
				end case;

				if (UC_ADDRESS = 58) or (UC_ADDRESS = 81) then
					-- dummy write to last control register
					CONFIG_CHANGE_TOGGLE <= not CONFIG_CHANGE_TOGGLE;	
					-- Configuration change toggles upon writing the last control register
					-- This happens invisibly to the user (only the ARM uC writes to this last control register
					-- which is invible to the user and to the ComBlock Control Center).
				end if;

				-- special case: MAC address LSB, at an address not erased when importing new settings
				if (UC_ADDRESS = 236) then
					REG236 <= UC_AD;	
					LAN_ADDR_CHANGE_TOGGLE <= not LAN_ADDR_CHANGE_TOGGLE;
				end if;
				
				-- Reserved:
				-- REG254 reserved for output serial
				-- REG255 write reserved for output serial (8-bit parallel format)
				if (UC_ADDRESS = 255) then
					-- REG255 write reserved for output serial (8-bit parallel format)
					if(PATH_TO_HOST = 2) then
						-- route response to host query over LAN/TCP-IP
						IP2_TCP_TX_DATA(0) <= UC_AD;
						TX_LAN_TOGGLE <= not TX_LAN_TOGGLE;
					end if;
				end if;
			end if;
		end if;
	end process;
end generate;

-- initialize control registers for simulation
UC_WRITE_001y: if (SIMULATION = '1') generate
process
begin
	-- initialize the control registers during simulation
	CONFIG_CHANGE_TOGGLE <= '0';
	-- 300 KSymbols/s
	REG9 <= x"52";	-- I symbol rate 
	REG10 <= x"49";	
	REG11 <= x"9d";	
	REG12 <= x"00";	
	REG13 <= x"52";    -- Q symbol rate
	REG14 <= x"49";
	REG15 <= x"9d";	
	REG16 <= x"00";	
	REG17 <= x"0a";	-- I spreading factor 
	REG18 <= x"00";
	REG19 <= x"0a";	-- Q spreading factor
	REG20 <= x"00";
	REG26 <= x"ca";
	REG60 <= x"d0";
	REG61 <= x"ca";
	REG70 <= x"52";	-- I symbol rate 
	REG71 <= x"49";	
	REG72 <= x"9d";	
	REG73 <= x"00";	
	REG74 <= x"52";    -- Q symbol rate
	REG75 <= x"49";
	REG76 <= x"9d";	
	REG77 <= x"00";	
--
--	wait for 1500 us;
--
--	-- 234 KSymbols/s
--	REG9 <= x"f3";	-- I symbol rate 
--	REG10 <= x"ae";	
--	REG11 <= x"7a";	
--	REG12 <= x"00";	
--	REG13 <= x"f3";    -- Q symbol rate
--	REG14 <= x"ae";
--	REG15 <= x"7a";	
--	REG16 <= x"00";	
--	REG17 <= x"0D";	-- I spreading factor 
--	REG18 <= x"00";
--	REG19 <= x"0D";	-- Q spreading factor
--	REG20 <= x"00";
--
--	REG70 <= x"f3";	-- I symbol rate 
--	REG71 <= x"ae";	
--	REG72 <= x"7a";	
--	REG73 <= x"00";	
--	REG74 <= x"f3";    -- Q symbol rate
--	REG75 <= x"ae";
--	REG76 <= x"7a";	
--	REG77 <= x"00";	
--	CONFIG_CHANGE_TOGGLE <= '1';

--	-- 122 KSymbols/s
--	REG9 <= x"90";	-- I symbol rate 
--	REG10 <= x"f6";	
--	REG11 <= x"3f";	
--	REG12 <= x"00";	
--	REG13 <= x"90";    -- Q symbol rate
--	REG14 <= x"f6";
--	REG15 <= x"3f";	
--	REG16 <= x"00";	
--	REG17 <= x"19";	-- I spreading factor 
--	REG18 <= x"00";
--	REG19 <= x"19";	-- Q spreading factor
--	REG20 <= x"00";
--
--	REG70 <= x"90";	-- I symbol rate 
--	REG71 <= x"36";	
--	REG72 <= x"3f";	
--	REG73 <= x"00";	
--	REG74 <= x"90";    -- Q symbol rate
--	REG75 <= x"f6";
--	REG76 <= x"3f";	
--	REG77 <= x"00";	
	CONFIG_CHANGE_TOGGLE <= '1';

	wait;
end process;
end generate;

--// reserved COMSCOPE -------------------------------------------------------
-- Comment out if ComScope feature is unused
UC_WRITE_003: process(UC_CSIB_IN, UC_WEBG, UC_ADDRESS, UC_AD, 
	FORCE_TRIGGER_TOGGLE, TRIGGER_REARM_TOGGLE, START_CAPTURE_TOGGLE)
begin
	if rising_edge(UC_WEBG) then
		if (UC_CSIB_IN = '0') and (UC_ALE_IN = '0') and (UC_REB_IN = '1')  then
			-- Reserved for ComScope			
			if (UC_ADDRESS = 237) then
				REG237 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 238) then
				REG238 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 239) then
				REG239 <= UC_AD;
			end if;
			if (UC_ADDRESS = 240) then
				REG240 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 241) then
				REG241 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 242) then
				REG242 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 243) then
				REG243 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 244) then
				REG244 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 245) then
				REG245 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 246) then
				REG246 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 247) then
				REG247 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 248) then
				REG248 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 249) then
				REG249 <= UC_AD;	
			end if;
			if (UC_ADDRESS = 250) then 
				-- detect one-shot force trigger	
				if(UC_AD(0) = '1') then	
					FORCE_TRIGGER_TOGGLE <= not(FORCE_TRIGGER_TOGGLE);
				end if;	
				-- detect one-shot re-arm	
				if(UC_AD(1) = '1') then	
					TRIGGER_REARM_TOGGLE <= not(TRIGGER_REARM_TOGGLE);
				end if;	
				-- start capturing again
				if(UC_AD(2) = '1') then	
					START_CAPTURE_TOGGLE <= not (START_CAPTURE_TOGGLE);
				end if;	
			end if;
		end if;
	end if;
end process;

--// end of COMSCOPE section -------------------------------------------------------

-- Reclock CONFIG_CHANGE_TOGGLE to be synchronous with processing clock CLK_P
RECLOCK_002: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		CONFIG_CHANGE_TOGGLE_D <= CONFIG_CHANGE_TOGGLE;
		CONFIG_CHANGE_TOGGLE_D2 <= CONFIG_CHANGE_TOGGLE_D;
		if(CONFIG_CHANGE_TOGGLE_D /= CONFIG_CHANGE_TOGGLE_D2) then
			CONFIG_CHANGE_PULSE <= '1';
		else
			CONFIG_CHANGE_PULSE <= '0';
		end if;
	end if;
end process;

LAN_ADDR_CHANGE_PULSE_GEN: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		LAN_ADDR_CHANGE_TOGGLE_D <= LAN_ADDR_CHANGE_TOGGLE;
		LAN_ADDR_CHANGE_TOGGLE_D2 <= LAN_ADDR_CHANGE_TOGGLE_D;
		if(LAN_ADDR_CHANGE_TOGGLE_D /= LAN_ADDR_CHANGE_TOGGLE_D2) then
			LAN_ADDR_CHANGE_PULSE <= '1';
		else
			LAN_ADDR_CHANGE_PULSE <= '0';
		end if;
	end if;
end process;


-- DNA Port ------------------------------------
-- Read FPGA unique DNA ID
DNA_ID_001: DNA_ID 
	GENERIC MAP(
		CLK_FREQUENCY => 125	-- CLK_P in MHz, as time reference
	)
	PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => SYNC_RESET_CLK_P,
		ID_OUT => DNA_ID_DATA,
		ID_VALID_OUT => open,
		ID_SAMPLE_CLK_OUT => DNA_ID_SAMPLE_CLK 
);


-- M&C USB interface --------------------------
-- REG255 reserved for reading serial port inputs
-- These signals are pulled high (to mimic stop bit).
REG255 <= "1111" & RX_LAN_BUFFER_EMPTY & "111";
	-- M&C port through LAN 
	-- indicates AVAILABILITY of 8-bit byte from LAN. Not actual data.
	-- When low, uC must read byte from LAN

-- Reclock TX_LAN_TOGGLE
RECLOCK_TX_LAN_TOGGLE: process(CLK_P,TX_LAN_TOGGLE)
begin
	if rising_edge(CLK_P) then
		TX_LAN_TOGGLE_D <= TX_LAN_TOGGLE;
		TX_LAN_TOGGLE_D2 <= TX_LAN_TOGGLE_D;
		if(TX_LAN_TOGGLE_D /= TX_LAN_TOGGLE_D2) then
			IP2_TCP_TX_DATA_VALID(0) <= '1';
		else
			IP2_TCP_TX_DATA_VALID(0) <= '0';
		end if;
	end if;
end process;

-- Immediately upon completing reading a M&C byte from the USB or LAN, ask for the 
-- next one. 
-- RACE CONDITION??????? ARM IS FAST!!!!
RECLOCK_RDN_D: process(CLK_P, SREG254_READ_TOGGLE)
begin
	if rising_edge(CLK_P) then
		SREG254_READ_TOGGLE_D <= SREG254_READ_TOGGLE;
		SREG254_READ_TOGGLE_D2 <= SREG254_READ_TOGGLE_D;

		RX_LAN_BUFFER_EMPTY_D <= RX_LAN_BUFFER_EMPTY;
		RX_LAN_BUFFER_EMPTY_D2 <= RX_LAN_BUFFER_EMPTY_D;


		if (SREG254_READ_TOGGLE_D2 /= SREG254_READ_TOGGLE_D) then
			-- end of M&C byte read from ARM uC.
			if(RX_LAN_BUFFER_EMPTY_D2 = '0') then
				-- last M&C byte read was over LAN. Increment LAN elastic buffer read pointer
				RX_LAN_SAMPLE_CLK_REQ <= '1';
				PATH_TO_HOST <= 2;	
					-- identifies LAN as the media through which	this module exchanges 
					-- M&C information. Response will be directed the same way.
			end if;
		else
			RX_LAN_SAMPLE_CLK_REQ <= '0';
		end if;
	end if;
end process;

-- read byte received over LAN
RX_USB_LAN <= RX_LAN;


--// MONITORING ----------------------------------


--// simulation. send to a tab-delimited text file for subsequent (Matlab) plot.
--SIM2OUTFILE_X: if(SIMULATION = '1') generate
--	Inst_SIM2OUTFILE1: SIM2OUTFILE 
--	generic map(
--		FILENAME => "com1826top1.txt"
--	)
--	PORT MAP(
--		CLK => CLK_P,
--		DATA1 => RX_DATA1(15 downto 4),
--		DATA2 => RX_DATA1_Q(13 downto 2),
--		DATA3 => x"000",	
--		SAMPLE_CLK_IN => RX_SAMPLE1_CLK
--	);
--end generate;

end Behavioral;
