-------------------------------------------------------------
-- MSS copyright 2016-2018
-- Filename:  COM1800_TOP.VHD
-- Authors: 
--		Alain Zarembowitch / MSS
-- Version: 003b
-- Last modified: 12/21/18
-- Inheritance: 	COM-1824_TOP 1/8/18
--
-- description:  Wideband channel emulator
-- Target: COM-1800 FPGA development platform.
-- Tested with Xilinx Vivado tools (not tested with ISE)
---------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.com5402pkg.all;	-- defines global types, max number of TCP streams, etc
Library UNISIM;
use UNISIM.vcomponents.all;

entity COM1800_TOP is
	generic (
       OPTION: std_logic_vector(7 downto 0) := x"20";    
			-- TODO: insert character here when using multiple firmware options
			-- (ASCII format '0' = x30, 'A' = x41, etc)
       REVISION: std_logic_vector(7 downto 0) := x"35";    -- '5'	
            --// 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 

        -- 1 GB 
        DDR3_NRANKS: integer := 1;    -- number of ranks , 1GB = 1, 8GB = 2
        DDR3_NADDRBITS: integer := 14;    -- number of address bits, 1GB = 14, 8GB = 16
        APP_NADDRBITS: integer := 28;    -- number of application address bits (address of 64-bit words), 
--            -- in accordance with memory size 28(1GB),29(4GB),30(8GB)
        -- 4 GB 
--        DDR3_NRANKS: integer := 2;    -- number of ranks , 1GB = 1, 4GB = 2, 8GB = 2
--        DDR3_NADDRBITS: integer := 15;    -- number of address bits, 1GB = 14, 4GB = 15, 8GB = 16
--        APP_NADDRBITS: integer := 29;    -- number of application address bits (address of 64-bit words), 
--            -- in accordance with memory size 28(1GB),29(4GB),30(8GB)
        -- 8 GB 
--		DDR3_NRANKS: integer := 2;	-- number of ranks , 1GB = 1, 4GB = 2, 8GB = 2
--		DDR3_NADDRBITS: integer := 16;	-- number of address bits, 1GB = 14, 4GB = 15, 8GB = 16
--		APP_NADDRBITS: integer := 30;	-- number of application address bits (address of 64-bit words), 
--            -- in accordance with memory size 28(1GB),29(4GB),30(8GB)
			
			
		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.
		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


		--// DDR3 SDRAM SODIMM. 1.5 V
		-- Inouts
		ddr3_dq                        : inout std_logic_vector(63 downto 0);
		ddr3_dqs_p                     : inout std_logic_vector(7 downto 0);
		ddr3_dqs_n                     : inout std_logic_vector(7 downto 0);

		-- Outputs
		ddr3_addr                      : out   std_logic_vector((DDR3_NADDRBITS-1) downto 0);
		ddr3_ba                        : out   std_logic_vector(2 downto 0);
		ddr3_ras_n                     : out   std_logic;
		ddr3_cas_n                     : out   std_logic;
		ddr3_we_n                      : out   std_logic;
		ddr3_reset_n                   : out   std_logic;
		ddr3_ck_p                      : out   std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_ck_n                      : out   std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_cke                       : out   std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_cs_n                      : out   std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_odt                       : out   std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_dm                        : out   std_logic_vector(7 downto 0);
 
		-- 4 XAUI pairs for future connection to 10gbase-T Ethernet PHY
		-- TODO
        
		--// 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(38 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 COM1800_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;
		PHASE_SHIFT_VAL: in std_logic_vector(7 downto 0);
		PHASE_SHIFT_TRIGGER_TOGGLE: in std_logic;
		INPUT_CLK_STOPPED : OUT std_logic;
		LOCKED : OUT std_logic;
		TP: OUT std_logic_vector(10 downto 1)
        );
    END COMPONENT;

	COMPONENT CLKGEN7_MMCM_DYNAMIC is
	GENERIC (
      CLKIN1_PERIOD: real
    );    
	PORT(
      CLK_IN1           : in     std_logic;
      SYNC_RESET           : in     std_logic;
      M: in std_logic_vector(9 downto 0);   
      D: in std_logic_vector(6 downto 0);
      O: in std_logic_vector(10 downto 0);
      PROGRAM: 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 CROSS_CLK_DOMAINS_NODATALOSS
	Generic (
		DATA_WIDTH: integer;
		ADDR_WIDTH: integer;
		LOW_LATENCY: std_logic	
	);
	PORT(
		CLK_A : IN std_logic;
		CLK_B : IN std_logic;
		ASYNC_RESET : IN std_logic;
		DATA_IN : IN std_logic_vector(DATA_WIDTH-1 downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		SOF_IN : IN std_logic;
		EOF_IN : IN std_logic;
		SAMPLE_CLK_OUT_REQ : 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;
		SOF_OUT : OUT std_logic;
		EOF_OUT : OUT std_logic
		);
	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 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 := 1;  
		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);
		SUBNET_MASK: in std_logic_vector(31 downto 0);
		MULTICAST_IP_ADDR: 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_vector((NTCPSTREAMS-1) downto 0);	
		MAC_TX_CTS : IN 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);	
		TCP_RX_CTS: in std_logic_vector((NTCPSTREAMS-1) downto 0);	
		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 ELASTIC_BUFFER_NRAMB
	GENERIC (
		NRAMB: integer;
		NBITS: integer;
		READ_AHEAD_1ADDRESS: std_logic
	);	
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		DATA_IN : IN std_logic_vector(8 downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		SAMPLE_CLK_OUT_REQ : IN std_logic;          
		SAMPLE_CLK_IN_REQ : OUT std_logic;
		DATA_OUT : OUT std_logic_vector(8 downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		SAMPLE_CLK_OUT_E : OUT std_logic;
		BUFFER_EMPTY: out std_logic
		);
	END COMPONENT;

	COMPONENT DDR3_DELAY
	GENERIC (
		DDR3_NRANKS: integer;
		DDR3_NADDRBITS: integer;
		APP_NADDRBITS: integer;	
		DATA1_STARTADDR : std_logic_vector(31 downto 0);
		DATA1_CEILINGADDR : std_logic_vector(31 downto 0);
		SIMULATION: std_logic
	);	
	PORT(
		CLK : IN  std_logic;
		SYNC_RESET : IN  std_logic;
		CLK200: in std_logic; 
		CLK333p3: in std_logic; 
		PLL_LOCKED_IN: in std_logic;
		DATA1_IN : IN std_logic_vector(31 downto 0);
		DATA1_IN_VALID : IN  std_logic;
		DATA1_IN_CTS : OUT  std_logic;
		DATA1_OUT : OUT std_logic_vector(31 downto 0);
		DATA1_OUT_VALID : OUT  std_logic;
		DATA1_OUT_CTS : IN  std_logic;
		DATA1_OUT_EMPTY : OUT std_logic;
		DATA1_DELAY_CHANGE_TOGGLE : IN std_logic;
		DATA1_DELAY : IN std_logic_vector(31 downto 0);    
		ddr3_dq : INOUT  std_logic_vector(63 downto 0);
		ddr3_dqs_p : INOUT  std_logic_vector(7 downto 0);
		ddr3_dqs_n : INOUT  std_logic_vector(7 downto 0);
		ddr3_addr : OUT  std_logic_vector((DDR3_NADDRBITS-1) downto 0);
		ddr3_ba : OUT  std_logic_vector(2 downto 0);
		ddr3_ras_n : OUT  std_logic;
		ddr3_cas_n : OUT  std_logic;
		ddr3_we_n : OUT  std_logic;
		ddr3_reset_n : OUT  std_logic;
		ddr3_ck_p : OUT  std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_ck_n : OUT  std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_cke : OUT  std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_cs_n : OUT  std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_odt : OUT  std_logic_vector((DDR3_NRANKS-1) downto 0);
		ddr3_dm : OUT  std_logic_vector(7 downto 0);
		DATA1_IN_ADDR : OUT  std_logic_vector(31 downto 0);
		DATA1_OUT_ADDR : OUT  std_logic_vector(31 downto 0);
		MEMORY_RDY_OUT: out std_logic;
		TP : OUT  std_logic_vector(20 downto 1)
	  );
	END COMPONENT;

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

	COMPONENT 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;
		TP: out std_logic_vector(10 downto 1)
		);
	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


