----------------------------------------------------------------------------------
-- 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 sotrage 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);
           dbShort  : out  STD_LOGIC);
	end component;
	signal DAC_Qmax : STD_LOGIC_VECTOR (13 downto 0);
	signal dbShort : STD_LOGIC;
begin

	uParam: ConfigParam port map (DAC_Qmax, 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
					ser_Go_uINT or
					state_En or ser_Go_ResH or
					ser_Go_uRd or ser_Go_ResS
					--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,
									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
		--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;

