----------------------------------------------------------------------------------
-- Company:  University of Connecticut
-- Engineer: Igor Senderovich
-- 
-- Create Date:    16:06:03 12/28/2007 
-- Design Name:    Total FPGA testing module
-- Module Name:    FPGA_main - behavioral
-- Description:    Top-level design for TAGM Vbias board controller
------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

library UNISIM;
use UNISIM.VComponents.all;

library FPGA_BasicComp;
use FPGA_BasicComp.BasicComp.all;
use FPGA_BasicComp.MainComp.all;
use FPGA_BasicComp.FPGA_config.all;

entity FPGA_main is
 port ( ExtClk : in std_logic;			-- external crystal clock
	ExtRst_low : in std_logic;		-- external jumper, active low

	LocStamp : in std_logic_vector (4 downto 0);	-- geographical address jumpers
	StateCode  : out std_logic_vector (2 downto 0); -- global state

	-- SPI bus (with ADC and Temp sensors) lines
	SPI_SCLK 	: out std_logic;	-- 10 MHz clock for SPI bus
	SPI_T_CE	: out std_logic;	-- clock enable for temperature sensor
	SPI_A_CS_low	: out std_logic;	-- chip select (bar) for ADC
	SPI_SDI_tri	: out std_logic;	-- bus device read line
	SPI_SDO		: in std_logic;		-- bus device write line
	  
	-- AD5535 serial bus (DAC) lines
	DAC_SCLK 	: out std_logic;	-- 20 MHz clock for AD5535 serial bus
	DAC_RESET_low	: out std_logic;	-- reset (bar) for AD5535 DAC
	DAC_SYNC_low 	: out std_logic; 	-- sync (bar) line for AD5535 serial bus
	DAC_DIN		: out std_logic;	-- data line for AD5535 serial bus

	-- CP2201 parallel MuxIntel bus (ethernet controller) lines
	Eth_CLK 	: out std_logic;	-- 20 MHz clock for MuxIntel bus
	Eth_RST_low 	: inout std_logic;	-- reset (bar) for CP2201
	Eth_INT_low 	: in std_logic;		-- active-low interrupt from CP2201
	Eth_ALE 	: out std_logic;	-- address latch enable for MuxIntel bus
	Eth_AD  	: inout std_logic_vector (7 downto 0); -- 8-bit MuxIntel bus data lines
	Eth_RD_low 	: out std_logic;	-- data latch enable (bar) for read from device buffer
	Eth_WR_low 	: out std_logic;	-- data latch enable (bar) for write to device buffer
	Eth_CS_low 	: out std_logic;	-- chip select (bar) for MuxIntel bus

	-- RS-232 transmit line (for debugging)
	Serial_port	: out std_logic;	-- output pin for RS-232 stream

	-- General-purpose debug logic pins
	Debug_port	: out std_logic;	-- used for diagnostics
	DCM_stable	: out std_logic		-- true after the DCM has stabilized
 );
end FPGA_main;