--// CLOCKS, RESETS
signal CLK25g: std_logic := '0';
signal CLKREF_TCXOg: std_logic := '0';
signal CLK200: std_logic := '0';
signal CLK333p3: std_logic := '0';
signal CLK25_LOCKED: std_logic := '0';
signal CLK25_INPUT_CLK_STOPPED: std_logic := '0';
signal CLK10: std_logic := '0';
signal CLK10g: std_logic := '0';
signal CLK10g0: std_logic := '0';
signal CLK10g1: std_logic := '0';
signal CLK10_LOCKED: std_logic := '0';
signal CLK10_INPUT_CLK_STOPPED: std_logic := '0';
signal CLK125_FB: std_logic := '0';
signal CLK125: std_logic := '0';
signal CLK125_1: std_logic := '0';
signal CLK25: std_logic := '0';
signal CLK125_LOCKED: std_logic := '0';
signal CLK_P: std_logic := '0';
constant CLK_P_FREQUENCY: integer := 125; -- processing clock frequency CLK_P in MHz, as time reference

signal TICK_100MS: std_logic := '0';
signal TICK_1S: std_logic := '0';
signal TOGGLE_1s: std_logic := '0';
signal TOGGLE_1s_D0: std_logic := '0';
signal TOGGLE_1s_D: std_logic := '0';
signal TOGGLE_1s_D2: 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 RESET_STATE: integer range 0 to 1 := 0;
signal ASYNC_RESET: std_logic := '1';
signal SYNC_RESET_CLKREF: std_logic := '0';
signal SYNC_RESET_CLK_P: std_logic := '0';
signal ASYNC_RESET0_D: std_logic := '0';
signal ASYNC_RESET0_D2: std_logic := '0';
signal ASYNC_RESET1_D: std_logic := '0';
signal ASYNC_RESET1_D2: std_logic := '0';
signal ASYNC_RESET2_D: std_logic := '0';
signal ASYNC_RESET2_D2: std_logic := '0';
	-- asynchronous reset
signal READY_FLAG_CLK_P: std_logic := '0';

signal SERIAL_DAC: std_logic_vector(11 downto 0) := (others => '0');	
signal SERIAL_DAC_SAMPLE_CLK: std_logic := '0';
signal SERIAL_DAC_OP_MODE: std_logic_vector(1 downto 0) := (others => '0');

