----------------------------------------------------------------------------------
-- Company:  University of Connecticut
-- Engineer: Igor Senderovich
-- 
-- Create Date:    16:06:03 12/28/2007 
-- Design Name:    Total FPGA testing module
-- Module Name:    FPGA_ctrl - Behavioral 
-- Description: 
--
------------------------------------------------------------------------------
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;

entity FPGA_ctrl is
    Port ( fClk : in  STD_LOGIC;
	   fClk_out : out STD_LOGIC;
	   Rst : in STD_LOGIC;
	   Eth_iRst : inout STD_LOGIC;
	   Eth_iINT : in STD_LOGIC;
	  
	   LocStamp : in STD_LOGIC_VECTOR (4 downto 0);
	   state_Qout  : out STD_LOGIC_VECTOR (2 downto 0);

	-- SPI bus (with ADC and Temp sensors) lines
	   SPI_SCLK 	: out STD_LOGIC;
	   SPI_T_CE	: out STD_LOGIC;
	   SPI_A_iCS	: out STD_LOGIC;
	   SPI_SDI	: out STD_LOGIC;
	   SPI_SDO	: in STD_LOGIC;
	  
	-- DAC lines -----------------------------
	   DAC_Clk 	: out STD_LOGIC;
	   DAC_iRst	: out STD_LOGIC;
	   DAC_serISync : out STD_LOGIC; 
	   DAC_serData  : out STD_LOGIC;

	-- MuxIntel lines ------------------------
	   ALE : out STD_LOGIC;
	   AD  : inout STD_LOGIC_VECTOR (7 downto 0);
	   iRD : out STD_LOGIC;
	   iWR : out STD_LOGIC;
	   iCS : out STD_LOGIC;

	  --dbShort : in STD_LOGIC; --debug pin to short out waiting periods

	   dbInfoStart : out STD_LOGIC;
	   dbInfoStream1 : out STD_LOGIC;
	   dbInfoStream2 : out STD_LOGIC;
	  
	   db_serial : out STD_LOGIC
	);
end FPGA_ctrl;

architecture Behavioral of FPGA_ctrl is

	signal Clk : STD_LOGIC;  -- the main FPGA ("slow") clock subdivided from Eth. Ctrl's fClk by the Transceiver
	signal iRst, Rst_Quer : STD_LOGIC;
	signal LocStamp8bit : STD_LOGIC_VECTOR (7 downto 0);

	signal DAC_iRst_int, DACregs_Rst : STD_LOGIC;
	signal DAC_Done,DAC_iGo : STD_LOGIC;
	signal DAC_Addr : STD_LOGIC_VECTOR (4 downto 0);
	signal DAC_D  : STD_LOGIC_VECTOR (13 downto 0);

	-- Timeout (TO) signals
	signal DBbyte : STD_LOGIC_VECTOR (7 downto 0);

	--Transceiver control lines
	signal TxRx_A, TxRx_D, TxRx_Q : STD_LOGIC_VECTOR (7 downto 0);
	signal TxRx_Done, TxRx_RiW, TxRx_Go : STD_LOGIC;
	signal TxRx_Go_u1, TxRx_Go_ResH, TxRx_Go_Xmit, TxRx_Go_ResS : STD_LOGIC;
	signal TxRx_Go_uINT, TxRx_Go_Idl, TxRx_Go_uRd, TxRx_Go_uProg : STD_LOGIC;

	--State Register lines
	signal state_D, state_Q : STD_LOGIC_VECTOR (2 downto 0);
	signal state_En, state_En_u1, state_En_ResH, state_En_ResS, state_En_uProg : STD_LOGIC;
	signal state_En_Xmit, state_En_Quer, state_En_Idl, state_En_uRd : STD_LOGIC;

	--Lines for DAC, ADC and Temp data storage registers
	signal TempReg_En, ADCregs_En, DACregs_En : STD_LOGIC;
	signal TempReg_D : STD_LOGIC_VECTOR (9 downto 0);
	signal ADCregs_A : STD_LOGIC_VECTOR (2 downto 0);
	signal ADCregs_D : STD_LOGIC_VECTOR (11 downto 0);
	signal DACregs_Q, ADCregs_Q, TempReg_Q : STD_LOGIC_VECTOR (15 downto 0);

	--MAC address storage register lines
	signal MACregs_A : STD_LOGIC_VECTOR (3 downto 0);
	signal MACregs_D, MACregs_Q : STD_LOGIC_VECTOR (7 downto 0);
	signal MACregs_En, MACregs_En_ResH, MACregs_En_ResS, MACregsRst : STD_LOGIC;

	--SPI-related signals