architecture behavioral of FPGA_main is

	--Clock generation signals
	signal Clk : std_logic;  	-- the main FPGA clock generated from DCM_CLK0
	signal Clk2 : std_logic;  	-- divided-by-2 FPGA clock generated from DCM_CLKDV

	--Global chip reset signal
	signal Rst : std_logic;		-- internal signal wired to chip global reset
	
	--State register
	type State_t is (HARD_RESET,
			 SOFT_RESET,
			 PACKET_WAIT,
			 PACKET_RECEIVED,
			 QUERY_INPUTS,
			 REPORT_STATUS,
			 PROGRAM_DAC,
			 REPORT_DAC_VALUES
	);
	signal State : State_t := HARD_RESET;

	signal INT_Go_reg : std_logic := '0';

	--Clock controller lines
	signal DCM_CLK0 : std_logic;
	--signal DCM_CLK180 : std_logic;
	--signal DCM_CLK270 : std_logic;
	--signal DCM_CLK2X : std_logic;
	--signal DCM_CLK2X180 : std_logic;
	--signal DCM_CLK90 : std_logic;
	signal DCM_CLKDV : std_logic;
	--signal DCM_CLKFX : std_logic;
	--signal DCM_CLKFX180 : std_logic;
	signal DCM_LOCKED : std_logic;
	--signal DCM_PSDONE : std_logic;
	--signal DCM_STATUS : std_logic_vector (7 downto 0);
	signal DCM_CLKFB : std_logic;
	signal DCM_CLKIN : std_logic; 
	--signal DCM_PSCLK : std_logic;
	--signal DCM_PSEN : std_logic;
	--signal DCM_PSINCDEC : std_logic;

	--Board geographical address
	signal LocStamp8bit : std_logic_vector (7 downto 0);	-- geographic address byte

	--Random access memory (1k x 16bits) control lines
	signal RAM_ADDR_tri : std_logic_vector (9 downto 0);
	signal RAM_DO : std_logic_vector (15 downto 0);
	signal RAM_DI_tri  : std_logic_vector (15 downto 0);
	signal RAM_DOP : std_logic_vector (1 downto 0);
	signal RAM_DIP : std_logic_vector (1 downto 0);
	signal RAM_WE_tri : std_logic_vector (1 downto 0);
	signal RAM_SSR : std_logic;
	signal RAM_EN : std_logic;
	signal RAM_ADDRB : std_logic_vector (9 downto 0) := "00" & X"36";
	signal RAM_DOB : std_logic_vector (15 downto 0);
	signal RAM_DIB  : std_logic_vector (15 downto 0);
	signal RAM_DOPB : std_logic_vector (1 downto 0);
	signal RAM_DIPB : std_logic_vector (1 downto 0);
	signal RAM_WEB : std_logic_vector (1 downto 0) := (others => '0');
	signal RAM_SSRB : std_logic := '0';
	signal RAM_ENB : std_logic := '1';

	--Transceiver control lines
	signal TxRx_A_tri : std_logic_vector (7 downto 0);
	signal TxRx_D_tri : std_logic_vector (7 downto 0);
	signal TxRx_Q : std_logic_vector (7 downto 0);
	signal TxRx_Rd_tri : std_logic;	-- '1' => read, '0' => write
	signal TxRx_Go : std_logic := '0';	-- starts a new transaction
	signal TxRx_Done : std_logic;	-- returned when transaction is finished

	-- ResetHard control lines
	signal ResetHard_Go : std_logic := '0';
	signal ResetHard_Done : std_logic;
	signal DAC_Rst_Hard : std_logic;
	signal RAM_EN_ResH : std_logic;
	signal TxRx_Go_ResH : std_logic := '0';
	signal INT_Go_ResH : std_logic := '0';
	--signal Ser_Go_ResH : std_logic := '0';

	-- ResetSoft control lines
	signal ResetSoft_Go : std_logic := '0';
	signal ResetSoft_Done : std_logic;
	signal DAC_Rst_Soft : std_logic;
	signal RAM_EN_ResS : std_logic;
	signal TxRx_Go_ResS : std_logic := '0';
	--signal Ser_Go_ResS : std_logic := '0';

	-- Transmitter control lines
	signal Transmitter_Go : std_logic := '0';
	signal Transmitter_Done : std_logic;
	signal PktType_Xmit : std_logic_vector (7 downto 0) := (others => '0');
	signal RAM_EN_Xmit : std_logic;
	signal TxRx_Go_Xmit : std_logic := '0';
	signal INT_Go_Xmit : std_logic := '0';
	--signal Ser_Go_Xmit : std_logic := '0';

	-- Receiver control lines
	signal Receiver_Go : std_logic := '0';
	signal Receiver_Done : std_logic;
	signal PktType_Rcev : std_logic_vector (7 downto 0);
	signal RAM_EN_Rcev : std_logic;
	signal TxRx_Go_Rcev : std_logic := '0';
	--signal Ser_Go_Rcev : std_logic := '0';

	-- Querier control lines
	signal Querier_Go : std_logic := '0';
	signal Querier_Done : std_logic;
	signal RAM_EN_Quer : std_logic;
	--signal Ser_Go_Quer : std_logic := '0';

	-- Interrupt catcher control lines
	signal INT_Go : std_logic := '0';
	signal INT_Done : std_logic;
	signal INT_Mask_tri : std_logic_vector (15 downto 0);
	signal INT_Found : std_logic_vector (15 downto 0);
	signal TxRx_Go_INT : std_logic := '0';
	--signal Ser_Go_INT : std_logic := '0';

	-- DAC_writer control lines
	signal DAC_Go : std_logic := '0';
	signal DAC_Done : std_logic;
	signal RAM_EN_DAC : std_logic;
	--signal Ser_Go_DAC : std_logic := '0';

	-- DAC_controller control lines
	signal DAC_Cycle_Go : std_logic := '0';
	signal DAC_Cycle_Done : std_logic;
	signal DAC_Cycle_Addr : std_logic_vector (4 downto 0);
	signal DAC_Cycle_Code : std_logic_vector (13 downto 0);

	-- Serial output control lines
	--signal Ser_Go : std_logic := '0';
	--signal Ser_Done : std_logic;
	--signal Ser_D_tri : std_logic_vector (7 downto 0);
	--signal Ser_Q : std_logic;