--// DDR3 SDRAM DELAY
signal DATA11: unsigned(15 downto 0):= (others => '0');
signal DATA12: unsigned(15 downto 0):= (others => '0');
signal DATA1: unsigned(31 downto 0):= (others => '0');
signal SAMPLE1_CLK: std_logic := '0';
signal DATA1_DELAY_CHANGE_TOGGLE: std_logic := '0';
signal DATA1_DELAY: std_logic_vector(31 downto 0) := (others => '0');
constant SODIMM_STARTADDR : std_logic_vector(31 downto 0) := (others => '0');
constant SODIMM_CEILINGADDR : std_logic_vector(31 downto 0) :=  x"08000000";	-- full 1GB memory;
--constant SODIMM_CEILINGADDR : std_logic_vector(31 downto 0) :=  x"20000000";	-- full 4GB memory
--constant SODIMM_CEILINGADDR : std_logic_vector(31 downto 0) :=  x"40000000";	-- full 8GB memory
signal DDR3_DATA1_IN_ADDR : std_logic_vector(31 downto 0) := (others => '0');
signal DDR3_DATA1_OUT_ADDR : std_logic_vector(31 downto 0) := (others => '0');
signal DDR3_MEMORY_RDY_OUT : std_logic := '0';
signal DDR3_TP : std_logic_vector(20 downto 1) := (others => '0');
signal DATA2: std_logic_vector(31 downto 0) := (others => '0');
signal SAMPLE2_CLK: std_logic := '0';
signal DATA21: std_logic_vector(15 downto 0) := (others => '0');
signal DATA22: std_logic_vector(15 downto 0) := (others => '0');