--	signal SPI_iRst_onreq	: STD_LOGIC;
--	signal SPI_iRst	: STD_LOGIC;
--	signal SPI_Done	: STD_LOGIC;
--	signal SPI_Temp_Q	: STD_LOGIC_VECTOR (9 downto 0);
--	signal SPI_ADC_Q	: STD_LOGIC_VECTOR (11 downto 0);
--	signal SPI_ADC_A	: STD_LOGIC_VECTOR (2 downto 0);
--	signal SPI_Go	: STD_LOGIC;
--	signal SPI_T_iA	: STD_LOGIC;
--	signal SPI_ADC_Aout : STD_LOGIC_VECTOR (2 downto 0);
	
	-- Interrupt catcher signals
	signal INT_Done, INT_Go, INT_Go_ResH, INT_Go_Xmit, INT_Go_Idl	: STD_LOGIC;
	signal INT_Mask, INT_Found	: STD_LOGIC_VECTOR (7 downto 0);
	--signal INT_Go_Xmit	: STD_LOGIC;

	signal GSR_PORT, GTS_PORT, Rst_int  : STD_LOGIC;-- Reset signals
	
	-- Serial debug lines
	signal ser_Go, ser_Go_uINT, ser_Go_ResH, ser_Go_uResS : STD_LOGIC;
	signal ser_Go_Quer, ser_Go_uRd, ser_Go_Xmit, ser_Go_ResS: STD_LOGIC;
	signal ser_D : STD_LOGIC_VECTOR (7 downto 0);

	-- Debug signals
	signal dbInfo : STD_LOGIC_VECTOR (15 downto 0);
	signal EthAccessCnt  : STD_LOGIC_VECTOR (5 downto 0);
	signal dbInfoCnt : STD_LOGIC_VECTOR (3 downto 0);
	signal dbInfoCnt_int : integer range 15 downto 0;
	signal Cnt : STD_LOGIC_VECTOR (7 downto 0);

	signal dbShort_int, db_serial_int :STD_LOGIC;
	signal ser_Go_cnt : STD_LOGIC_VECTOR (1 downto 0);
	signal dbtmp1, Go_cnt, SPI_SDI_int : STD_LOGIC;
	signal StateChCnt : STD_LOGIC_VECTOR (7 downto 0);
	signal Reset_hard_db1, Reset_hard_db2, Transmitter_db : STD_LOGIC;
	signal RstCnt : STD_LOGIC_VECTOR (1 downto 0);
	
	signal DACtestAddr : STD_LOGIC_VECTOR (4 downto 0);

	component ConfigParam is
	    Port ( DAC_Qmax : out  STD_LOGIC_VECTOR (13 downto 0);
		   DAC_Q_GainModeChan : out  STD_LOGIC_VECTOR (13 downto 0);
		   dbShort  : out  STD_LOGIC);
	end component;
	
	signal DAC_Qmax : STD_LOGIC_VECTOR (13 downto 0);
	signal DAC_Q_GainModeChan : STD_LOGIC_VECTOR (13 downto 0);
	signal dbShort : STD_LOGIC;