begin
	LocStamp8bit <= "100" & LocStamp;
	StateCode <= "000" when State = HARD_RESET else
	             "001" when State = SOFT_RESET else
	             "010" when State = PACKET_WAIT else
	             "011" when State = PACKET_RECEIVED else
	             "100" when State = QUERY_INPUTS else
	             "101" when State = REPORT_STATUS else
	             "110" when State = PROGRAM_DAC else
	             "111" when State = REPORT_DAC_VALUES;

	-----------------------------------------------------------------
	-- Internal clock, driven from external CMOS clock pin (ExtClk)
	-- buffered and conditioned by the general-purpose DCM primitive
	-----------------------------------------------------------------
	IBUFG_inst : IBUFG
	port map ( O => DCM_CLKIN, 	-- drives DCM clock input
      		   I => ExtClk 		-- external clock input port
   	);

	DCM_SP_inst : DCM_SP
	generic map ( CLKDV_DIVIDE => 2.0,
		      CLKFX_DIVIDE => 8,
		      CLKFX_MULTIPLY => 2,
		      CLKIN_DIVIDE_BY_2 => FALSE,
		      CLKIN_PERIOD => 50.0,
		      CLKOUT_PHASE_SHIFT => "NONE",
		      CLK_FEEDBACK => "1X",
		      DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
		      DLL_FREQUENCY_MODE => "LOW",
		      DUTY_CYCLE_CORRECTION => TRUE,
		      PHASE_SHIFT => 0,
		      STARTUP_WAIT => FALSE )
	-- To use any of the unused outputs below, simply uncomment them
	-- and connect them to a new BUFG component to drive the new net.
	port map ( CLK0 => DCM_CLK0,     	-- 0 degree DCM CLK ouptput
		   --CLK180 => DCM_CLK180,	-- 180 degree DCM CLK output
		   --CLK270 => DCM_CLK270, 	-- 270 degree DCM CLK output
		   --CLK2X => DCM_CLK2X,   	-- 2X DCM CLK output
		   --CLK2X180 => DCM_CLK2X180, 	-- 2X, 180 degree DCM CLK out
		   --CLK90 => DCM_CLK90,   	-- 90 degree DCM CLK output
		   CLKDV => DCM_CLKDV,   	-- Divided DCM CLK out (CLKDV_DIVIDE)
		   --CLKFX => DCM_CLKFX,   	-- DCM CLK synthesis out (M/D)
		   --CLKFX180 => DCM_CLKFX180, 	-- 180 degree CLK synthesis out
		   LOCKED => DCM_LOCKED, 	-- DCM LOCK status output
		   --PSDONE => DCM_PSDONE, 	-- Dynamic phase adjust done output
		   --STATUS => DCM_STATUS, 	-- 8-bit DCM status bits output
		   CLKFB => DCM_CLKFB,   	-- DCM clock feedback
		   CLKIN => DCM_CLKIN,  	-- Clock input (from IBUFG, BUFG or DCM)
		   --PSCLK => DCM_PSCLK,   	-- Dynamic phase adjust clock input
		   --PSEN => DCM_PSEN,     	-- Dynamic phase adjust enable input
		   --PSINCDEC => DCM_PSINCDEC,	-- Dynamic phase adjust increment/decrement
		   RST => Rst        		-- DCM asynchronous reset input
	);

	BUFG_inst_1 : BUFG
	port map ( O => Clk,		-- drives the main Clk for the design
      		   I => DCM_CLK0	-- unshifted clock from DCM
	);
	DCM_CLKFB <= DCM_CLK0;
	DCM_stable <= DCM_LOCKED;

	BUFG_inst_2 : BUFG
	port map ( O => Clk2,		-- drives the SPI_CLK for the design
      		   I => DCM_CLKDV	-- unshifted clock from DCM
	);

	------------------
	-- External reset
	------------------
	STARTUP_SPARTAN3A_inst : STARTUP_SPARTAN3A
	port map (--CLK => Clk, -- Clock input for start-up sequence
		  --GTS => Rst, -- Global 3-state input (GTS cannot be used for the port name)
		  GSR => Rst -- Global Set/Reset input (GSR cannot be used for the port name)
	);

	Rst <= not ExtRst_low;

	--------------------------------------------------------
	-- RAM block for register banks
	-- Here I chose the dual-ported component only because
	-- there are no extra resources required over the
	-- single-ported version.  The second port is useful
	-- for snooping on the RAM during simulation, but is
	-- not used by actual device components.
	--------------------------------------------------------
	RAMB16BWE_S18_S18_inst : RAMB16BWE_S18_S18
	generic map ( INIT_A => X"00000", 	--  Value of output RAM registers at startup
		      INIT_B => X"00000",
		      SRVAL_A => X"00000", 	--  Output value upon SSR assertion
		      SRVAL_B => X"00000",
		      WRITE_MODE_A => "WRITE_FIRST",
		      WRITE_MODE_B => "WRITE_FIRST",
		      -- Address 0 to 255
		      INIT_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
		      -- Address 256 to 511
		      INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
		      -- Address 512 to 767
		      INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
		      -- Address 768 to 1023
		      INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
		      -- The next set of INITP_xx are for the parity bits
		      -- Address 0 to 255
		      INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      -- Address 256 to 511
		      INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      -- Address 512 to 767
		      INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      -- Address 768 to 1023
		      INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
		      INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
	port map ( CLKA => Clk,			-- 1-bit Clock
		   DOA => RAM_DO,		-- 16-bit Data Output
		   DOPA => RAM_DOP,		-- 2-bit parity Output
		   ADDRA => RAM_ADDR_tri,	-- 10-bit Address Input
		   DIA => RAM_DI_tri, 		-- 16-bit Data Input
		   DIPA => RAM_DIP,		-- 2-bit parity Input
		   ENA => RAM_EN,		-- 1-bit RAM Enable Input
		   SSRA => RAM_SSR,		-- 1-bit Synchronous Set/Reset Input
		   WEA => RAM_WE_tri,		-- 2-bit Write Enable Input
		   -- Second port lines are not wired to components but
		   -- signals are connected for snooping during simulation.
		   CLKB => Clk,
		   DOB => RAM_DOB,
		   DOPB => RAM_DOPB,
		   ADDRB => RAM_ADDRB,
		   DIB => RAM_DIB,
		   DIPB => RAM_DIPB,
		   ENB => RAM_ENB,
		   SSRB => RAM_SSRB,
		   WEB => RAM_WEB
	);

	RAM_DIP <= "00";
	RAM_SSR <= '0';
	RAM_EN <= RAM_EN_ResH or RAM_EN_ResS or
		  RAM_EN_Xmit or RAM_EN_Rcev or
		  RAM_EN_Quer or RAM_EN_DAC;

	----------------------------------------------------------------------
	-- Allocation of registers in the 1kB RAM address space is as follows.
	-- All registers are 16 bits (18 including parity) addressed at once.
	-- 	Temperature value (2 bytes)	 	0x0
	-- 	MAC addresses (2 x 6 bytes)		0x10 - 0x15
	-- 	ADC values (16 x 2 bytes)		0x20 - 0x2f
	-- 	DAC values (32 x 2 bytes)		0x40 - 0x5f
	----------------------------------------------------------------------

	------------------------
	-- ResetHard sequencer
	------------------------
	ResetHard_inst: ResetHard
        port map ( Clk => Clk,
		   Go => ResetHard_Go,
		   Done => ResetHard_Done,
		   Eth_Rst_low => Eth_Rst_low,
		   Eth_INT_low => Eth_INT_low,
		   DAC_Rst => DAC_Rst_Hard,
		   RAM_EN => RAM_EN_ResH,
		   RAM_ADDR_tri => RAM_ADDR_tri,
		   RAM_WE_tri => RAM_WE_tri,
		   RAM_DI_tri => RAM_DI_tri,
		   RAM_DO => RAM_DO,
		   TxRx_Go => TxRx_Go_ResH,
		   TxRx_A_tri => TxRx_A_tri,
		   TxRx_D_tri => TxRx_D_tri,
		   TxRx_Rd_tri => TxRx_Rd_tri,
		   TxRx_Q => TxRx_Q,
		   TxRx_Done => TxRx_Done,
		   INT_Go => INT_Go_ResH,
		   INT_Mask_tri => INT_Mask_tri,
		   INT_Found => INT_Found,
		   INT_Done => INT_Done
		   --Ser_Go => Ser_Go_ResH,
		   --Ser_D_tri => Ser_D_tri,
		   --Ser_Done => Ser_Done
		   --Debug => Debug_port
	);

	------------------------
	-- ResetSoft sequencer
	------------------------
	ResetSoft_inst: ResetSoft
        port map ( Clk => Clk,
		   Go => ResetSoft_Go,
		   Done => ResetSoft_Done,
		   DAC_Rst => DAC_Rst_Soft,
		   RAM_EN => RAM_EN_ResS,
		   RAM_ADDR_tri => RAM_ADDR_tri,
		   RAM_WE_tri => RAM_WE_tri,
		   RAM_DI_tri => RAM_DI_tri,
		   RAM_DO => RAM_DO,
		   TxRx_Go => TxRx_Go_ResS,
		   TxRx_Rd_tri => TxRx_Rd_tri,
		   TxRx_A_tri => TxRx_A_tri,
		   TxRx_D_tri => TxRx_D_tri,
		   TxRx_Q => TxRx_Q,
		   TxRx_Done => TxRx_Done
		   --Ser_Go => Ser_Go_ResS,
		   --Ser_D_tri => Ser_D_tri,
		   --Ser_Done => Ser_Done,
		   --Debug => Debug_port
	);

	-------------------------------------------
	-- Sequencer for sending ethernet packets
	-------------------------------------------
	Transmitter_inst: Transmitter
        port map ( Clk => Clk,
		   Go => Transmitter_Go,
		   Done => Transmitter_Done,
		   LocStamp => LocStamp8bit,
		   PktType => PktType_Xmit,
		   RAM_EN => RAM_EN_Xmit,
		   RAM_ADDR_tri => RAM_ADDR_tri,
		   RAM_WE_tri => RAM_WE_tri,
		   RAM_DI_tri => RAM_DI_tri,
		   RAM_DO => RAM_DO,
		   TxRx_Go => TxRx_Go_Xmit,
		   TxRx_Rd_tri => TxRx_Rd_tri,
		   TxRx_A_tri => TxRx_A_tri,
		   TxRx_D_tri => TxRx_D_tri,
		   TxRx_Q => TxRx_Q,
		   TxRx_Done => TxRx_Done,
		   INT_Go => INT_Go_Xmit,
		   INT_Mask_tri => INT_Mask_tri,
		   INT_Found => INT_Found,
		   INT_Done => INT_Done
		   --Ser_Go => Ser_Go_Xmit,
		   --Ser_D_tri => Ser_D_tri,
		   --Ser_Done => Ser_Done,
		   --Debug => Debug_port
	);

	----------------------------------------
	-- Querier reads fresh values from the
	-- ADC and temperature sensors
	----------------------------------------
	Querier_inst: Querier
        port map ( Clk => Clk,
		   Go => Querier_Go,
		   Done => Querier_Done,
		   SPI_SCLK => Clk2,
		   SPI_T_CE =>  SPI_T_CE,
		   SPI_A_CS_low => SPI_A_CS_low,
		   SPI_SDI_tri => SPI_SDI_tri,
		   SPI_SDO => SPI_SDO,
		   RAM_EN => RAM_EN_Quer,
		   RAM_ADDR_tri => RAM_ADDR_tri,
		   RAM_WE_tri => RAM_WE_tri,
		   RAM_DI_tri => RAM_DI_tri,
		   RAM_DO => RAM_DO
		   --Ser_Go => Ser_Go_Quer,
		   --Ser_D_tri => Ser_D_tri,
		   --Ser_Done => Ser_Done
		   --Debug => Debug_port
	);
	SPI_SCLK <= Clk2;

	-----------------------------------------------
	-- Receiver decodes incoming ethernet packets
	-----------------------------------------------
	Receiver_inst: Receiver
        port map ( Clk => Clk,
		   Go => Receiver_Go,
		   Done => Receiver_Done,
		   LocStamp => LocStamp8bit,
		   PktType => PktType_Rcev,
		   RAM_EN => RAM_EN_Rcev,
		   RAM_ADDR_tri => RAM_ADDR_tri,
		   RAM_WE_tri => RAM_WE_tri,
		   RAM_DI_tri => RAM_DI_tri,
		   RAM_DO => RAM_DO,
		   TxRx_Go => TxRx_Go_Rcev,
		   TxRx_Rd_tri => TxRx_Rd_tri,
		   TxRx_A_tri => TxRx_A_tri,
		   TxRx_D_tri => TxRx_D_tri,
		   TxRx_Q => TxRx_Q,
		   TxRx_Done => TxRx_Done
		   --Ser_Go => Ser_Go_Rcev,
		   --Ser_D_tri => Ser_D_tri,
		   --Ser_Done => Ser_Done
		   --Debug => Debug_port
	);

	--------------------------------------------------
	-- DAC_writer pushes DAC values from FPGA memory
	-- to the DAC chip over the MuxIntel parallel bus.
	--------------------------------------------------
	DAC_writer_inst: DAC_writer
        port map ( Clk => Clk,
		   Go => DAC_Go,
		   Done => DAC_Done,
		   RAM_EN => RAM_EN_DAC,
		   RAM_ADDR_tri => RAM_ADDR_tri,
		   RAM_WE_tri => RAM_WE_tri,
		   RAM_DI_tri => RAM_DI_tri,
		   RAM_DO => RAM_DO,
		   DAC_control_Go => DAC_Cycle_Go,
		   DAC_control_Done => DAC_Cycle_Done,
		   DAC_Addr => DAC_Cycle_Addr,
		   DAC_Code => DAC_Cycle_Code
		   --Ser_Go => Ser_Go_DAC,
		   --Ser_D_tri => Ser_D_tri,
		   --Ser_Done => Ser_Done
		   --Debug => Debug_port
	);

	----------------------------------------------
	-- DAC_controller is the sequencer for the
	-- serial bus connecting to the DAC.
	----------------------------------------------
	DAC_controller_inst: DAC_controller
	port map ( Clk => Clk,
		   Go => DAC_Cycle_Go,
		   Done => DAC_Cycle_Done,
		   Addr => DAC_Cycle_Addr,
		   Code => DAC_Cycle_Code,
		   SCLK => Clk,
		   SYNC_low => DAC_SYNC_low,
		   DIN => DAC_DIN
	);

	DAC_RESET_low <= not (DAC_Rst_Hard or DAC_Rst_Soft);
	DAC_SCLK <= Clk;

	----------------------------------------------
	-- Ethernet controller interrupt catcher
	----------------------------------------------
	INTCatcher_inst: INTCatcher
	port map ( Clk => Clk,
		   Go => INT_Go,
		   Done => INT_Done,
		   INT_low => Eth_INT_low,
		   Mask => INT_Mask_tri,
		   Found => INT_Found,
		   TxRx_Go => TxRx_Go_INT,
           	   TxRx_Rd_tri => TxRx_Rd_tri,
           	   TxRx_A_tri => TxRx_A_tri,
           	   TxRx_D_tri => TxRx_D_tri,
		   TxRx_Q => TxRx_Q,
		   TxRx_Done => TxRx_Done
		   --Ser_Go => Ser_Go_INT,
		   --Ser_D_tri => Ser_D_tri,
		   --Ser_Done => Ser_Done
		   --Debug => Debug_port
	);

	INT_Go <= INT_Go_ResH or INT_Go_Xmit or INT_Go_reg;
	INT_Mask_tri <= X"1001" when (INT_Go_reg = '1') else (others => 'Z');

	-------------------------------------------------------
	-- Transceiver manages communication with the ethernet
	-- controller over the MuxIntel parallel bus.
	-------------------------------------------------------
	Transceiver_inst: Transceiver
	port map ( Clk => Clk,
		   Go => TxRx_Go,
		   Done => TxRx_Done,
		   Rd => TxRx_Rd_tri,
		   A => TxRx_A_tri,
		   D => TxRx_D_tri,
		   Q => TxRx_Q,
		   -- MuxIntel parallel bus lines
		   ALE => Eth_ALE,
		   AD => Eth_AD,
		   RD_low => Eth_RD_low,
		   WR_low => Eth_WR_low,
		   CS_low => Eth_CS_low
	);

	TxRx_Go <= TxRx_Go_ResH or TxRx_Go_ResS or 
		   TxRx_Go_Xmit or TxRx_Go_Rcev or TxRx_Go_INT;
	Eth_CLK <= Clk;

	--------------------------
	-- Serial output control 
	--------------------------
	--SerialOutFIFO_inst: SerialOutFIFO
	--port map ( Clk => Clk,
	--	   Go => Ser_Go,
	--	   Done => Ser_Done,
	--	   D => Ser_D_tri,
	--	   Q => Ser_Q
	--);

	--Ser_Go <= Ser_Go_ResH or Ser_Go_ResS or
	--	  Ser_Go_Xmit or Ser_Go_Rcev or
	--	  Ser_Go_Quer or Ser_Go_INT  or
	--	  Ser_Go_DAC;
	--Serial_port <= Ser_Q;

	-- Set debug pins if not in use
	Serial_port <= '1';
	Debug_port <= '1';

	---------------------------------
	-- State machine implementation
	---------------------------------
	State_Machine : process (Clk)
				 
	begin
		if rising_edge(Clk) then
			State <= State;
			ResetHard_Go <= '0';
			ResetSoft_Go <= '0';
			Receiver_Go <= '0';
			Querier_Go <= '0';
			Transmitter_Go <= '0';
			INT_Go_reg <= '0';
			DAC_Go <= '0';

			case State is

			    when HARD_RESET =>
				ResetHard_Go <= DCM_LOCKED and not ResetHard_Done;
				if (ResetHard_Done = '1') then
					State <= QUERY_INPUTS;
				end if;

			    when SOFT_RESET =>
				ResetSoft_Go <= DCM_LOCKED and not ResetSoft_Done;
				if (ResetSoft_Done = '1') then
					State <= QUERY_INPUTS;
				end if;

			    when PACKET_WAIT =>
				INT_Go_reg <= DCM_LOCKED and not INT_Done;
				if (INT_Done = '1') then
					if (INT_Found(0) = '1') then
						State <= PACKET_RECEIVED;
					else
						State <= HARD_RESET;
					end if;
				end if;

			    when PACKET_RECEIVED =>
				Receiver_Go <= DCM_LOCKED and not Receiver_Done;
				if (Receiver_Done = '1') then
					case (PktType_Rcev) is
					    when X"52" =>
						State <= HARD_RESET;
					    when X"D2" =>
						State <= SOFT_RESET;
					    when X"51" =>
						State <= QUERY_INPUTS;
					    when X"50" =>
						State <= PROGRAM_DAC;
					    when others =>
						State <= PACKET_WAIT;
					end case;
				end if;

			    when QUERY_INPUTS =>
				Querier_Go <= DCM_LOCKED and not Querier_Done;
				if (Querier_Done = '1') then
					State <= REPORT_STATUS;
				end if;

			    when REPORT_STATUS =>
				PktType_Xmit <= X"53";
				Transmitter_Go <= DCM_LOCKED and not Transmitter_Done;
				if (Transmitter_Done = '1') then
					State <= PACKET_WAIT;
				end if;

			    when PROGRAM_DAC =>
				DAC_Go <= DCM_LOCKED and not DAC_Done;
				if (DAC_Done = '1') then
					State <= REPORT_DAC_VALUES;
				end if;

			    when REPORT_DAC_VALUES =>
				PktType_Xmit <= X"44";
				Transmitter_Go <= DCM_LOCKED and not Transmitter_Done;
				if (Transmitter_Done = '1') then
					State <= PACKET_WAIT;
				end if;
			end case;
		else
			ResetHard_Go <= ResetHard_Go;
			ResetSoft_Go <= ResetSoft_Go;
			Receiver_Go <= Receiver_Go;
			Querier_Go <= Querier_Go;
			Transmitter_Go <= Transmitter_Go;
			PktType_Xmit <= PktType_Xmit;
			INT_Go_reg <= INT_Go_reg;
			DAC_Go <= DAC_Go;
			State <= State;
		end if;
	end process;

end behavioral;