--//	1G ETHERNET MAC
signal CLK_SKEW21: std_logic_vector(15 downto 0) := (others => '0');
signal CLK_SKEW22: std_logic_vector(15 downto 0) := (others => '0');
signal LAN1_PHY_ID: std_logic_vector(15 downto 0) := (others => '0');
signal LAN1_MAC_ADDR: std_logic_vector(47 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_BAD_CRCS:  std_logic_vector(15 downto 0);
signal LAN1_TP: std_logic_vector(10 downto 1) := (others => '0');

--//-- IP STACK #1  -----------------------------------
constant NTCPSTREAMS1: integer := 2;  -- number of concurrent TCP streams handled by this component
signal IP1_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 LAN1_MULTICAST_IP_ADDR: std_logic_vector(31 downto 0) := (others => '0');	
signal IPSTACK1_TP: std_logic_vector(10 downto 1) := (others => '0');
signal LAN1_TCP_CONNECTION_RESET: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal LAN1_TCP_RX_DATA: SLV8xNTCPSTREAMStype;
signal LAN1_TCP_RX_DATA_VALID: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal LAN1_TCP_RX_CTS: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal LAN1_TCP_TX_DATA: SLV8xNTCPSTREAMStype;
signal LAN1_TCP_TX_DATA_VALID: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal LAN1_TCP_TX_CTS: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal LAN1_TCP_CONNECTED_FLAG: std_logic_vector((NTCPSTREAMS1-1) downto 0) := (others => '0');
signal LAN1_TCP_CONNECTION_RESET_STATE1: integer range 0 to 2 := 0;
signal LAN1_UDP_RX_DATA: std_logic_vector(7 downto 0) := (others => '0');
signal LAN1_UDP_RX_DATA_VALID: std_logic := '0';
signal LAN1_UDP_RX_DEST_PORT_NO_OUT: std_logic_vector(15 downto 0) := (others => '0');
signal LAN1_UDP_RX_SOF: std_logic := '0';
signal LAN1_UDP_RX_EOF: std_logic := '0';
signal LAN1_RX_DATA0_X: std_logic_vector(8 downto 0) := (others => '0');
signal LAN1_RX_SAMPLE0_CLK: std_logic := '0';
signal LAN1_RX_DATA1_X: std_logic_vector(8 downto 0) := (others => '0');
signal LAN1_RX_SAMPLE1_CLK: std_logic := '0';

--// LAN#1 TCP-IP Interface for M&C (port 1028)
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;

--// 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 T16b_1: std_logic_vector(15 downto 0) := (others => '0');	
signal T16b_1_VALID: std_logic := '0';
signal T16b_2: std_logic_vector(15 downto 0) := (others => '0');	
signal T16b_2_VALID: 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';
signal COMSCOPE2_TP: std_logic_vector(16 downto 1) := (others => '0');	

--//-- DNA Port ------------------------------------
signal DNA_ID_DATA: std_logic_vector(56 downto 0) := (others => '0');
signal DNA_ID_SAMPLE_CLK: std_logic := '0';
signal DNA_ID_VALID_OUT: std_logic := '0';
signal DNA_ID_TP: std_logic_vector(10 downto 1) := (others => '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_TOGGLE2_D: std_logic := '0';
signal CONFIG_CHANGE_TOGGLE2_D2: std_logic := '0';
signal CONFIG_CHANGE_PULSE_P: std_logic := '0';

--// Control Registers
constant NCREGS: integer := 20;	-- TODO: set the number of control registers. 
constant NCREG_IMIN: integer := 0;	-- starting at this index
constant NCREG_IMAX: integer := (NCREG_IMIN+NCREGS-1);
type SLV8xNCREGStype is array (integer range NCREG_IMIN to NCREG_IMAX) of std_logic_vector(7 downto 0);
signal CREG: SLV8xNCREGStype;
signal REG255: std_logic_vector(7 downto 0) := (others => '0');

--// Status Registers
constant NSREGS: integer := 9;	-- TODO: set the number of status registers.
constant NSREG_IMIN: integer := 7;	-- starting at this index
constant NSREG_IMAX: integer := (NSREG_IMIN+NSREGS-1);
type SLV8xNSREGStype is array (integer range NSREG_IMIN to NSREG_IMAX) of std_logic_vector(7 downto 0);
signal SREG: SLV8xNSREGStype := (others => (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 SREG7_READ_TOGGLE2_D: std_logic := '0';
signal SREG7_READ_TOGGLE2_D2: std_logic := '0';
signal LATCH_MONITORING_PULSE_P: 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 SREG250: std_logic_vector(7 downto 0):= "00000000";
signal SREG251: std_logic_vector(7 downto 0):= "00000000";

--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin
--//--------------------------------------------------------------------------
--// CLOCKS, RESETS 
--//--------------------------------------------------------------------------
-- Frequency plan: 
-- 19.2 MHz TCXO or 10 MHz external -> 25 MHz -> 125 MHz with multiple phases (Ethernet LAN PHY)
-- USAGE: set control register CREG(0)(0) = '0' to select the internal TCXO frequency reference.
SIM_001: if(SIMULATION = '1') generate
	 -- 10 MHz
    process
    begin
        CLK10g <= '0';
        wait for 50 ns;
        CLK10g <= '1';
        wait for 50 ns;
    end process;

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

REF_CLK_GEN_002: if(SIMULATION = '0') generate
   BUFG_001: BUFG port map(I => CLKREF_TCXO, O=> CLKREF_TCXOg);
   BUFG_002: BUFG port map (I => CLKREF_EXT, O => CLK10g1);

    -- generate alternative 10MHz clock from the always-present 19.2MHz TCXO clock 
     CLKGEN7C_001: 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 => CLK10g0,    -- 10 MHz global (future)
		PHASE_SHIFT_VAL => x"00",
		PHASE_SHIFT_TRIGGER_TOGGLE => '0',
		INPUT_CLK_STOPPED => CLK10_INPUT_CLK_STOPPED,
		LOCKED => CLK10_LOCKED,
		TP => open
    );

	-- select reference clock 
	BUFGMUX_001 : BUFGMUX
	port map (
		O => CLK10g,   -- 1-bit output: Clock output
		I0 => CLK10g0, -- 1-bit input: Clock input (S=0)
		I1 => CLK10g1, -- 1-bit input: Clock input (S=1)
		S => CREG(0)(0)   -- 1-bit input: Clock select. 
	);

end generate;

-- generate 25 MHz from 10 MHz
CLKGEN7D_001: CLKGEN7_MMCM_ADJ 
GENERIC MAP(
	CLKFBOUT_MULT_F => 63.750,
	CLKOUT0_DIVIDE_F => 25.500,
	CLKIN1_PERIOD => 100.00
) 
PORT MAP(
	CLK_IN1 => CLK10g,    -- 10 MHz TCXO clock 
	CLK_OUT1 => CLK25g,    -- 25 MHz global
	PHASE_SHIFT_VAL => x"00",
	PHASE_SHIFT_TRIGGER_TOGGLE => '0',
	INPUT_CLK_STOPPED => CLK25_INPUT_CLK_STOPPED,
	LOCKED => CLK25_LOCKED,
	TP => open
);

-- generate multiple offsets for the 125 MHz clock 
-- Includes several delayed versions for LAN PHY  
  PLLE2_ADV_001 : PLLE2_ADV
  generic map
   (BANDWIDTH            => "LOW",

    
    COMPENSATION         => "ZHOLD",
    DIVCLK_DIVIDE        => 1,
    CLKFBOUT_MULT        => 40,
    CLKFBOUT_PHASE       => 0.000,
    CLKOUT0_DIVIDE       => 8,
    CLKOUT0_PHASE        => 0.000,
    CLKOUT0_DUTY_CYCLE   => 0.500,
    CLKOUT1_DIVIDE       => 8,
    CLKOUT1_PHASE        => 123.75,	-- (delay ns / 8ns)*360 deg*8 (because phase delay at vco) modulo 45 deg
    CLKOUT1_DUTY_CYCLE   => 0.500,
    CLKOUT2_DIVIDE       => 5,
    CLKOUT2_PHASE        => 0.000,
    CLKOUT2_DUTY_CYCLE   => 0.500,
    CLKOUT3_DIVIDE       => 3,
    CLKOUT3_PHASE        => 0.000,
    CLKOUT3_DUTY_CYCLE   => 0.500,
    CLKIN1_PERIOD        => 40.0)
  port map
    -- Output clocks
   (
    CLKFBOUT            => CLK125_FB,
    CLKOUT0             => CLK125,	-- reference 125MHz for LAN PHY 
    CLKOUT1             => CLK125_1,	-- controlled delay
    CLKOUT2             => CLK200,	-- for DDR3 wrapper
    CLKOUT3             => CLK333p3,	-- for DDR3 wrapper
    CLKOUT4             => open,
    CLKOUT5             => open,
    -- Input clock control
    CLKFBIN             => CLK125_FB,
    CLKIN1              => CLK25g,
    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              => CLK125_LOCKED,
    PWRDWN              => '0',
    RST                 => not CLK25_LOCKED);


BUFG_004: BUFG port map(I => CLK125, O => CLK_P); -- processing clock CLK_P 

-- report PLLs lock status and presence of input frequency reference(s)
SREG(8)(2 downto 0) <= CLK125_LOCKED & CLK25_LOCKED & (not CLK25_INPUT_CLK_STOPPED);

 -- Generate miscellaneous global clocks and resets from the 
 -- reference 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(CLK25_LOCKED = '1') and (CLK125_LOCKED = '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;

-- generate a reset synchronous with CLKREF at the end of the ASYNC_RESET
SYNC_RESET_CLKREF_GEN: process(ASYNC_RESET, CLK10g)
begin
	if rising_edge(CLK10g) then
		ASYNC_RESET0_D <= ASYNC_RESET;
		ASYNC_RESET0_D2 <= ASYNC_RESET0_D;
		
		if(ASYNC_RESET0_D = '0') and (ASYNC_RESET0_D2 = '1')  then
			SYNC_RESET_CLKREF <= '1';
		else
			SYNC_RESET_CLKREF <= '0';
		end if;
		
	end if;
end process;

-- 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_RESET2_D <= ASYNC_RESET;
		ASYNC_RESET2_D2 <= ASYNC_RESET2_D;
		
		if(ASYNC_RESET2_D = '0') and (ASYNC_RESET2_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;

	-- 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_P_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';
				TOGGLE_1s <= not TOGGLE_1s;
			else
				TICK_100MS_CNTR <= TICK_100MS_CNTR - 1;
				TICK_1S <= '0';
			end if;
		else
			TICK_1S <= '0';
		end if;
	end if;
end process;

--//--------------------------------------------------------------------------
--//	SERIAL DAC
--//--------------------------------------------------------------------------
-- 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 => CLK_P_FREQUENCY
	)
	PORT MAP(
	CLK => CLK_P,							-- synchronous clock
	DATA_IN => SERIAL_DAC,		-- user 12-bit input data
	DATA_IN_CLK => SERIAL_DAC_SAMPLE_CLK,		-- user enable
	OP_MODE(0) => SERIAL_DAC_OP_MODE(0),			-- "00" for normal DAC operation, "11" for high impedance output
	OP_MODE(1) => SERIAL_DAC_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						
	);
SERIAL_DAC_OP_MODE <= "00";	-- J4.b13 output always on.

--//--------------------------------------------------------------------------
--//	DDR3 SDRAM DELAY
--//--------------------------------------------------------------------------
-- generate two test ramps in opposite directions, then delay them
TEST_RAMP_GEN: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		DATA11 <= DATA11 + 1;
		DATA12 <= DATA12 - 1;
	end if;
end process;
-- pack 1 complex (14-bit I, 14-bit Q) sample into one 32-bit word
-- room for future 16-bit samples.
-- order: I before Q.
DATA1 <= DATA11 & DATA12;
SAMPLE1_CLK <= '1';	-- every clock brings a new 32bit sample

-- delay is expressed in SDRAM addresses (x64-bit wide data)
-- Always round to multiple of 8 addresses (because BL = 8), or 16 complex samples
DATA1_DELAY <= x"00010000";

DATA1_DELAY_CHANGE_TOGGLE <= CONFIG_CHANGE_TOGGLE;
DDR3_DELAY_001: DDR3_DELAY 
GENERIC MAP(
	DDR3_NRANKS => DDR3_NRANKS,
	DDR3_NADDRBITS => DDR3_NADDRBITS,
	APP_NADDRBITS => APP_NADDRBITS,
	DATA1_STARTADDR => SODIMM_STARTADDR,
	DATA1_CEILINGADDR => SODIMM_CEILINGADDR,
	SIMULATION => SIMULATION
 ) 
PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => SYNC_RESET_CLK_P,
	CLK200 => CLK200,
	CLK333p3 => CLK333p3,
	PLL_LOCKED_IN => CLK125_LOCKED,
	DATA1_IN => std_logic_vector(DATA1),
	DATA1_IN_VALID => SAMPLE1_CLK,
	DATA1_IN_CTS => open,	-- unused. DDR3 max throughput is large enough. no need for flow control.
	DATA1_DELAY_CHANGE_TOGGLE => DATA1_DELAY_CHANGE_TOGGLE,
	DATA1_DELAY => DATA1_DELAY,
	DATA1_OUT => DATA2,
	DATA1_OUT_VALID => SAMPLE2_CLK,
	DATA1_OUT_CTS => SAMPLE1_CLK,	-- use the same regular sampling rate at input/output. acts as regulator.
	DATA1_OUT_EMPTY => open,
	ddr3_dq => ddr3_dq,
	ddr3_dqs_p => ddr3_dqs_p,
	ddr3_dqs_n => ddr3_dqs_n,
	ddr3_addr => ddr3_addr,
	ddr3_ba => ddr3_ba,
	ddr3_ras_n => ddr3_ras_n,
	ddr3_cas_n => ddr3_cas_n,
	ddr3_we_n => ddr3_we_n,
	ddr3_reset_n => ddr3_reset_n,
	ddr3_ck_p => ddr3_ck_p,
	ddr3_ck_n => ddr3_ck_n,
	ddr3_cke => ddr3_cke,
	ddr3_cs_n => ddr3_cs_n,
	ddr3_dm => ddr3_dm,
	ddr3_odt => ddr3_odt,
	MEMORY_RDY_OUT => DDR3_MEMORY_RDY_OUT,
	DATA1_IN_ADDR => DDR3_DATA1_IN_ADDR,	-- debug
	DATA1_OUT_ADDR => DDR3_DATA1_OUT_ADDR,	-- debug
	TP => DDR3_TP
);

DATA21 <= DATA2(31 downto 16);
DATA22 <= DATA2(15 downto 0);

--//--------------------------------------------------------------------------
--//	1G ETHERNET MAC
--//--------------------------------------------------------------------------
-- Interface with on-board GbE PHY: Micrel KSZ9031
-- Support 10/100/1000 Ethernet LAN.
CLK_SKEW21 <= x"0310"; 	 --(INTERNAL_PHY_CLKS_DELAYS => '0')
CLK_SKEW22 <= x"0000";    -- future	

--MAC address automatically generated from unique DNA_ID
LAN1_MAC_ADDR <= x"02" & DNA_ID_DATA(39 downto 0);    
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 => 125,
	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 => not READY_FLAG_CLK_P,	-- 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 => DNA_ID_SAMPLE_CLK,	-- to load the custom CLK_SKEWs and MAC address once and for all at power up/reset
	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 => 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 => 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 => LAN1_LINK_STATUS,
	SPEED_STATUS => LAN1_SPEED_STATUS,
	DUPLEX_STATUS => LAN1_DUPLEX_STATUS,
	PHY_ID => LAN1_PHY_ID,
	N_RX_FRAMES => open,
	N_RX_BAD_CRCS => LAN1_N_RX_BAD_CRCS,
	N_RX_FRAMES_TOO_SHORT => open,
	N_RX_FRAMES_TOO_LONG => open,
	N_RX_WRONG_ADDR => open,
	N_RX_LENGTH_ERRORS => open,
	CS_CLKG => open,
	CS1 => open,
	CS1_CLK => open,
	CS2 => open,
	CS2_CLK => open,
	CT1 => open,
	CT1_CLK => open,
	TP => LAN1_TP
);

SREG(7) <= LAN1_PHY_ID(7 downto 0);

--//-- IP STACK #1  -----------------------------------
-- reclock with CLK_P for easier P&R
-- 1 UDP receive ports + 1 UDP transmit port + 2 TCP servers
-- TCP server at port 1028 for monitoring & control (tx/rx)
-- TCP server at port 1024 for the user's application
-- UDP receive port 1029 for backdoor commands
RECLOCK_IP1: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		IP1_ADDRv4(31 downto 0) <= CREG(1) & CREG(2) & CREG(3) & CREG(4);	-- local IP address
		SUBNET_MASK <= CREG(5) & CREG(6) & CREG(7) & CREG(8);
		GATEWAY_IP_ADDR <= CREG(9) & CREG(10) & CREG(11) & CREG(12);
	end if;
end process;

IPSTACK_001: COM5402 
GENERIC MAP(
		NUDPTX => 1,
		NUDPRX => 1,
		NTCPSTREAMS => 2,  
		IGMP_EN => '1',	-- enable multicast UDP
		CLK_FREQUENCY => 125,	-- CLK_P 125 MHz, as time reference
		TX_IDLE_TIMEOUT => 50,	-- 50*4us = 200us 
		TCP_KEEPALIVE_PERIOD => 60,
		SIMULATION => '0'
)
PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => not READY_FLAG_CLK_P,
	MAC_ADDR => LAN1_MAC_ADDR,
	IPv4_ADDR => IP1_ADDRv4,
	IPv6_ADDR => x"00000000000000000000000000000000",
	MULTICAST_IP_ADDR => LAN1_MULTICAST_IP_ADDR,  
	SUBNET_MASK => SUBNET_MASK,
	GATEWAY_IP_ADDR => GATEWAY_IP_ADDR,
	CONNECTION_RESET => LAN1_TCP_CONNECTION_RESET,
	TCP_KEEPALIVE_EN => "11",
	-- 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_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 => LAN1_UDP_RX_DATA,
	UDP_RX_DATA_VALID => LAN1_UDP_RX_DATA_VALID,
	UDP_RX_SOF => LAN1_UDP_RX_SOF, 
	UDP_RX_EOF => LAN1_UDP_RX_EOF, 
	UDP_RX_DEST_PORT_NO_IN => x"0405",  	-- port 1029  
	CHECK_UDP_RX_DEST_PORT_NO => '1',	
	UDP_RX_DEST_PORT_NO_OUT => LAN1_UDP_RX_DEST_PORT_NO_OUT,
	-- UDP tx
	UDP_TX_DATA => x"00",
	UDP_TX_DATA_VALID => '0',
	UDP_TX_SOF => '0',
	UDP_TX_EOF => '0',
	UDP_TX_CTS => open,
	UDP_TX_ACK => open,
	UDP_TX_NAK => open,
	UDP_TX_DEST_IP_ADDR => (others => '0'),
	UDP_TX_DEST_PORT_NO => (others => '0'),
	UDP_TX_SOURCE_PORT_NO => x"0000",	
	-- TCP rx streams
	TCP_RX_DATA => LAN1_TCP_RX_DATA,	
	TCP_RX_DATA_VALID => LAN1_TCP_RX_DATA_VALID,
	TCP_RX_RTS => open,
	TCP_RX_CTS => LAN1_TCP_RX_CTS,	

	-- TCP tx streams
	TCP_TX_DATA => LAN1_TCP_TX_DATA,
	TCP_TX_DATA_VALID => LAN1_TCP_TX_DATA_VALID,
	TCP_TX_CTS => LAN1_TCP_TX_CTS,	
	-- Monitoring
	TCP_CONNECTED_FLAG => LAN1_TCP_CONNECTED_FLAG,
--	CS1 => S1_1,
--	CS1_CLK => S1_1_CLK,
--	CS2 => S2_1,
--	CS2_CLK => S2_1_CLK,
	TP => IPSTACK1_TP	
);

-- one elastic buffer for each tcp rx stream
-- M&C, TCP port 1028 (port is defined within COM5402 component) OR UDP port 1029 
LAN1_RX_DATA0_X <= ("0" & LAN1_UDP_RX_DATA) when (LAN1_UDP_RX_DATA_VALID = '1') else ("0" & LAN1_TCP_RX_DATA(0));
LAN1_RX_SAMPLE0_CLK <= '1'  when (LAN1_UDP_RX_DATA_VALID = '1') and (unsigned(LAN1_UDP_RX_DEST_PORT_NO_OUT) = 1029) else
								LAN1_TCP_RX_DATA_VALID(0);

ELASTIC_BUFFER_NRAMB_002: ELASTIC_BUFFER_NRAMB 
generic map(
	NRAMB => 1, 
	NBITS => 9,
	READ_AHEAD_1ADDRESS => '1'	-- no read latency, tricky timing ok because ARM is slower.
)
PORT MAP(
	CLK => CLK_P,
	SYNC_RESET => SYNC_RESET_CLK_P,
	DATA_IN => LAN1_RX_DATA0_X,	-- 9 bit wide
	SAMPLE_CLK_IN => LAN1_RX_SAMPLE0_CLK,
	SAMPLE_CLK_IN_REQ => LAN1_TCP_RX_CTS(0),
	DATA_OUT => LAN1_RX_DATA1_X,	-- 9 bit wide
	SAMPLE_CLK_OUT => open,
	SAMPLE_CLK_OUT_E => open,
	SAMPLE_CLK_OUT_REQ => RX_LAN_SAMPLE_CLK_REQ,
	BUFFER_EMPTY => RX_LAN_BUFFER_EMPTY
);
RX_LAN <= LAN1_RX_DATA1_X(7 downto 0);

MONITORING_004: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		if(LATCH_MONITORING_PULSE_P = '1') then
			-- latch in multi-byte status registers upon reading status register SREG(7)
			SREG(9) <= LAN1_MAC_ADDR(47 downto 40);
			SREG(10) <= LAN1_MAC_ADDR(39 downto 32);
			SREG(11) <= LAN1_MAC_ADDR(31 downto 24);
			SREG(12) <= LAN1_MAC_ADDR(23 downto 16);
			SREG(13) <= LAN1_MAC_ADDR(15 downto 8);
			SREG(14) <= LAN1_MAC_ADDR(7 downto 0);
			SREG(15)(0) <= LAN1_TCP_CONNECTED_FLAG(0);
		end if;
	end if;
end process;

--//--------------------------------------------------------------------------
--//	TEST POINTS
--//--------------------------------------------------------------------------
-- Warning: test points can make timing much worse!
--LEFT_CONNECTOR_A(10 downto 1) <= ;

--//--------------------------------------------------------------------------
--//	COMSCOPE
--//--------------------------------------------------------------------------
COMSCOPE_GEN: if (SIMULATION = '0') generate
	--  Comment in/out as needed. unused during simulation
	-- Define Comscope traces here 

	-- Trace 1
	S1_1 <= std_logic_vector(DATA11(15 downto 8));		-- test ramp1 before delay
	S1_1_CLK <= SAMPLE1_CLK;
	S1_2 <= std_logic_vector(DATA12(13 downto 6));		-- test ramp2 before delay
	S1_2_CLK <= SAMPLE1_CLK;
-- TODO define other ComScope traces here
--	S1_3 <= 
--	S1_3_CLK <= 

	-- Trace 2
	S2_1 <= DATA21(15 downto 8);		-- test ramp1 after delay
	S2_1_CLK <= SAMPLE2_CLK;
	S2_2 <= DATA22(13 downto 6);		-- test ramp2 after delay
	S2_2_CLK <= SAMPLE2_CLK;

	-- Trigger (1-bit format)
	T16b_1(0) <= '0';
	T16b_1_VALID <= '0';
	
	COMSCOPE2_001: COMSCOPE2 
	generic map(
		TRACE1_ENABLED => '1',    -- TODO enable as many simultaneous traces as needed
		TRACE2_ENABLED => '1',
		TRACE3_ENABLED => '0',
		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 => T16b_1,
		T16b_1_VALID => T16b_1_VALID,
		T16b_2 => T16b_2,
		T16b_2_VALID => T16b_2_VALID,
		T16b_3 => (others => '0'),
		T16b_3_VALID => '0',
		T16b_4 => (others => '0'),
		T16b_4_VALID => '0',
		SREG250 => SREG250,
		SREG251 => SREG251,
		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 => COMSCOPE2_TP
	);
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 
UC_READ_001: process(UC_ADDRESS, REG255, RX_LAN, SREG251, SREG250, SREG)
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_LAN;		-- reg 254 = 8-bit data from 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 <= SREG251;	-- reg 251 = comscope  status
		when "11111010" => UC_AD_LOCAL <= SREG250;	-- reg 250 = comscope data byte
		
		-- User-defined status registers -------
		-- Note: SREG0-6 are inserted by the ARM co-processor, not the FPGA.
		when "00000111" => UC_AD_local <= SREG(7);
		when "00001000" => UC_AD_local <= SREG(8);
		when "00001001" => UC_AD_local <= SREG(9);
		when "00001010" => UC_AD_local <= SREG(10);
		when "00001011" => UC_AD_local <= SREG(11);
		when "00001100" => UC_AD_local <= SREG(12);
		when "00001101" => UC_AD_local <= SREG(13);
		when "00001110" => UC_AD_local <= SREG(14);
		when "00001111" => UC_AD_local <= SREG(15);
--		when "00010000" => UC_AD_local <= SREG(16);
--		when "00010001" => UC_AD_local <= SREG(17);
--		when "00010010" => UC_AD_local <= SREG(18);
--		when "00010011" => UC_AD_local <= SREG(19);
--		when "00010100" => UC_AD_local <= SREG(20);
--		when "00010101" => UC_AD_local <= SREG(21);
--		when "00010110" => UC_AD_local <= SREG(22);
--		when "00010111" => UC_AD_local <= SREG(23);
--		when "00011000" => UC_AD_local <= SREG(24);
--		when "00011001" => UC_AD_local <= SREG(25);
--		when "00011010" => UC_AD_local <= SREG(26);
--		when "00011011" => UC_AD_local <= SREG(27);
--		when "00011100" => UC_AD_local <= SREG(28);
--		when "00011101" => UC_AD_local <= SREG(29);
--		when "00011110" => UC_AD_local <= SREG(30);
--		when "00011111" => UC_AD_local <= SREG(31);
--		when "00100000" => UC_AD_local <= SREG(32);
--		when "00100001" => UC_AD_local <= SREG(33);
--		when "00100010" => UC_AD_local <= SREG(34);
--		when "00100011" => UC_AD_local <= SREG(35);
--		when "00100100" => UC_AD_local <= SREG(36);
--		when "00100101" => UC_AD_local <= SREG(37);
--		when "00100110" => UC_AD_local <= SREG(38);
--		when "00100111" => UC_AD_local <= SREG(39);
--		when "00101000" => UC_AD_local <= SREG(40);
		when others => UC_AD_local <= x"00";

	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_SREG7_TOGGLE_001: 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_P <= '1';
		else
			LATCH_MONITORING_PULSE_P <= '0';
		end if;
	end if;
end process;

-- write to FPGA control registers
UC_WRITE_001ax: if (SIMULATION = '0') generate
	UC_WRITE_001a: process(UC_WEBG)
	begin
		if rising_edge(UC_WEBG) then
			if (UC_CSIB_IN = '0') and (UC_ALE_IN = '0') and (UC_REB_IN = '1')  then
				for I in NCREG_IMIN to NCREG_IMAX loop
					if(UC_ADDRESS = I) then
						CREG(I) <= UC_AD;
					end if;
				end loop;
			end if;
		end if;
	end process;
end generate;
	
-- 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
				if (UC_ADDRESS = 236) then
					-- activate a configuration change (with possible service interruption)
					-- writing 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;
				-- 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)
					-- route response to host query over LAN/TCP-IP
					LAN1_TCP_TX_DATA(0) <= UC_AD;
					TX_LAN_TOGGLE <= not TX_LAN_TOGGLE;
				end if;
			end if;
		end if;
	end process;