begin

	uParam: ConfigParam port map (DAC_Qmax, DAC_Q_GainModeChan, dbShort);

	fClk_out <=  fClk;
	LocStamp8bit <= "100" & LocStamp;
	iCS <= '0'; -- Eth Ctrl chip select pin permanently down.

	-- Reset signal routing -------------------------------------------------------
	--Rst_int  <= '1' when (GSR_PORT='1' or Rst='1') else '0';
	iRst <= not Rst_int;
	prolong_rst : process (fClk, Rst, GSR_PORT, RstCnt)
	begin
		if GSR_PORT='1' or Rst='1' then
			RstCnt <= "00";
		else
			if rising_edge(fClk) and RstCnt/="11" then
				RstCnt <= RstCnt + "01";
			else
				RstCnt <= RstCnt;
			end if;
		end if;
	end process;
	Rst_int <= '1' when (GSR_PORT='1' or Rst='1' or RstCnt/="11") else '0';
	TxRx_Go <= '0' when GSR_PORT='1' else 'Z';
	
	-- Startup primitive for GSR, GTS or startup sequence ctrl.
	STARTUP_SPARTAN3A_inst : STARTUP_SPARTAN3A
	port map (CLK => CLK, -- Clock input for start-up sequence
		  GSR => GSR_PORT, -- Global Set/Reset input (GSR cannot be used for the port name)
		  GTS => GTS_PORT  -- Global 3-state input (GTS cannot be used for the port name)
	);
	-----------------------------------------------------------------------------

	-- Registers ----------------------------------
	state_Qout <= state_Q;
	MACregsRst <= not Eth_iRst or Rst_int;
	r1: stateReg port map (Clk, Rst_int, state_En, state_D, state_Q);
	r2: MACregs  port map (Clk, MACregsRst, MACregs_En, MACregs_A, MACregs_D, MACregs_Q);
	r6: DACregs  port map (Clk, DACregs_Rst, DACregs_En, DAC_Addr, DAC_D, DACregs_Q);

	r3: TempReg port map (Clk, Rst_int, TempReg_En, TempReg_D, TempReg_Q);
	r5: ADCregs  port map (Clk, Rst_int, ADCregs_En, ADCregs_A, ADCregs_D, ADCregs_Q);
	------------------------------------------------
	
	
	uINT: INTCatcher port map (Clk, Rst, Eth_iINT, INT_Go, INT_Mask, INT_Found, INT_Done,
				   TxRx_Go_uINT, TxRx_A, TxRx_RiW, TxRx_Q, TxRx_Done,
				   ser_Go_uINT, ser_D);

	u1: Transceiver port map (fClk, Clk, Rst_int, ALE, AD, iRD, iWR,
				  TxRx_Go, TxRx_RiW, TxRx_A, TxRx_D, TxRx_Q, TxRx_Done);

	-- Serial output control ---------------------------------------------\
	ser_Go <= ser_Go_Xmit or --ser_Go_Quer or
		  or ser_Go_uINT
		  or state_En or ser_Go_ResH
		  or ser_Go_uRd or ser_Go_ResS
		  --or ADCregs_En or MACregs_En
                  ;
	ser_D <= ("00100" & state_D) when state_En='1' else 
		 --ADCregs_Q(7 downto 0) when ADCregs_En='1' else
		 --'1' & StateChCnt(6 downto 0) when state_En='1' else
		 --"0011" & MACregs_A when MACregs_En='1' else 
		 "ZZZZZZZZ";
	db0: SerialOutFIFO port map (Clk, Rst, ser_Go, ser_D, db_serial);
	----------------------------------------------------------------------/


	INT_Go <= INT_go_ResH or INT_go_Xmit or INT_Go_Idl;
	TxRx_Go <= TxRx_Go_uINT or TxRx_Go_ResH or TxRx_Go_ResS
                   or TxRx_Go_Xmit or TxRx_Go_uRd or TxRx_Go_uProg;
	state_En <= state_En_ResH or state_En_ResS or state_En_Xmit or state_En_Quer or 
		    state_En_uRd or state_En_uProg or state_En_Idl;
	MACregs_En <= MACregs_En_ResH or MACregs_En_ResS;
		
	dbShort_int <= dbShort;
	uResH: Reset_hard
        port map (Clk, Rst_int, Eth_iRst, state_En_ResH, state_D, state_Q,
		  MACregs_En_ResH, MACregs_A, MACregs_D,
		  TxRx_Go_ResH, TxRx_A, TxRx_D, TxRx_RiW, TxRx_Q, TxRx_Done,
		  INT_Go_ResH, INT_Mask, INT_Found, INT_Done,
		  dbShort_int, ser_Go_ResH, ser_D, Reset_hard_db1,Reset_hard_db2);
								
	uResS: Reset_soft
        port map (Clk, Rst_int, DAC_iRst_int,
	 	  state_En_ResS, state_D, state_Q,
		  MACregs_En_ResS, MACregs_A, MACregs_D, DBbyte,
		  TxRx_Go_ResS, TxRx_A, TxRx_D, TxRx_RiW, TxRx_Q, TxRx_Done,
		  ser_Go_ResS, ser_D);

	uXmit: Transmitter
        port map (Clk, Rst_int, state_En_Xmit, state_D, state_Q, LocStamp8bit,-- PktNum,
		  MACregs_A, MACregs_Q, TempReg_Q, 
		  ADCRegs_A, ADCRegs_Q, DAC_Addr, DACRegs_Q,
		  TxRx_Go_Xmit, TxRx_RiW, TxRx_A, TxRx_D, TxRx_Q, TxRx_Done,
		  INT_Go_Xmit, INT_Mask, INT_Found, INT_Done,
		  ser_Go_Xmit, ser_D);
	
									
	uIdl: Idler_ctrl
        port map (Clk, Rst_int, state_En_Idl, state_D, state_Q,
		  INT_Go_Idl, INT_Mask, INT_Found, INT_Done --,dbInfoStream2
                 );
	
	Rst_Quer <= '1' when state_Q="001" else Rst_int;
	uQuer: Querier
        port map(Clk, Rst_quer, SPI_SCLK, SPI_T_CE, SPI_A_iCS, SPI_SDI, SPI_SDO,
		 ADCregs_En, ADCregs_A, ADCregs_D, TempReg_En, TempReg_D,
		 state_En_Quer, state_D, state_Q, ser_Go_Quer, ser_D,dbtmp1);

	uRd: Reader
        port map (Clk, Rst_int, state_En_uRd, state_D, state_Q, LocStamp8bit,
		  TxRx_Go_uRd, TxRx_A, TxRx_D, TxRx_RiW, TxRx_Q, TxRx_Done,
		  ser_Go_uRd, ser_D);

	uProg: Programmer_ctrl
        port map (Clk, Rst_int,
		  DAC_iGo, DACregs_En, DAC_Addr, DAC_D, DAC_Done,
		  DAC_Qmax, DAC_Q_GainModeChan,
		  state_En_uProg, state_D, state_Q,
		  TxRx_Go_uProg, TxRx_RiW, TxRx_A, TxRx_Q, TxRx_D, TxRx_Done
		  --,dbInfoStream1,dbInfoStream2
                 );
	dbInfoStream1 <= DAC_iGo;
	dbInfoStream2 <= DAC_Done;
	

	DAC_Clk <= Clk;
	u10: DAC_controller
	port map (Clk, iRst, DAC_iGo, DAC_Addr, DAC_D,
		  DAC_serISync, DAC_serData, -- DAC chip communication lines
		  DAC_Done);
	DACregs_Rst <= Rst or not DAC_iRst_int;
	DAC_iRst <= DAC_iRst_int;

	dbInfoStart <= '0' when state_Q="110" else '1';

--	DAC_iGo <= not state_En;
--	DAC_Addr <= DACtestAddr when state_En='1' else "ZZZZZ";
--	
--	DACtest : process (state_En)
--      begin
--		if Rst='1' then
-- 			DACtestAddr <= "00000";
--		else
--			if rising_edge(state_En) then
--				DACtestAddr <= DACtestAddr + "00001";
--				DAC_D <= DACtestAddr & "1" & X"FF";
--			else
--				DACtestAddr <= DACtestAddr; DAC_D <= DAC_D;
--			end if;				
--		end if;
--	end process;


-- Debugging Code


	--db_serial <= db_serial_int;

	--dbInfoStart <= '0' when state_Q="101" else '1';
	--dbInfoStream1 <= state_En;

----------------------------------------------------------------------------------------------------------------------------
-- count number of Eth IO operations (queries through transceiver)
--   EthAccessCounter : process (Rst_int, TxRx_Go, Clk)
--		begin
--		if (Rst_int='1') then
--			EthAccessCnt <= "000000";
--		else
--			if (falling_edge(Clk) and TxRx_Go='1') then
--				EthAccessCnt <= EthAccessCnt +  "000001";
--			else
--				 EthAccessCnt <= EthAccessCnt;
--			end if;
--		end if;
--	end process;
--	-------------------------------------------------------
	
--	uCheck: INTCatcher
--	port map (Clk, Rst, Eth_iINT, Transmitter_db, "1000", Done_TxINT,
--		  TxRx_Go9, TxRx_A, TxRx_RiW, TxRx_D, TxRx_Done,
--		  ser_En, ser_LogStr);
--	
--	db1: SerStringOut
--	port map (Clk, Rst, ser_En, ser_LogStr, db_serial,
--	          SerStringOut_db, dbInfoStream2);
--	ser_LogStr <= "Testing output: 1234567890$%-=";

--	dbInfoStart <= ser_Go;--TxRx_Go or TxRx_Done;
--	dbInfoStart <= Reset_hard_db1; -- when TxRx_Go='1' else '0';
--	dbInfoStream1 <= TxRx_Qreg(conv_integer(TxRx_Qreg_ind));