end generate;

-- initialize control registers for simulation
UC_WRITE_001y: if (SIMULATION = '1') generate
	-- initialize the control registers during simulation
	CREG(0) <= x"00";	
	CREG(1) <= x"00";	
	CREG(2) <= x"00";	
	CREG(3) <= x"00";	
	CREG(4) <= x"00";	
	CREG(5) <= x"00";	
	CREG(6) <= x"00";	
	CREG(7) <= x"00";	
	CREG(8) <= x"00";	
	CREG(9) <= x"00";	
	CREG(10) <= x"00";
	CREG(11) <= x"00"; 
	CREG(12) <= x"00";	
--	CREG(13) <= x"00";	-- 
--	CREG(14) <= x"00";	-- 
--	CREG(15) <= x"00";	-- 
--	CREG(16) <= x"00";	-- 
--	CREG(17) <= x"00";   -- 
--	CREG(18) <= x"00";	--
--	CREG(19) <= x"00";	--
	
	UC_WRITE_001: process
	begin
		CONFIG_CHANGE_TOGGLE <= '0';
		wait for 75us;
		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 various processing clocks
CONFIG_CHANGE_PULSE_GEN_002: process(CLK_P)
begin
	if rising_edge(CLK_P) then
		CONFIG_CHANGE_TOGGLE2_D <= CONFIG_CHANGE_TOGGLE;
		CONFIG_CHANGE_TOGGLE2_D2 <= CONFIG_CHANGE_TOGGLE2_D;
		if(CONFIG_CHANGE_TOGGLE2_D /= CONFIG_CHANGE_TOGGLE2_D2) then
			CONFIG_CHANGE_PULSE_P <= '1';
		else
			CONFIG_CHANGE_PULSE_P <= '0';
		end if;
	end if;