--	dbInfoStream1 <= Reset_hard_db1;
--	dbInfoStream2 <= Reset_hard_db2;


--	dbtmp1 <= '1' when (state_D="010" and state_En='1') else '0';
--	db5: DropOnSig port map (Rst, Transmitter_db, dbInfoStream1);
--	db6: DropOnSig port map (Rst, dbtmp1, dbInfoStream2);

--	dbtmp1 <= not Eth_iINT;
--	db7: CountEvents
--	port map (Clk, Rst, dbtmp1,dbInfoStream1,dbInfoStream2);

	
--	dbInfoStream1 <= Transmitter_db;--state_Q(0);
--	stateDB : process (Rst, state_En)
--	begin
--		if Rst='1' then
--			dbInfoStream1 <= '1';
--		else
--			if ser_Go='1' then
--				dbInfoStream1 <= '0';
--			end if;
--		end if;
--	end process;
--	
--	dbInfoStart <= SerStringOut_db;
--	stateDB2 : process (Rst, SerStringOut_db)
--	begin
--		if Rst='1' then
--			dbInfoStart <= '1';
--		else
--			if SerStringOut_db='1' then
--				dbInfoStart <= '0';
--			end if;
--		end if;
--	end process;

	
	
--	dbInfoStart  <= dbInfoCnt(0) and dbInfoCnt(1) and dbInfoCnt(2) and dbInfoCnt(3);

	-- register to remember data from TxRx
--	m1: pulser
--	port map (fClk,TxRx_Done, fTxRx_Done);
--	m0: Reg8bit
--	port map (fClk, Rst, fTxRx_Done, TxRx_Q, TxRx_Qreg);
--	ShiftOut_TxRxdata : process (Clk,TxRx_Done)
--	begin
--		if (Rst_int='1') then
--			TxRx_Qreg_ind<="000";
--		else
--			if falling_edge(fClk) then
--				if TxRx_Qreg_ind="000" then
--					TxRx_Qreg_ind <= TxRx_Qreg_ind - ("00" & TxRx_Done);
--				else
--					TxRx_Qreg_ind <= TxRx_Qreg_ind - ("00" &
--						(TxRx_Qreg_ind(0) or TxRx_Qreg_ind(1) or TxRx_Qreg_ind(2)));
--				end if;
--			else
--				TxRx_Qreg_ind <= TxRx_Qreg_ind; 
--			end if;
--		end if;
--	end process;
	

	
	-- shift out debug info stream
--	ShiftOut_dbStream : process (Rst_int,fClk,dbInfoCnt)
--		begin
--
--		if (Rst_int='1') then
--			dbInfoCnt <= "1111"; Cnt<=X"00";
--		else
--			if rising_edge(fClk) then
--				dbInfoCnt <= dbInfoCnt - "0001";
--				--if Cnt/=X"FF" then Cnt <= Cnt + X"01"; end if;	
--			else
--				 dbInfoCnt <= dbInfoCnt; 
--				--Cnt<=Cnt;
--			end if;
--		end if;
--
--		dbInfoCnt_int <= conv_integer(dbInfoCnt);
--		dbInfoStream1 <= dbInfo(dbInfoCnt_int);
--		if Cnt<X"FF" then
--			null;
--		else
--			dbInfoStart <= '0';
--		end if;
--	end process;
	
---------------------------------------------------	
	
	
	
	
--	Timeout : process (Clk,Rst,state_En)
--	begin 
--		if (state_En='1' or Rst='1') then
--			TOcount <= X"000000";
--			TOmult  <= "000000";
--		else
--			if rising_edge(Clk) then
--				if (TOmult=DBbyte) then
--					TOrst <= '1';
--					TOcount <= X"000000";
--					TOmult  <= "000000";
--				else
--					TOrst <= '0'; 
--					
--					-- if not timed out, count peacefully:
--					TOcount <= TOcount + 1;
--					if (TOcount(22 downto 18)="10011") then
--						TOmult <= TOmult + 1;
--					else
--						TOmult <= TOmult;
--					end if;
--				end if;
--				
--			else
--				TOcount <= TOcount;
--			end if;
--		end if;
--		
--	end process;
--	state_En_wTO <= '1' when (state_En='1' or TOrst='1') else '0';
--	state_D_wTO <= "000" when (TOrst='1') else state_D;

end Behavioral;