end process;


-- DNA Port ------------------------------------
-- Read FPGA unique DNA ID
DNA_ID_001: DNA_ID 
	GENERIC MAP(
		CLK_FREQUENCY => CLK_P_FREQUENCY	-- CLK_P in MHz, as time reference  
	)
	PORT MAP(
		CLK => CLK_P,
		SYNC_RESET => not READY_FLAG_CLK_P,
		ID_OUT => DNA_ID_DATA,
		ID_VALID_OUT => DNA_ID_VALID_OUT,
		ID_SAMPLE_CLK_OUT => DNA_ID_SAMPLE_CLK,
		TP => DNA_ID_TP
);

-- 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
			LAN1_TCP_TX_DATA_VALID(0) <= '1';
		else
			LAN1_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) and (RX_LAN_BUFFER_EMPTY_D2 = '0') then
			-- end of M&C byte read from ARM uC.
			-- last M&C byte read was over LAN. Increment LAN elastic buffer read pointer
			RX_LAN_SAMPLE_CLK_REQ <= '1';
		else
			RX_LAN_SAMPLE_CLK_REQ <= '0';
		end if;
	end if;
end process;

--// 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 => "com1800top.txt"
--	)
--	PORT MAP(
--		CLK => CLK_P,
--		DATA1 => DATA11(15 downto 4),
--		DATA2 => DATA12(15 downto 4),
--		DATA3 => DATA21(15 downto 4),	
--		SAMPLE_CLK_IN => '1'
--	);
--end generate;

end Behavioral;
