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 work;
use work.jem_pkg.all;


entity sum is
port(
	   CLK_in		:	in std_logic;
	   --vme signals 
	   VME_NDS0		:	in std_logic;	--positive logic
	   VME_NWRITE		:	in std_logic;	--positive logic
	   VME_ADDRESS	:	in std_logic_vector(23 downto 1);
	   VME_DATA	:	inout std_logic_vector(15 downto 0);
	   control_sum	:	inout std_logic_vector(11 downto 0);

		INPUT_prog : out std_logic_vector(3 downto 0);
--		INPUT_init : out std_logic_vector(3 downto 0);
		INPUT_cclk : out std_logic_vector(3 downto 0);
		INPUT_din  : out std_logic_vector(3 downto 0);
		INPUT_done : in std_logic_vector(3 downto 0);

		input_r_i : in std_logic_vector(intosum downto 0);		--ok
		input_r_o : out std_logic_vector(67 downto intosum+1);	  -- clk 1-7
		input_s_i : in std_logic_vector(intosum downto 0);		--ok
		input_s_o : out std_logic_vector(67 downto intosum+1);	  -- clk 1-7
		input_t_i : in std_logic_vector(intosum downto 0);		--ok
		input_t_o : out std_logic_vector(67 downto intosum+1);	  -- clk 1-7
		input_u_i : in std_logic_vector(intosum downto 0);		--ok
		input_u_o : out std_logic_vector(67 downto intosum+1);	  -- clk 1-7

		jconf_l : out std_logic_vector(5 downto 0);
		jconf_h : out std_logic_vector(7 downto 0);
		jconf_done : in std_logic;

		jet_l :  out std_logic_vector(82 downto 0);
		jet_h :  in std_logic_vector(38 downto 0);

		VME_DTACK : out std_logic;
		xtal40 : in std_logic;
		glink_clock : out std_logic;

		CLK_DES2: in std_logic;
		glink: inout std_logic_vector(25 downto 0);
		smm: out std_logic_vector(24 downto 0);
		TTC : inout std_logic_vector(56 downto 0)

	   );
END sum ;


architecture Behavioral of sum is

component CLKDLL
port(
	CLKIN	:	in std_logic;
	CLKFB	:	in std_logic;
	RST		:	in std_logic;
	CLK0		:	out std_logic;
	CLK90	:	out std_logic;
	CLK180	:	out std_logic;
	CLK270	:	out std_logic;
	CLK2X	:	out std_logic;
	CLKDV	:	out std_logic;
	LOCKED	:	out std_logic);
end component;

component BUFG
port(
	I	:	in std_logic;
	O	:	out std_logic);
end component;

component ofd
port(
	c	:	in std_logic;
	d	:	in std_logic;
	q	:	out std_logic);
end component;

component IBUFG
port(
	I	:	in std_logic;
	O	:	out std_logic);
end component;

component daq
generic(data_width   : integer := 50;	--	rtdp data width (either 50 or 88)
		frame_width	:	integer:=88;   -- frame length excl overall parity
		pipe_depth	:	integer:=latency_pipe-rtdp_latency;   -- latency buffer : shift register length 
--		pipe_depth	:	integer:=22;   -- for test purposes 
		latch_data	: boolean:=false);   
port(
	clk 	: in std_logic; 
	reset 	: in std_logic; -- reset fifo only
	rtd_data	 	: in std_logic_vector(data_width-1 downto 0); -- real-time data in
	read_request 	: in std_logic; -- latch piped data into fifo
	data_valid 		: out std_logic;
	daq_out 	: out std_logic; -- serial out to ROC
	full 	: out std_logic); -- buffer full, next read request might get ignored
end component;


component RAMB4_S16_S16
port(
	WEA	:	in std_logic;
	ENA	:	in std_logic;
	RSTA	:	in std_logic;
	CLKA	:	in std_logic;
	ADDRA: 	in std_logic_vector(7 downto 0);
	DIA	:	in std_logic_vector(15 downto 0);
	DOA	:	out std_logic_vector(15 downto 0);
	WEB	:	in std_logic;
	ENB	:	in std_logic;
	RSTB	:	in std_logic;
	CLKB	:	in std_logic;
	ADDRB:	in std_logic_vector(7 downto 0);
	DIB	:	in std_logic_vector(15 downto 0);
	DOB	:	out std_logic_vector(15 downto 0));
end component;

component counter
generic(
	WIDTH:	integer);
port(
	clk	:	in std_logic;	--clock signal
	en	:	in std_logic;	--enables counter
	rst	:	in std_logic;	--reset signal
	mask	:	in std_logic_vector(WIDTH-1 downto 0);	--max. count value
	tc	:	out std_logic;	--terminal count
	count	:	out std_logic_vector(WIDTH-1 downto 0));	--count
end component;


--constant g_bunch_clock_mode : boolean :=true;	  -- no elastic buffer, bunch clocked
constant g_bunch_clock_mode : boolean :=false;
signal g_new_module : std_logic;

--attribute equivalent_register_removal of input_r_o : signal is "no"; --not used. disable globally in project


--VME addresses not in package any longer
	constant as_version					:	std_logic_vector	:= x"00";
	constant as_status					:	std_logic_vector	:= x"02";
	constant as_control					:	std_logic_vector	:= x"04";
	constant as_pulse						:	std_logic_vector	:= x"06";
	constant as_cfg_mask					:	std_logic_vector	:= x"10";
	constant as_fpga_reset				:	std_logic_vector	:= x"12";
	constant as_fpga_done				:	std_logic_vector	:= x"14";
	constant as_ttc_command				:	std_logic_vector	:= x"40";
	constant as_ttc_status				:	std_logic_vector	:= x"42";
	constant as_ttc_control				:	std_logic_vector	:= x"44";
	constant as_glink_status			:	std_logic_vector	:= x"50";
	constant as_glink_control			:	std_logic_vector	:= x"52";
	constant as_read_request_delay	:	std_logic_vector	:= x"60";
	constant as_slice_cnt				:	std_logic_vector	:= x"62";
	constant as_bc_preset				:	std_logic_vector	:= x"64";

	constant as_spy_sl1					:	std_logic_vector	:= x"80";
	constant as_spy_sl2					:	std_logic_vector	:= x"84";
	constant as_spy_test					:	std_logic_vector	:= x"88";
	constant as_spy_exy					:	std_logic_vector	:= x"A0";
	constant as_spy_et					:	std_logic_vector	:= x"A4";

	constant as_latcorr					:	std_logic_vector	:= x"C0";

-- end of VME address definition

constant VME_inchips : integer :=4;


constant serwid : integer:=16;
constant ledon : integer :=10000000; --250ms
alias GEO_ADDR :std_logic_vector(3 downto 0) is control_sum(4 downto 1);
alias i2c_scl : std_logic is ttc(24);
alias i2c_sda : std_logic is ttc(25);
constant ttc_nreset	: integer:=21;
constant dtack_max : integer:=20; -- dtack timeout value

signal input_r_i_s,input_s_i_s,input_t_i_s,input_u_i_s :  std_logic_vector(intosum downto 0);	

signal rdo_bus_out : std_logic_vector(5 downto 0);
signal rdo_bus_in : std_logic_vector(4 downto 0);

signal GEO_ADDRs	: std_logic_vector(3 downto 0);
--alias vme_nds : std_logic is fcal(0);
--alias vme_brdsel  : std_logic is fcal(1);

--alias main_DLL : std_logic is JEN_WS;
signal main_dll_tmp,main_dll_tmp1 : std_logic;		
--CLK signals
signal TCLKIN_w,CLK_2,CLK_2g,FB_CLKIN_w,TCLK40 : std_logic;
signal QCLKIN_w,CLK_3g,CLK_3,QCLK40 : std_logic;
signal DLL_LOCK_QUARTZ,DLL_LOCK_BOARD : std_logic;
signal DLLRST, CONFIG_RST,INACTIVE :	std_logic;
signal clk90,clk90_tmp:	std_logic;
--vme signals
signal IDS0_tmp,IDS0,WRITE_EN: std_logic;
signal DATA_R_DAQ,DATA_R_JEN,DATA_R_INPUT : std_logic_vector (15 downto 0);
signal ISUB_ADDRESS,IREG_ADDRESS : integer;
--CONTROL_REG:
signal ICONTROL,ICONTROL_tmp,control_pulse,control_reg : std_logic_vector(15 downto 0);
signal GLOBAL_RESET : std_logic;
--InputFPGAs:
signal MUX_DATA,MUX_ADDR : std_logic_vector(11 downto 0);
signal s_ds_vector : std_logic_vector(11 downto 0);
signal i_ad,i_ce : std_logic;
signal ISTATUS,LOCK_LOSS_STATUS : std_logic_vector(15 downto 0);
signal a_ce_tmp,b_ce_tmp,c_ce_tmp,d_ce_tmp,e_ce_tmp,f_ce_tmp,g_ce_tmp,h_ce_tmp,v_ce_tmp,w_ce_tmp,z_ce_tmp : std_logic;
signal rdo_ce : std_logic;

--TTC_REG:
signal TTC_DS,TTC_DS1,TTC_MONO,bro2	:	std_logic;
signal DIN_TTC1	:	std_logic_vector(7 downto 0);
--signal DATA : std_logic_vector(7 downto 0);
signal V_TTC : std_logic_vector(7 downto 0);	--VME broadcast signals
signal SWITCH,SWITCH_tmp1,SWITCH_tmp2 : std_logic;
signal TTC_BUS : std_logic_vector(3 downto 0);
signal TTC_tmp,ttc_s : std_logic_vector(56 downto 0);
signal TTC_2_tmp : std_logic_vector(31 downto 16);

signal VME_BUS_READ,VME_BUS_READ_tmp,VME_BUS_READ_CON	:	std_logic_vector(15 downto 0);

signal SINERRSTR,DBERRSTR,BRCST_STR_2 :	std_logic;
signal BENT	:	std_logic_vector(11 downto 0);
signal SUBADDR: std_logic_vector(7 downto 0);
signal BRCST_CMD: std_logic_vector(1 downto 0);
signal CRAP0,CRAP1,CRAP2,CRAP3:	std_logic;

signal ZERO,ONE : std_logic;

--signal led1_cnt,led2_cnt,led6_cnt	:	std_logic_vector(24 downto 0);
--signal led2_cnt,led6_cnt	:	std_logic_vector(24 downto 0);
signal start_vme,start_ttc	:	std_logic;
signal led_ttc1,led_test	: std_logic;

signal crap_ttc	:	std_logic_vector(20 downto 0);
signal en_rst_ttc,en_rst_dll,ttc_lock_tmp	:	std_logic;
signal SRL16_vec	:	std_logic_vector(11 downto 0);

signal TTC_LOSS_CNT	:	std_logic_vector(7 downto 0);
signal SRL16_vec0,SRL16_vec1	:	std_logic_vector(15 downto 0);
signal TTC_LOSS_TC,TTC_LOSS_EN,TTC_LOSS_RST,TTCRST_EN,TTC_RST_EXTERN	:	std_logic;
signal DLL_RST_FORALL	:	std_logic;

signal EN1_TTC_HIGH,EN2_TTC_HIGH,EN_TTC_HIGH,TTC_HIGH	:	std_logic;
signal TTCRST_TMP1,TTCRST_TMP2	:	std_logic;
		   
signal RDO_BUS_in_tmp : std_logic_vector(4 downto 0);
signal RDO_BUS_OUT_tmp : std_logic_vector(11 downto 0);

signal start_int  : std_logic;
signal tmp1,tmp2: integer range 0 to 8;
signal data_write : std_logic_vector(15 downto 0);

signal cetmp: std_logic_vector(3 downto 0);

signal bro,broa : std_logic_vector(1 downto 0);
signal bro3  : std_logic_vector(2 downto 0);
signal br  : std_logic;

signal ttc_cmd_cnt, last_ttc_cmd,i2c_stat,i2c_cont : std_logic_vector(15 downto 0);
signal QCLKIN_g,qclkin_s : std_logic;

signal w_dat,r_dat : std_logic_vector(15 downto 0);
signal v_add : std_logic_vector(23 downto 1);
signal v_nds,v_brdsel,v_nds_tmp,v_sumsel : std_logic;
signal statmp : std_logic_vector(11 downto 0);
signal clk80,clk80a,lac,dinx,load_enable : std_logic;
signal isub_ch : integer;

signal clk40,clk_out : std_logic;
signal v_chipsel,ds0,vme_write, board_select,address_match, vme_n_write,vme_N_DS0,v_nren : std_logic;
signal ttc_lock : std_logic;

signal input_dones,in_conf_mask:std_logic_vector(3 downto 0);
signal jet_dones : std_logic;

signal in_load_config:std_logic;
signal ick : std_logic_vector(3 downto 0);
signal idin  : std_logic_vector(3 downto 0);

signal inp_ce	: std_logic_vector(vme_inchips-1 downto 0);
signal jet_ce :std_logic;
signal chn : std_logic_vector(6 downto 0);
signal ichn: integer;
signal jconf_d : std_logic_vector(7 downto 0);

signal r_dat_i2c:std_logic_vector(15 downto 0);
signal i2c_strb : std_logic;
signal reset_ttc:std_logic;

--i2c
--constant i2c_base		: STD_LOGIC_VECTOR( 6 downto 0)  := "0000110"; --mod. uli
constant i2c_base		: STD_LOGIC_VECTOR( 6 downto 0)  := "0000110"; --mod. uli

--signal i2c_cont 		: STD_LOGIC_VECTOR( 15 downto 0);--registers from VME

alias i2c_RegNo 		: STD_LOGIC_VECTOR( 4 downto 0) 	is i2c_cont( 12 downto 8); 
alias i2c_Data  		: STD_LOGIC_VECTOR( 7 downto 0) 	is i2c_cont( 7 downto 0); 
alias i2c_RW    		: STD_LOGIC 						is i2c_cont( 13); 

signal i2c_init				: STD_LOGIC;
signal IDLEn			: STD_LOGIC;	
signal A_Err,i2c_busy		: STD_LOGIC;	
signal i2c_DATA_OUT			: STD_LOGIC_VECTOR( 7 downto 0);-- TTCrx read Data out

signal new_command		: STD_LOGIC;					-- new_command flag


TYPE phase IS 			( P0 , P1 , P2 , P3 );

signal clockphase		: phase;

TYPE shiftstate IS 		( IDLE , STRT , ADDR , RDWR, AACK, DATA , DACK , STP1 , STP2 );


SIGNAL output_shiftreg	: STD_LOGIC_VECTOR(16 downto 0);
SIGNAL rw_reg			: STD_LOGIC;
SIGNAL dat_shiftreg		: STD_LOGIC_VECTOR(7 downto 0);

SIGNAL sequencer 		: shiftstate;

signal ttclk,cycle,clken			: STD_LOGIC;

signal shift_count		: INTEGER RANGE 0 to 16;
signal s_data,s_clck,i2c_res	: STD_LOGIC;

-- old main

constant inprox:integer:=3;
signal indat  : arr_fourty(inprox-1 downto 0);
signal SMM_int,smm_a,smm_b,jmm : std_logic_vector(24 downto 0);
signal RESET : std_logic;
signal START_PLAY_256,START_SPY_256,STOP_PLAY: std_logic;
signal DAQ_DATA_VALID_1,DAQ_OUT_1: std_logic;
signal rtd_data	:	std_logic_vector(49 downto 0);

--BLOCK RAM signals:
signal NADA : std_logic_vector(15 downto 0);	--contains only zeros
signal EX_IN,EY_IN,ET_IN : std_logic_vector(15 downto 0);
signal READ_ADDR_T,READ_ADDR_Y,READ_ADDR_X : std_logic_vector(7 downto 0);
signal RDO_ADDR_T,RDO_ADDR_Y,RDO_ADDR_X : std_logic_vector(8 downto 0);
signal RDO_ADDR_T_exp,RDO_ADDR_Y_exp,RDO_ADDR_X_exp,MASK_RDO : std_logic_vector(8 downto 0);
signal EX_OUT,EY_OUT : std_logic_vector(15 downto 0);
signal ET_OUT : std_logic_vector(15 downto 0);
--additional signals:
signal ACTIVE : std_logic;
signal PLAY_ONCE,VME_ONCE : std_logic;
signal S_CE_TMP1,S_CE_TMP,EXTERN_EN	:	std_logic;
signal RST_CNT_X,RST_CNT_Y,RST_CNT_T : std_logic;
signal RDO_EN_X,RDO_EN_Y,RDO_EN_T : std_logic;
signal TTC_CNT_X,TTC_CNT_Y,TTC_CNT_T : std_logic;
signal READ_REQUEST_TMP : std_logic;

signal SMM_SLICE,	READ_REQUEST, SMM_DATA_VALID	:	 std_logic;
signal ENABLE_SPY,TC_WRITE,RESET_SPY,RESET_WRITE,SPY_ENABLE,enable_cnt: std_logic;
signal MASK,READ_ADDR,WRITE_ADDR : std_logic_vector(7 downto 0);
signal addr_vme : std_logic_vector(7 downto 0);

signal icontrols,icontrols_tmp, data_r_jen1 : std_logic_vector(12 downto 0);


signal AKTIVE,L1A_SIG,L1A_SIG_TMP,l1a_sim,RST_BC	:	std_logic;
--clock generation:
signal CLK0_h,CLK0_w,DLL_LOCK: std_logic;
signal CLKIN_w,DLL_RST: std_logic;
--conrol path signals:
signal S_CE,S_WRITE,TS_EN : std_logic;
--signal WRITE_EN:	std_logic;
signal S_CE_VEC	:	std_logic_vector(7 downto 0);
signal icontrolr,icontrolr_TMP,pulser	:	std_logic_vector(11 downto 0);
signal ADDR_IN : std_logic_vector(4 downto 0);
signal S_DATA_IN,S_DATA_OUT : std_logic_vector(11 downto 0);
signal IADDR_VME	:	integer;
--vme readout signals:
signal DATA_READ_RR,DATA_READ_TOP,DATA_READ_GL,DATA_READ_SPY,cnt_reg1,cnt_reg2,cnt_reg3 :	std_logic_vector(9 downto 0);
-- general signals:
signal CRAP01,CRAP02,CRAP03,CRAP04	: std_logic;
signal RREQ_SL,RREQ_ROI	:	std_logic;
signal RREQ_SLV : std_logic_vector(6 downto 0); 
signal DVALID	:	std_logic_vector(5 downto 0);
signal DVALID_JEN_SRL,SLICE_JEN_SRL,ROI_BC_SRL,DVALID_ROI,ROI_STREAM	:	std_logic_vector(1 downto 0);
signal DVALID_BC_SRL,SLICE_BC_SRL	:	std_logic_vector(2 downto 0);
--BC_NR GENERATION:
signal BC_COUNT,BC_OFFSET	:	std_logic_vector(11 downto 0);
signal BC_COUNT_TMP,BC_NUMBER_SL,BC_NUMBER_ROI	:	std_logic_vector(11 downto 0);
signal BC_READ_REQ,BC_DATA_VALID,BC_SL_DVALID,BC_ROI_DVALID :	std_logic;
signal DAT_VALID	:	std_logic_vector(5 downto 0);
--SLICE_MAPPING:
signal DATA_SL,DATA_ROI,DATA_SL_muxed, DATA_ROI_muxed	:	std_logic_vector(19 downto 0);
signal BC_SLICE_ROI,BC_SLICE_SL	:	std_logic;
signal DAV_INT_SL,DAV_INT_ROI	: std_logic;
--SPY_SIGNALS:
signal capture_next : std_logic;
signal SL_DAT_int,ROI_DAT_int	:	std_logic_vector(19 downto 0);
signal SL_DAV_int, ROI_DAV_int	:	std_logic;
signal RE_SET_SPY	:	std_logic;
signal  start	:	std_logic;
signal BC_SL_RREQ,BC_ROI_RREQ	:	std_logic;
--GLINK_RESET:
signal sl_rst_int,roi_rst_int	:	std_logic;

signal GLINK_CTRL	:	std_logic_vector(11 downto 0);
--signal GLINK_SET	:	std_logic_vector(3 downto 0);
signal G_LINK_STATUS	:	std_logic_vector(5 downto 0);
signal sl_rst_srl,roi_rst_srl	:	std_logic_vector(15 downto 0);
signal DATA_OUT,crap_reg	: std_logic_vector(11 downto 0);
signal lfsr: STD_LOGIC_VECTOR(20 downto 1); -- to Xilinx notation
signal int_res,srl_1,srl_0 : std_logic;
signal roi_in_tmp : std_logic_vector(3 downto 0);

signal doit, areg, breg, creg, start_capture : std_logic;

signal ram_sl_out,ram_roi_out	:	std_logic_vector(19 downto 0);

type ram_type is array(integer range <>) of std_logic_vector(9 downto 0);
signal ram_sl_1,ram_sl_2 ,ram_roi: ram_type(0 to 1023);
signal wcnt_sl, rcnt_sl_1,rcnt_sl_tmp_1,rcnt_sl_2,rcnt_sl_tmp_2,wcnt_roi, rcnt_roi , rcnt_roi_tmp:	integer range 0 to 1023;

signal bc_COUNT_INT	:	std_logic_vector(11 downto 0);
signal TC	:	std_logic;
signal COUNT_VALUE	:	integer range 0 to 4095;
signal ibc_offset	:	integer range 0 to 4095;

--VME signals of different registers:
type srl_type is array (63 downto 0) of std_logic_vector (11 downto 0); 
signal srl_bc : srl_type;
signal BC_NUMBER,tmptmp	:	std_logic_vector(11 downto 0);
signal L1_ACCEPT_TMP	:	std_logic;
signal RREQ_DEF 	:	std_logic_vector(2 downto 0); 
--RR_SIGNALS:
signal RREQ_CNT,MASK_RREQ	: 	std_logic_vector(2 downto 0);
signal RREQ_EN_INT:	std_logic;	
--LEVEL1A_SIGNALS:
signal SL_LATENCY,ROI_LATENCY	:	std_logic_vector(5 downto 0);
signal SL_LATENCY_SRL,ROI_LATENCY_SRL	:	std_logic_vector(63 downto 0);
signal L1_ACCEPT_SL,L1_ACCEPT_ROI	:	std_logic;
signal xclkin,xclk : std_logic;

signal r_add,last_add : std_logic_vector(7 downto 0);
signal res_spycnt : std_logic;


signal	jet_slice		:	 std_logic;	--	in
signal	JEN_READ_REQ	:	 std_logic;	--  out
signal	JEN_DATA_VALID	:	 std_logic;	--	in
	----------INPUT_FPGAS:
	----------GLINK_SIGNALS:
signal	SL_DAT		:	 std_logic_vector(19 downto 0);	--out
signal	SL_EHCLKSEL	:	 std_logic;				--	out
signal	SL_FLAGSEL	:	 std_logic;				--	 out
signal	SL_FLAG		:	 std_logic;			--	 out
signal	SL_FF		:	 std_logic;				 -- out
signal	SL_HCLKON	:	 std_logic;	--	out
signal	SL_LOCKED	:	 std_logic;		--	 in
signal	SL_LOOPEN	:	 std_logic;		 -- out
signal	SL_LOUT1	:	 std_logic;		--in
signal	SL_LOUT2	:	 std_logic;		 --in
signal	SL_MDFSEL	:	 std_logic;			  --out
signal	SL_M20SEL	:	 std_logic;	-- out
signal	SL_RST		:	 std_logic;	--	out
signal	SL_CAV		: 	 std_logic;			 -- out
signal	SL_nDAV		:	 std_logic;		-- out
signal	SL_STRBIN	:	 std_logic;	 --out
signal	SL_ED		:	 std_logic;		--	 out
signal	SL_INV		:	 std_logic;	-- in
signal	SL_RFD		:	 std_logic;		 --in


signal v_in:arr_five(4 downto 0);
signal ndtack_int : std_logic;

signal smm_spy : arr_twentyfive(playspy_depth-1 downto 0);
signal roc_spy : arr_twentyfive(1023 downto 0);
signal ttc_cmd: std_logic_vector(3 downto 0);
signal spy_acc,reset_playspy_pointer,sum_dav,smm_slice_tmp,bc_slice_tmp,bc_slice : std_logic;
signal control_reg_s,roc_spydat : std_logic_vector(15 downto 0);

signal	in_SLICE			:	 std_logic_vector(10 downto 0);--	 in
signal x40,glck,dav_int,ordav : std_logic;
signal g_fifo : arr_eighteen(14 downto 0);
signal latcorr : std_logic_vector(7 downto 0);	  
signal extroi : std_logic_vector(3 downto 0);

															
BEGIN
INACTIVE <= '0';
----------------------
--board level de-skew:
----------------------
clkpad_t	:	IBUFG	port map (I=>CLK_in,O=>TCLKIN_w);
clkpad_x	:	IBUFG	port map (I=>xtal40,O=>x40);
dll_1	:	CLKDLL	port map (CLKIN=>TCLKIN_w,CLKFB=>CLK_2g,RST=>DLLRST,CLK2X=>clk80a,CLK0=>CLK_OUT,LOCKED=>DLL_LOCK_BOARD);
bufg_2	:	BUFG		port map (I=>CLK_out,O=>CLK_2g);

bufg_x	:	BUFG		port map (I=>CLK80a,O=>CLK80);

CLK40<=CLK_2g;	--40 MHz clock from TTCrx																 
TCLK40<=CLK40;	--40 MHz clock from TTCrx
QCLK40<=CLK40;	--40 MHz clock from TTCrx

--reset DLL might be required eventually. Currently system comes up properly if TTC clock available.
-- we'd rather prefer pulls to have system start up in crystal or debug mode with auto switch to guarantee
-- proper DLL lock.
dllrst<='0'; -- no reset
------------------------------------
--VME data/address handling(INTERN):
------------------------------------
--VME_DTACK<='0';


process(TCLK40)
begin
	if TCLK40'event and TCLK40='1' then
			IDS0_tmp<=board_select;
			IDS0<=IDS0_tmp;
	end if;
end process;

start_int<='1' when ids0='0' and ids0_tmp='1' else '0';		 --for narrowRDO

process(TCLK40)
begin
	if TCLK40'event and TCLK40='1' then
		if IDS0='0' and IDS0_tmp='1' and VME_WRITE='1' then 
			WRITE_EN<='1';
	 	else WRITE_EN<='0';
		end if;
	end if;
end process;


vme_WRITE<=not vme_n_write;
DS0<=not vme_N_DS0;

--vme_dtack<='0'; --use with patched CPLD only

--vme_dtack<=not ndtack_int ; --use with patched CPLD only

vme_dtack<='1' when ndtack_int='0' else 'Z';		 --inv  , normal op.
--vme_dtack<= 'Z';	--patch for defective JEM1
-- VME tristate bus ---------------------
data_write<=w_dat;
------------------------------------------
--new--
r_add<=v_add(7 downto 1) &'0';

--assign cclk here (inverted clock)

----------------- 
process(clk40)
variable rtmp,testreg,maskreg,maskr,resreg,s_dat,pulsereg: std_logic_vector(15 downto 0);
variable crapreg : std_logic_vector(15 downto 0):=x"0000";
variable masktmp :std_logic_vector(3 downto 0);
variable	v_ds,v_dstmp,last_ds,wenab,wenab1,ldentmp,v_write : std_logic;
variable sertmp,clktmp : std_logic_vector(2*serwid-1 downto 0);
variable lacx,lacy : std_logic :='0'; --initialise (for simulation)
variable rentmp,restmp :std_logic;
variable rescnt : integer range 0 to 15;
variable tmp,tmp1 : std_logic_vector(7 downto 0);
variable pipe0,pipe1,pipe2,pipe3,pipe4,dtmp : std_logic;
variable trescnt:integer:=0 ;
variable dcnt  : integer range 0 to dtack_max; -- delay of dtack signal
variable radd,ladd : std_logic_vector(7 downto 0);
variable strbtmp,endacc,load_conf_jet,load_conf_inp: std_logic;

--variable smm_spy : arr_twentyfive(511 downto 0);
variable smm_spout : std_logic_vector(24 downto 0);
variable roc_spout : std_logic_vector(24 downto 0);
variable spywadd,spyradd: integer range 0 to playspy_depth-1;
variable rspywadd,rspyradd: integer range 0 to 1023;
variable bufnum : integer range 0 to 2;
variable spy_enab,playstart,spacc,hunt_l1a:std_logic;

variable ttctmp,broadcast,playcnt: std_logic_vector(7 downto 0);
variable v_wren, v_ren,v_ren_tmp: boolean;
variable cntmp:std_logic_vector(9 downto 0);
variable roc_rcnt,roc_wcnt: integer range 0 to 1023;

variable res_ttc: std_logic;
variable dtack_init_cnt: integer:=0;

begin
IF falling_edge(clk40) THEN lacx := not lacx;  END IF;
if rising_edge(clk40) then
lacy := lacx;

vme_n_WRITE<=vme_NWRITE;
vme_N_DS0<=vme_NDS0;
GEO_ADDRs<=GEO_ADDR;


rtmp:=DATA_R_INPUT ; 



w_dat <= vme_data;
v_nds	<= vme_nds0;
v_nds_tmp<=v_nds;
v_brdsel	<=board_select ;
v_write := not vme_n_WRITE;
--if v_ds='0' then v_add <=	vme_address; end if; -- latch for compliance	(read)

v_add <=	vme_address; 


	if dcnt /= dtack_max then	-- minimum dtack delay from ds = 30 ns (VME specs)
		dcnt:=dcnt+1;
	else	
		dtmp:='1'; 
	end if;
	if board_select='0' then
		dcnt:=0;		--permanent reset
		dtmp:='0';
	end if;
if dtack_init_cnt < 200 then dtack_init_cnt:=dtack_init_cnt+1; dtmp:='0'; end if;
	ndtack_int<=not dtmp;



--wenab1:=wenab;
wenab:= not last_ds and v_ds and v_write and v_brdsel;
ladd:=x"00";
if v_nds_tmp='0' and v_nds='1' and v_ren then ladd:=radd; end if; --latch current address for a tick

if v_sumsel='0' and endacc='1' then last_add<=ladd; else last_add<=(others=>'0'); end if;
endacc:=	v_sumsel;

load_conf_jet:='0';load_conf_inp	:='0';
if v_add(18 downto 15)="1010" then load_conf_jet:='1'; end if;
if v_add(18 downto 15)="1011" then load_conf_inp:='1'; end if;

in_load_config <=	load_conf_inp and wenab;

last_ds:=v_ds;
v_ds:=v_dstmp;		-- delay 1 tick
v_dstmp:=not v_nds;		-- delay 1 tick

	if resreg=x"0000" then
		rescnt:=0;
	else
		rescnt :=rescnt+1;
	end if;

	if rescnt=15 then
		resreg:=	x"0000";
	end if;

	for i in 0 to 3 loop
--		input_prog(i)<=not( resreg(4+i));
		if resreg(4+i)='1' then input_prog(i)<='0'; else input_prog(i)<='Z'; end if;
	end loop;
-- jet config	 *****************************************************
--	jconf_h(7)<=not( resreg(0));	-- prog
		if resreg(0)='1' then jconf_h(7)<='0'; else jconf_h(7)<='Z'; end if;

	pipe0:= wenab and load_conf_jet  ;	-- cclk
	if pipe0='1' then 	tmp:=w_dat(7 downto 0);	end if;
	if pipe2='1' then 	tmp:=w_dat(15 downto 8); end if;
		


	for i in 0 to 7 loop --bit shift
		tmp1(i):=tmp(7-i);
	end loop;

	jconf_h(6)<=pipe1 or pipe3;
	jconf_d <= tmp1;

	pipe4:=pipe3;
	pipe3:=pipe2;
	pipe2:=pipe1;
	pipe1:=pipe0;

-------------------------------------------------------------------------
--ttc
ttc_s<=ttc;
playstart:='0';
broadcast:=ttc_s(37 downto 30); -- brcst(7:2) stobe(2:1)	  

if bc_sl_rreq='1' then playcnt:=playcnt+'1';	end if;
if broadcast(7 downto 6)="01" and broadcast(1)='1' then playstart:='1'; end if;
playstart:=playstart or pulsereg(1);


ttctmp:=x"ff";
if ttc_s(0)='1' then ttctmp:=ttc_s(20 downto 13); end if; -- command word

--spy
if control_reg(4)='1' then
	smm_spy(spywadd)<=smm_int;
	if spywadd=playspy_depth-1 then spywadd:=0; else spywadd:=spywadd+1; end if;
end if;
if playstart='1' then spywadd:=0; end if;

--roc spy
		if capture_next='1' then hunt_l1a := '1'; end if;		 --pulse
		if roc_wcnt /=0 or (hunt_l1a='1' and ordav='1') then 
			hunt_l1a:='0';
			roc_spy(roc_wcnt)<=roi_dat_int(8 downto 0) & roc_spydat(15 downto 0);
			if roc_wcnt /= 1023 then roc_wcnt := roc_wcnt +1; else roc_wcnt :=0; end if;
		end if;

--new
spacc:='0';
strbtmp:='0';
pulsereg:=(others=>'0');
radd:=v_add(7 downto 1) &'0';
v_wren:=	v_add(18 downto 13)="000100" and write_en='1';
v_ren:=	v_add(18 downto 13)="000100" and address_match='1' and v_nds='0';
-- register write
if  v_wren and radd=as_control then control_reg<=w_dat; end if;
if  v_wren and radd=as_pulse then pulsereg:=w_dat; end if;

if  v_wren and radd=as_cfg_mask then maskreg:=w_dat;  end if;
if  v_wren and radd=as_fpga_reset then resreg:=w_dat; end if;
if  v_wren and radd=as_ttc_command then ttctmp:=w_dat(7 downto 0);  end if;

if  v_wren and radd=as_ttc_control then i2c_cont<=w_dat;end if;
if  v_wren and radd=as_ttc_control then strbtmp:='1';  end if;

if  v_wren and radd=as_glink_control then GLINK_CTRL<=w_dat(11 downto 0);  end if;
if  v_wren and radd=as_read_request_delay then SL_LATENCY <=w_dat(5 downto 0);  end if;
if  v_wren and radd=as_slice_cnt then RREQ_DEF <=w_dat(2 downto 0);  end if;
if  v_wren and radd=as_bc_preset then bc_offset<=w_dat(11 downto 0);  end if;

if  v_wren and radd=as_spy_sl1+x"02"  then 	rspyradd:=0;  end if;
if  v_wren and radd=as_spy_sl2+x"02" then rspyradd:=0;   end if;
if  v_wren and radd=as_spy_exy+x"02" then 	spyradd:=0;  end if;
if  v_wren and radd=as_spy_et+x"02" then 	spyradd:=0;   end if;

if  v_wren and radd=as_latcorr then latcorr <=w_dat(7 downto 0);   end if;


																						 
-- register read
if  v_ren and radd=as_version then rtmp:=x"0005" ; end if;
if  v_ren and radd=as_status then rtmp:= playcnt &
--	input_u_i_s(49)&input_t_i_s(49)&input_s_i_s(49)&input_r_i_s(49)&
    input_u_i_s(49)&input_t_i_s(49)&input_s_i_s(49)&g_new_module&
	 main_dll_tmp1 & TTC_LOCK & DLL_LOCK_BOARD & DLL_LOCK_QUARTZ; end if;
if  v_ren and radd=as_control then rtmp:=control_reg ; end if;
if  v_ren and radd=as_pulse then rtmp:=x"0000" ; end if;
if  v_ren and radd=as_cfg_mask then rtmp:=maskreg ; end if;
if  v_ren and radd=as_fpga_reset then rtmp:=x"0000" ; end if;
if  v_ren and radd=as_fpga_done then rtmp:=x"00"&input_dones&"000" & jet_dones ; end if;
if  v_ren and radd=as_ttc_command then rtmp:=x"0000" ; end if;
if  v_ren and radd=as_ttc_status then rtmp:=i2c_stat ; end if;
if  v_ren and radd=as_ttc_control then rtmp:=i2c_cont ; end if;
if  v_ren and radd=as_glink_status then rtmp:="0000000000"&G_LINK_STATUS ; end if;
if  v_ren and radd=as_glink_control then rtmp:=x"0"&GLINK_CTRL ; end if;
if  v_ren and radd=as_bc_preset then rtmp:=x"0"&bc_offset ; end if;
if  v_ren and radd=as_read_request_delay then rtmp:=x"00"&"00"&sl_latency ; end if;
if  v_ren and radd=as_slice_cnt then rtmp:=x"000"&"0"&rreq_def ; end if;
if  v_ren and radd=as_spy_test then rtmp:="000000" & ram_roi(rcnt_roi) ; end if;


cntmp:= conv_std_logic_vector(rspyradd,10);
if  v_ren and radd=as_spy_sl1 then rtmp:=roc_spout(15 downto 0) ; end if;
if  v_ren and radd=as_spy_sl2 then rtmp:="00" & cntmp(5 downto 0) & roc_spout(23 downto 16)  ; end if;
roc_spout:=	roc_spy(rspyradd)	;
if  ladd=as_spy_sl1 then rspyradd:=rspyradd+1 ; end if;
if  ladd=as_spy_sl2 then rspyradd:=rspyradd+1 ; end if;

--if  v_ren and radd=as_spy_ex then rtmp:=conv_std_logic_vector(spyradd,8) & smm_spout(7 downto 0) ; end if;
if  v_ren and radd=as_spy_exy then rtmp:= smm_spout(15 downto 0) ; end if;
if  v_ren and radd=as_spy_et then rtmp:=x"0" & "000" & smm_spout(24 downto 16) ; end if;


--if radd=as_spy_ex then rtmp:=indat(0)(15 downto 0) ; end if;
--if radd=as_spy_ey then rtmp:=indat(1)(15 downto 0) ; end if;
--if radd=as_spy_et then rtmp:=indat(2)(15 downto 0) ; end if;
--if radd=as_spy_ex then rtmp:=x"00" & smm_spout(7 downto 0) ; end if;

if v_ren and radd=as_spy_exy then 	spacc:='1';  end if;
if v_ren and radd=as_spy_et then 	spacc:='1';  end if;

if  v_ren and radd=as_latcorr then rtmp:=x"00" & latcorr; end if;

																										
if  v_ren and radd=x"FE" then rtmp:=crapreg ; end if;

--LOCK_LOSS_STATUS<= INPUT_dones&in_conf_mask & TTC_LOSS_CNT;

spy_acc<=spacc;
if spacc='0' and spy_acc='1' then
	if spyradd=playspy_depth-1 then spyradd:=0; else spyradd:=spyradd+1; end if;
end if;
smm_spout:=smm_spy(spyradd);

masktmp:=  maskreg(7 downto 4);

i2c_strb<=strbtmp;

-- TTC reset
if trescnt/=20000 then res_ttc:='1'; trescnt:=trescnt+1; else res_ttc:='0'; end if;

--res_ttc:=control_reg(15); --debug
reset_ttc<=res_ttc;

if v_add(18 downto 15) = x"0" then rentmp :='0'; else rentmp:='1'; end if;

rentmp:=rentmp  and board_select and not VME_WRITE; 

--if rentmp='1' then VME_DATA<=rtmp; else VME_DATA<=(others=>'Z'); end if;
r_dat <=rtmp;
v_nren<=not rentmp;
in_conf_mask<=masktmp;
input_dones<=input_done;
jet_dones<=jconf_done;
--control_sum(9 downto 5)<=input_dones&jet_dones;
control_sum(8 downto 5)<=input_dones;

--input_prog<=icontrol(7 downto 4);



-- connect to pulse reg


if  pulsereg(2)='1' then trescnt:=0; end if;


GLOBAL_RESET<=pulsereg(0);
DLL_RST_FORALL<= pulsereg(3);

capture_next<=pulsereg(9);
L1A_SIM<=pulsereg(10);

--from control
TTC_LOSS_RST<=pulsereg(12);

reset_playspy_pointer<=playstart;


crapreg(2):=jen_data_valid;

crapreg(1):=v_add(11);
crapreg(0):=jet_slice;
control_reg_s<=control_reg;
end if;

lac <= lacx xor lacy;
end process;


--if rentmp='1' then 
VME_DATA<=r_dat when v_nren='0' else (others=>'Z');



process(Clk80)	 --serialise input config data at double rate
variable rtmp,testreg,s_dat: std_logic_vector(15 downto 0);
variable	v_ds,v_dstmp,last_ds,wenab,wenab1,ldentmp,v_write : std_logic;
variable sertmp,clktmp : std_logic_vector(2*serwid-1 downto 0);

begin	 
if rising_edge(Clk80) then

s_dat:=w_dat(7 downto 0) & w_dat(15 downto 8);

if in_load_config='1'   then 			
	for i in 0 to serwid-1 loop
		sertmp(2*i):=s_dat(i);
		sertmp(2*i+1):=s_dat(i);
		clktmp(2*i):='1';
		clktmp(2*i+1):='0';
	end loop;
else 
	sertmp:= sertmp(2*serwid-2 downto 0)&'0'; --shift
	clktmp:= clktmp(2*serwid-2 downto 0)&'0'; --shift
end if;
for i in 0 to 3 loop
	input_cclk(i)<= clktmp(2*serwid-1) and in_conf_mask(i);
	input_din(i)<=	sertmp(2*serwid-1) ;
end loop;

end if;
end process;
---------------------------------------------------------------------------------



---TTC_LOCK_LOSS_COUNTER (with saturation)
process(QCLK40)
begin
	if QCLK40'event and QCLK40='1' then
		if TTC_LOSS_RST='1' then 
			TTC_LOSS_CNT<= (others=>'0');
		elsif TTC_LOSS_TC='0' and TTC_LOSS_EN='1' then 
			TTC_LOSS_CNT<=TTC_LOSS_CNT+1;
			else 
			TTC_LOSS_CNT<=TTC_LOSS_CNT;
		end if;
	end if;
end process;
TTC_LOSS_TC<='1' when TTC_LOSS_CNT="11111111" else '0';
TTC_LOSS_EN<=not TTC_LOCK;
---
--LED_8 <=TTC_LOSS_TC;			--RED_LED ---WARNING!!!!
---

-------------
--INPUT FPGA:
-------------

lab_ince: for i in 0 to vme_inchips-1 generate
	inp_ce(i)<='1' when 
		(ds0='1' and v_add(18 downto 15)=x"3" and conv_integer(v_add(14 downto 13))=i)
		else '0';
	end generate;

	jet_ce<='1' when ds0='1' and v_add(18 downto 15)=x"2" else '0';

--------------------------------------------------------------
---MULTIPLEXING PART------------------------------------------
--------------------------------------------------------------

process (tclk40)
variable  TTC_DAT		: std_logic_vector(7 downto 0);
begin
if rising_edge(tclk40) then

input_r_i_s<=input_r_i;
input_s_i_s<=input_s_i;
input_t_i_s<=input_t_i;
input_u_i_s<=input_u_i;

--input_r_o(61)<=control_reg(8);
--input_s_o(61)<=control_reg(8);
--input_t_o(61)<=control_reg(8);
--input_u_o(61)<=control_reg(8);

input_r_o(61)<='0';
input_s_o(61)<='0';
input_t_o(61)<='0';
input_u_o(61)<='0';

for i in 0 to 5 loop

	input_r_o(i+62)<=RDO_BUS_OUT_tmp(i)and inp_ce(0) ;
	input_s_o(i+62)<=RDO_BUS_OUT_tmp(i)and inp_ce(1) ;
	input_t_o(i+62)<=RDO_BUS_OUT_tmp(i)and inp_ce(2) ;
	input_u_o(i+62)<=RDO_BUS_OUT_tmp(i)and inp_ce(3) ;
	jet_l(i)<=RDO_BUS_OUT_tmp(i)and jet_ce ;

end loop;

v_in(0)<= input_r_i(44 downto 40);
v_in(1)<= input_s_i(44 downto 40);
v_in(2)<= input_t_i(44 downto 40);
v_in(3)<= input_u_i(44 downto 40);
v_in(4)<= jet_h(38 downto 34);

for i in 0 to 4 loop
	rdo_bus_in_tmp(i)<=
	   (v_in(0)(i)and inp_ce(0))
		or (v_in(1)(i)and inp_ce(1))
		or (v_in(2)(i)and inp_ce(2))
		or (v_in(3)(i)and inp_ce(3))
		or (v_in(4)(i) and jet_ce)  	
				 ;
end loop;

		TTC_tmp <= TTC;
		ttc_dat:=(others=>'0');
		TTC_DAT(0):=DLL_RST_FORALL;
		ttc_dat(1):=reset_playspy_pointer;
		TTC_DAT(5):=GLOBAL_RESET;
--		ttc_dat(6):=TTC_tmp(41);	--L1A
		ttc_dat(6):=L1A_SIG;	--L1A
		ttc_dat(7):=TTC_tmp(38);	--BC_RES

input_r_o(60 downto 53)<=ttc_dat;
input_s_o(60 downto 53)<=ttc_dat;
input_t_o(60 downto 53)<=ttc_dat;
input_u_o(60 downto 53)<=ttc_dat;
jet_l(13 downto 6)<=ttc_dat;


end if;
end process;

---------------------------------------------------------------
-------------------LED FUNCTIONALITY---------------------------
---------------------------------------------------------------

start_vme <= '1' when IDS0_tmp = '1' and IDS0 = '0' else '0';

PLED1:process(qCLK40)
variable led_cnt : integer range 0 to ledon;
variable led_sig : std_logic;
begin
	if qclk40'event and qclk40='1' then
	  led_sig:='0';
      if start_vme = '1' then led_cnt:=0; end if; 
	  if led_cnt/=ledon then
   		led_cnt:=led_cnt+1; 
		led_sig:='1';
	  end if;

--	  led_vme<=led_sig;
  	end if;
end process;


PLED2:process(qCLK40)
variable led_cnt : integer range 0 to ledon;
variable led_sig : std_logic;
begin
	if qclk40'event and qclk40='1' then
	  led_sig:='0';
      if ttc_mono = '1' then led_cnt:=0; end if; 
	  if led_cnt/=ledon then
   		led_cnt:=led_cnt+1; 
		led_sig:='1';
	  end if;

--	  led_ttc<=led_sig;
  	end if;
end process;

PLED6:process(qCLK40)
variable led_cnt : integer range 0 to ledon;
variable led_sig : std_logic;
begin
	if qclk40'event and qclk40='1' then
	  led_sig:='0';
      if TTCRST_EN = '1' then led_cnt:=0; end if; 
	  if led_cnt/=ledon then
   		led_cnt:=led_cnt+1; 
		led_sig:='1';
	  end if;

--	  led_6<=led_sig;
  	end if;
end process;


-- l1acc LED
process(qCLK40)
variable led_cnt : integer range 0 to ledon;
variable led_sig : std_logic;
begin
	if qclk40'event and qclk40='1' then
	  led_sig:='0';
      if l1a_sig = '1' then led_cnt:=0; end if; 
	  if led_cnt/=ledon then
   		led_cnt:=led_cnt+1; 
		led_sig:='1';
	  end if;
control_sum(10)<=led_sig;

--LED_GELB4<=led_sig;

  	end if;
end process;




-- short broadcast LED
process(qCLK40)
variable led_cnt : integer range 0 to ledon;
variable led_sig : std_logic;
begin
	if qclk40'event and qclk40='1' then
	  led_sig:='0';
      if br = '1' then led_cnt:=0; end if; 
	  if led_cnt/=ledon then
   		led_cnt:=led_cnt+1; 
		led_sig:='1';
	  end if;

--	  LED_GELB3<=led_sig;

  	end if;
end process;

-- command strobe LED
process(qCLK40)
variable led_cnt : integer range 0 to ledon;
variable led_sig : std_logic;
begin
	if qclk40'event and qclk40='1' then
	  led_sig:='0';
      if ttc_ds = '1' then led_cnt:=0; end if; 
	  if led_cnt/=ledon then
   		led_cnt:=led_cnt+1; 
		led_sig:='1';
	  end if;
control_sum(11)<=led_sig;

  	end if;
end process;

process(qCLK40)
begin
	if qclk40'event and qclk40='1' then

--	CRAP_TTC <= "00000000000000000001" + ('0' & crap0 & TTC_2_tmp(31 downto 30) & TTC_2_tmp(21 downto 16) & TTC_1_tmp(13 downto 5) & TTC_1_tmp(2 downto 1));
--	crap<=crap_ttc(19)or fcal(0)or fcal(1);
  	end if;
end process;







process(tCLK40)
variable vadd	: std_logic_vector(15 downto 0);
variable wcnt: integer range 0 to 8;
variable rcnt: integer range 0 to 3;
variable rdo_tmp: std_logic_vector(11 downto 0) :=zero12;
variable read_tmp: std_logic_vector(15 downto 0);
variable tmptmp:std_logic;
begin
	if rising_edge(tCLK40) then
		vadd:=v_add(16 downto 1);											 
		if v_add(12)='1'then
--			vadd:=x"00" & "001" & v_add(7 downto 5) & v_add(2 downto 0); -- 8 channel addresses
		
			vadd:=x"00" & ( 	v_add(10 downto 6)+"01000")& v_add(3 downto 1); -- 8 channel addresses
		end if;

		if rdo_bus_in_tmp(4)='1' then			  -- start read
			rcnt:=0;
		elsif rcnt/= 3  then
			rcnt:=rcnt+1;
		end if;

		if start_int='1' then
			wcnt:=0;
		elsif wcnt/= 8  then
			wcnt:=wcnt+1;
		end if;

-- don't optimise RDO pins away

		rdo_tmp(5):='0';
		if wcnt=0 then
			rdo_tmp(4):=vme_write;
			rdo_tmp(5):='1';
		end if;

		for i in 0 to 1 loop
			 if wcnt=i then rdo_tmp(3 downto 0):=vadd(4*i+3 downto 4*i); end if;
		end loop;

		for i in 0 to 2 loop
			 if wcnt=i+2 then rdo_tmp(3 downto 0):=data_write(4*i+3 downto 4*i);  end if;
		end loop;

-----		rcnt:= conv_integer(rdo_bus_in_tmp(11 downto 10));
		for i in 0 to 3 loop
			 if rcnt=i then read_tmp(4*i+3 downto 4*i):=rdo_bus_in_tmp(3 downto 0); end if;
		end loop;


	end if;

DATA_R_INPUT<="0000" & read_tmp(11 downto 0);
RDO_BUS_OUT_tmp<=rdo_tmp;
crap0<=tmptmp;
tmp1<=rcnt;
tmp2 <=wcnt;
end process;


process (tclk40)
variable tcnt : std_logic_vector(15 downto 0) :=(others=>'0');
begin

if rising_edge(tclk40) then
--if CONTROL_pulse(control_reset_tcnt)='1' then tcnt:=(others=>'0'); end if;
if ttc_ds='1' then 
	last_ttc_cmd(7 downto 0)<= din_ttc1;
	last_ttc_cmd(15 downto 8)<= last_ttc_cmd(7 downto 0);
	if tcnt/=x"ffff" then tcnt:=tcnt+1; end if;
end if;
ttc_cmd_cnt<=tcnt;
end if;
end process;

--config_c<='0';
--config_d<='0';



--vme_DTACK <= ndtack_int;
---------------------------------------------

address_match<='1'  when ("1" & GEO_ADDRs(3 downto 0))=V_add(23 downto 19) else '0';
board_select <= address_match and ds0;
v_chipsel<='1' when v_nds='0' and address_match='1' and v_add="000100" else '0';


--	control_sum(5)<='1';

-- jet config
jconf_l(3 downto 0)<=jconf_d(7 downto 4);	  --d0= MSB !
jconf_l(4)<='0'; --rd :write
jconf_l(5)<='0'; -- cs : activated

jconf_h(5 downto 2)<=jconf_d(3 downto 0);

--jconf_h(6)<='Z';	-- cclk
--jconf_h(7)<='Z';	-- prog



--jconf_d <=w_dat(7 downto 0);



process(clk40)
--variable ttctmp : std_logic_vector(56 downto 0);
variable tmptmp : std_logic;
begin
--ttctmp:=(others=>'Z');
if rising_edge(clk40) then
--statmp(9 downto 4)<= jet_h(38 downto 33);

--jet_l(5 downto 0)<=icontrol(13 downto 8);


ttc(26)<='0';			--pd
ttc(27)<= '1';			 --clksel
ttc(ttc_nreset)<=not reset_ttc;		--21

end if;
end process;



ttc(20 downto 0)<=(others=>'Z');
ttc(25 downto 22)<=(others=>'Z');
ttc(56 downto 28)<=(others=>'Z');

control_sum(0)<='Z';


---i2c controller

one <='1';
zero<='0';
i2c_res<='0';



process(clk40)
variable cnt:integer:=0;
variable tds,tmp:std_logic:='0';
begin
if rising_edge(clk40) then
----------------------------------------------------
tmp:='0';
if cnt=500 then 
	tmp:='1';
	cnt:=0;
else
	cnt:=cnt+1;
end if;
clken<=tmp;

	if (IDLEn = '1' ) then
		new_command <= '0';						--clear flag once controller starts
	elsif(i2c_strb='1') then
		new_command <= '1';						-- trailing/falling edge sets flag
	end if;
--------------------clken
	if  clken='1' then     --*** *************************************

	i2c_init <= new_command;-- i2c_initiate I2C cycles
-------------------------------------------------------------------------------
-- 4-phase clock generator
-------------------------------------------------------------------------------

	case clockphase is
	when P0  	=> clockphase <= P1;
	when P1  	=> clockphase <= P2;
	when P2  	=> clockphase <= P3;
	when others => clockphase <= P0;
 
	end case;
	

-------------------------------------------------------------------------------
-- I2C sequencer 
-------------------------------------------------------------------------------

	IF (clockphase = P3) THEN

	IDLEn <= '1';
	shift_count <= shift_count + 1;
	rw_reg <= rw_reg;

	case sequencer is 	
	when IDLE =>
		IDLEn <= i2c_init;
		cycle <= '0';			-- First cycle sets pointer, second cycle xfers data
		IF (i2c_init = '1' ) THEN sequencer <= STRT; 
		end if;

	when STRT => 
		sequencer <= ADDR;
		rw_reg <= not i2c_RW;
		shift_count <= 0;

	when ADDR => 
		IF (shift_count = 6 ) THEN sequencer <= RDWR; 
		end if;

	when RDWR => 
		sequencer <= AACK;

	when AACK => 
		sequencer <= DATA;
		shift_count <= 0;

	when DATA => 
		IF (shift_count = 7 ) THEN sequencer <= DACK; 
		end if;

	when DACK => 
		sequencer <= STP1;

	when STP1 => 
		sequencer <= STP2;

	when STP2 => 
		IF (cycle = '0' ) 
			THEN sequencer <= STRT;
 			else sequencer <= IDLE;
		end if;
		cycle <= '1';

	when others => 
		sequencer <= IDLE; 
end case;

END IF;

-------------------------------------------------------------------------------
-- start - stop protocol bits 
-------------------------------------------------------------------------------
if i2c_res = '1' then
		s_clck <= '1';
else     --*** *************************************

	s_data <= s_data; 	-- hold state until specified
	s_clck <= s_clck;

	case sequencer is
	when IDLE =>
		s_data <= '1';
		s_clck <= '1';

	when STRT =>
		s_data <= '0';
		if(clockphase = P2 ) then
			s_clck <= '0';
		end if;


	when ADDR | RDWR | DATA | AACK | DACK =>
		s_data <= output_shiftreg(16);

		case clockphase is
		when P1 =>
			s_clck <= '1';
		when P3 =>
			s_clck <= '0';
		when others =>
		end case;	


	when STP1 =>
		case clockphase is
		when P0 =>
			s_clck <= '0';
			s_data <= '0';
		when P1 =>
			s_clck <= '1';
		when P2 =>
			s_data <= '1';
		when others =>
		end case;	
	
	when others => 
	end case;
end if;
-------------------------------------------------------------------------------
-- output shift register
-------------------------------------------------------------------------------

	IF (clockphase = P3) THEN


	output_shiftreg (16 downto 1) <= output_shiftreg (15 downto 0) ;
	output_shiftreg (0) <= '1' ;

	case sequencer is 	-- First cycle sets pointer, second cycle xfers data
	when IDLE =>

	when STRT => 															-- loadup shift register
		output_shiftreg(16 downto 10) <= i2c_base(6 downto 1) & cycle;
		output_shiftreg(9) <= (not i2c_RW) and cycle;								--1st cycle is always a write
		output_shiftreg(8) <= '1';											-- AACK bit, could also be Hi-Z
		IF (cycle = '0' ) 
			THEN output_shiftreg(7 downto 0) <= "000" & i2c_RegNo;			--1st cycle loads Register No.
 			elsif (i2c_RW = '0')
				then output_shiftreg(7 downto 0) <= "11111111";	
				else output_shiftreg(7 downto 0) <= i2c_Data;				--2nd cycle loads Data, even if read
		end if;

	when others => 

end case;
END IF;
-------------------------------------------------------------------------------
-- read register
-------------------------------------------------------------------------------

	IF (clockphase = P2) THEN


	IF (sequencer = DATA and cycle = '1') THEN
		dat_shiftreg(0) <= i2c_sda;
		dat_shiftreg(7 downto 1) <= dat_shiftreg(6 downto 0);
	ELSE
		dat_shiftreg <= dat_shiftreg;
 	end if;

	end if;

-------------------------------------------------------------------------------
-- I2C Address ACK error flag
-------------------------------------------------------------------------------


	IF (clockphase = P2) THEN

	IF (sequencer = STRT and cycle = '0') THEN
		A_Err <= '0';
	ELSIF
		(sequencer = AACK ) THEN
		A_Err <= A_Err or i2c_sda; -- i2c_sda should be low
	ELSE
		A_Err <= A_Err;
 	end if;

	end if;
END IF;
END IF;
END process;
i2c_stat<=	"0" & A_Err & i2c_busy & "00000" & i2c_DATA_OUT ;
i2c_busy <= new_command OR IDLEn;
i2c_scl <= '0' when s_clck = '0' else 'Z';
i2c_sda <=  '0'  when s_data  = '0' else 'Z'; 
i2c_DATA_OUT <= dat_shiftreg;

-- old main code


-- RTDP : energy processing   
process(CLK40)
variable eotmp : std_logic_vector(14 downto 0);
variable smm_tmp : std_logic_vector (24 downto 0);
variable smm_vec : arr_twentyfive (15 downto 0);
variable partmp : std_logic;
variable ofl :	 std_logic;
variable entmp:  std_logic_vector(13 downto 0);			--increased width!
variable sum : std_logic_vector(16 downto 0);
variable intmp : std_logic_vector(41 downto 0);
variable cnt : std_logic_vector(7 downto 0) :=x"00";
variable enab : std_logic_vector(2 downto 0);
begin
if rising_edge(CLK40) then

indat(0)<= input_r_i(39 downto 0);
indat(1)<= input_s_i(39 downto 0);
indat(2)<= input_t_i(39 downto 0);

--enab:=control_reg_s(10 downto 8);
--	smm_tmp:=(others=>'0');
	for n in 0 to 2 loop	  -- energies
		ofl:='0';
		sum:=(others=>'0');
		for i in 0 to 2 loop	 -- input processors
			intmp:="00" & indat(i);
--			if enab(i)='1'then intmp:=(others=>'0');end if;	 -- patch
			entmp:=intmp(n*14+13 downto n*14);

			if n=2 and entmp(11 downto 0)=full12	then ofl:='1'; end if;

			if n=2 then entmp:=entmp(11 downto 0) & "00";end if;	
			if entmp=full14 then ofl:='1'; end if;		 
			sum:=sum + entmp;
		end loop;
		eotmp:= sum(16 downto 2);

---pipe for JEM0 only
					
		if eotmp(11 downto 10)/="00" then
			eotmp(5 downto 0):= eotmp(11 downto 6);
			eotmp(7 downto 6):="11"	;
		elsif	eotmp( 9 downto  8)/="00" then 
			eotmp(5 downto 0):= eotmp(9 downto 4);
			eotmp(7 downto 6):="10"	;
		elsif	eotmp( 7 downto  6)/="00" then 
			eotmp(5 downto 0):= eotmp(7 downto 2);
			eotmp(7 downto 6):="01"	;
		else 
			eotmp(7 downto 6):="00"	;
		end if;
-- saturation
		if ofl='1' or (eotmp(14 downto 12)/="000") then eotmp:=full15; end if; 
--		smm_tmp:=smm_tmp(15 downto 0) & eotmp(7 downto 0);
		smm_tmp(8*n+7 downto 8*n):=eotmp(7 downto 0);
	end loop;

-- odd parity
	smm_tmp(24):='1';  
	for i in 0 to 23 loop smm_tmp(24):=smm_tmp(24) xor smm_tmp(i);	end loop;
	smm_int<= smm_tmp;	

-- Debug-------------------------------------------------------------------------------------
--	partmp:='1'; -- debug :generate a parity error 
--	cnt:=cnt+1;
--	smm_tmp:= cnt&cnt&cnt;	  -- CMM debug
-- odd parity
--	partmp:='1';  
--	for i in 0 to 23 loop partmp:=partmp xor smm_tmp(i);	end loop;
-----------------------------------------------------------------------------------------
--	smm<= partmp & smm_tmp;	     		  -- OFD

	jet_l(49 downto 25)<= smm_tmp;  -- duplicate to jet proc 

-- debug : 2 ticks delay
smm_vec(15 downto 1):=smm_vec(14 downto 0);
smm_vec(0):=smm_tmp;
smm_tmp:=smm_vec(conv_integer(control_reg(3 downto 0)));

--	smm_a<=smm_tmp;
--	smm_b<=smm_a;
--	if control_reg(8)='1' then smm_tmp:=smm_b;	 end if;
	jmm<=jet_h(24 downto 0);
	if control_reg(9)='1' then smm_tmp:=jmm;	 end if;

	smm<= smm_tmp(15) & smm_tmp(23 downto 16) & smm_tmp(24) & smm_tmp(14 downto 0);	  --routing error on PCB


end if;

end process;


RESET<=global_reset;

----------------------roc


crap01 <= SL_LOUT1 or SL_LOUT2;

CRAP_reg<= '0'&xclk&(CRAP01 or crap02 or crap04) & crap03 & x"00";
crap03<='0' when DAT_VALID/="000000" else '1';
dat_valid<=dvalid;

---------------------------------------------------------------------------
------------------------MAP I/O SIGNALS to I/O FFs--------------------------
---------------------------------------------------------------------------
process(CLK40)	  --I/O FFs
variable	in_DATA_VALID	:	 std_logic_vector(3 downto 0); -- in
variable tmp,SL_DAV: std_logic;
variable g_word,gcnt,g_word1 : std_logic_vector(19 downto 0);
variable davtmp : std_logic_vector(4 downto 0); 
variable sdavtmp, bctmp,sumtmp,sdavtmp1, bctmp1,sumtmp1,ldav,sl_dav1 : std_logic;
variable fcnt: integer range 0 to 14 :=0;
begin
if rising_edge(CLK40) then
davtmp :=sdavtmp & input_u_i_s(48)& input_t_i_s(48)& input_s_i_s(48)& input_r_i_s(48);
if davtmp="00000" then ordav<='0'; else ordav<='1'; end if;

g_word:="0000000"& bctmp & sumtmp & input_u_i_s(46 downto 45)& input_t_i_s(47 downto 45)& 
			input_s_i_s(47 downto 45)& input_r_i_s(47 downto 45);


-- debug
if sl_dav='0' then gcnt:=x"00000"; else gcnt:=gcnt+'1'; end if; 
if control_reg(12)='1' then g_word:=gcnt; end if;
if control_reg(14)='1' then g_word:=x"0000"&'0'&extroi(2 downto 0); end if;



roc_spydat<= "000" & g_word(12 downto 0);
roi_dat_int <=	  x"000" &'0' & davtmp(4 downto 0)& g_word(1 downto 0);

if GLINK_CTRL(9)='1' or  GLINK_CTRL(7)='1' then g_word:=lfsr; end if;


--glink(19 downto 0)<=	 g_word	;
jet_l(69 downto 50)<=	 g_word	;
if GLINK_CTRL(9)='0'and GLINK_CTRL(8)='0' then sl_dav := davtmp(4); else sl_dav :='1'; end if;

if control_reg(14)='1' then sl_dav := extroi(3); end if;


dav_int<=sl_dav;
SL_nDAV<= not SL_DAV ;

G_LINK_STATUS <= "00000" & SL_LOCKED;

--sdavtmp:=	sum_dav;
--bctmp:=	BC_SLICE;	
--sumtmp:=	SMM_SLICE;

sdavtmp:=sdavtmp1	;
bctmp:=bctmp1	;	
sumtmp:=sumtmp1	;

sdavtmp1:=	sum_dav;
bctmp1:=	BC_SLICE;	
sumtmp1:=	SMM_SLICE;




	for i in 0 to 15 loop
		g_word1(i):=g_word(15-i);
	end loop;

	if g_new_module='0' then 	g_word1:= g_word; end if;   -- for old 20 bit'er and 16 bit'er 
-- g_word1:= g_word;    --  for new 16-bit'er only

-- g-link fifo write
if fcnt=14 then fcnt:=0; else fcnt:=fcnt+1; end if;
if sl_dav='1' and ldav='0' then fcnt :=0; end if;
g_fifo(fcnt)<=(sl_dav and not ldav) & sl_dav & g_word1(15 downto 0);

						 		 	  	  
ldav:=sl_dav;
end if;


if falling_edge(clk40) then
sl_dav1:= sl_dav;
if g_new_module='0' then sl_dav1:=not sl_dav; end if;
if g_bunch_clock_mode then	glink(25)<=    sl_dav1;	  end if;
if g_bunch_clock_mode then	glink(15 downto 0)<=	 g_word1(15 downto 0)	; 	end if;
end if;
end process;


process(glck)
variable pipe : std_logic_vector(5 downto 0);
variable fcnt: integer range 0 to 14 :=0;
variable fout : std_logic_vector(17 downto 0);
variable fout1 : std_logic_vector(15 downto 0);
variable davtmp,davtmp1 : std_logic;

begin
if falling_edge(glck) then

	pipe:=dav_int & pipe(5 downto 1);

	if fout(16)='0' then davtmp:='0' ;end if;
--	if fout(17)='1' then davtmp:='1' ;end if;
	davtmp1:=davtmp;
	if g_new_module='0' then davtmp1:=not davtmp;end if;
	if not g_bunch_clock_mode then glink(25)<=  davtmp1;  end if;

	if not g_bunch_clock_mode then	glink(15 downto 0)<=	fout(15 downto 0);	end if;

	
	if fcnt=14 then fcnt:=0; else fcnt:=fcnt+1; end if;
	if pipe(0)='0' and pipe(1)='1' then  fcnt:=0; end if;
	fout:=g_fifo(fcnt);
	if pipe(0)='0' and pipe(1)='1' then  davtmp:='1' ; end if;



end if;
end process;



----------------------------------------------------------------------------
--VME READ_OUT:
----------------------------------------------------------------------------


--LFSR
process (CLK40)
begin
   if CLK40'event and CLK40='1' then  
      lfsr <=  lfsr(19 downto 1) & not ( lfsr(20) xor lfsr(17));   --taps and XNOR according to Xilinx xapp210   
   end if;
end process;

		
-- l1acc LED
process(CLK40)
variable led_cnt : integer range 0 to ledon;
variable led_sig : std_logic;
begin
	if clk40'event and clk40='1' then
	  led_sig:='0';
--      if L1A_SIG = '1' then led_cnt:=0; end if; 
      if RST_BC = '1' then led_cnt:=0; end if; 
	  if led_cnt/=ledon then
   		led_cnt:=led_cnt+1; 
		led_sig:='1';
	  end if;

--	  HEADER05<=led_sig;
--	  header12<=rst_bc;

  	end if;
end process;

process(CLK40)			  -- reset G-links at startup
variable cnt_tmp : integer range 0 to 50 :=0;
variable rst_tmp : std_logic :='0';
begin
if clk40'event and clk40='1' then
	if cnt_tmp/=50 then  cnt_tmp:=cnt_tmp+1; else rst_tmp:='1'; end if;
	sl_RST<=rst_tmp;
end if;
end process;



L1A_SIG_TMP<=ttc_tmp(41);	--L1_ACCEPT;
RST_BC<=ttc_tmp(38);	--BC_RESET;
L1A_SIG<=L1A_SIG_TMP or L1A_sim;
----------------------------------------------------------------------
----------------READ_REQUEST SIGNAL-----------------------------------
----------------------------------------------------------------------
process (CLK40)
variable cntmp : integer range 0 to 7 :=0;
variable latmp,rqtmp : std_logic;
variable bctmp:integer range 0 to 4095 :=0;
begin
if rising_edge(CLK40) then



	SL_LATENCY_SRL(63 downto 0) <= SL_LATENCY_SRL(62 downto 0) & L1A_SIG;
	latmp:=SL_LATENCY_SRL(conv_integer(SL_LATENCY));
	rqtmp:='0';
  	if latmp='1' then cntmp:=conv_integer(rreq_def); end if;
	if cntmp/=0 then
		cntmp:=cntmp-1;
      rqtmp:='1';
	end if;
-- bunch count
	if rst_bc='1' then 
		bctmp:=conv_integer(bc_OFFSET);
	elsif bctmp=lhc_cycles-1 then
		bctmp:=0;
	else
		bctmp:=bctmp + 1;
	end if;
-- if we want to latch we need to do so after DAQ-internal latency pipeline
-- therefore we need to set the pipe depth to 1 (not 0!) and cover the pipe depth
-- by software  / bunch count offset, or modify (add generic) DAQ to latch upon 1st tick of RREQ
--	if latmp='1' then BC_NUMBER <= conv_STD_LOGIC_VECTOR(bctmp,12); end if;
	BC_NUMBER <= conv_STD_LOGIC_VECTOR(bctmp,12);
	read_request<=rqtmp;

jet_l(14)<=	read_request;
input_r_o(52)<=read_request;
input_s_o(52)<=read_request;
input_t_o(52)<=read_request;
input_u_o(52)<=read_request;


end if;
end process;

------------------------------------------------------------------------------
------------------------ BC_NUMBER to DAQ -------------------------------
------------------------------------------------------------------------------

process(clk40)
variable jetpipe, sumpipe : arr_twentyfive(15 downto 0);
begin
if rising_edge(clk40) then
jetpipe:=  jetpipe(14 downto 0) & jmm;
sumpipe:= sumpipe(14 downto 0) & smm_int;

--rtd_data<=SMM_int & zero25; 		  -- insert JMM signal here


rtd_data<=sumpipe(conv_integer(latcorr(7 downto 4))) & jetpipe(conv_integer(latcorr(3 downto 0))); 

end if;
end process;


l_DAQ_smm: daq 
				generic map
				( pipe_depth=>latency_pipe-rtdp_latency)
				port map
				(--general signals:
				clk=>CLK40,reset=>RESET,
				---Input:
				rtd_data=>rtd_data,read_request=>READ_REQUEST,
				---Output:
				data_valid=>sum_dav,daq_out=>SMM_SLICE,
				---VME_Signals:
				full=>open
				);
																									

l_DAQ_bcnt: daq 
generic map 	 
--(data_width => 12) -- temporary fix at RAL
(pipe_depth=>latency_pipe-rtdp_latency,data_width => 12, latch_data=>true)
port map (--general signals:
		  clk=>CLK40,reset=>RESET,
		  rtd_data=>BC_NUMBER,read_request=>read_request,
		  data_valid=>open,daq_out=>BC_SLICE,full=>open);



---------------------------------------------------------------------

-- test registers

process(clk40)
begin
if rising_edge(clk40) then
if L1A_SIG='1' then cnt_reg1<= cnt_reg1+1;end if;
if RREQ_SL='1' then cnt_reg2<= cnt_reg2+1;end if;
if dvalid(5)='1' then cnt_reg3<= cnt_reg3+1;end if;

extroi<=jet_h(28 downto 25);
jet_l(77)<=g_new_module;

end if;
end process;
S_DATA_IN<=w_dat(11 downto 0);
------------------------ DAQ signal map ---------------------

glink(19)<=g_new_module;	--div0, 0 for old, 1 for new module
glink(18 downto 16)<=(others=>'0') ;	


glink(20)<=glck;	-- was "Locked", used on old module only (remove R on new module!)

--SL_LOCKED	<= glink(20);
--glink(21)<= '1'; -- SL_LOOPEN 	  electrical
glink(21)<= '0'; -- SL_LOOPEN 	  optical
g_new_module<=glink(22); --was SL_MDFSEL , now forced 0 on old module
glink(23)<= '1' ; --SL_M20SEL used on old board only
glink(24)<= SL_RST ;

jet_l(71)<= '1'; -- SL_LOOPEN 
jet_l(72)<= '0'; --SL_MDFSEL 
jet_l(73)<= '1'; --SL_M20SEL 
jet_l(74)<= SL_RST ;
jet_l(75)<=  SL_nDAV ;
--glink(25)<=  SL_nDAV ;


process(clk_des2)
variable cnt: integer range 0 to 20000000	:=0;
variable ledsig : std_logic;
begin
if rising_edge(clk_des2) then

if cnt= 20000000 then cnt:=0; ledsig:='0';else cnt:=cnt+1; end if;
if cnt= 10000000 then ledsig:='1'; end if;

control_sum(9)<=ledsig;
end if;
end process;

glck<=clk40 when g_bunch_clock_mode else x40 ;
--glck<=clk40;
--glck<=TCLKIN_w;
glink_clock<= glck;
jet_l(76)<=glck;
end Behavioral;

--23. 22 21 20 19. 18 17. 16 15 14 13 .12 11 10 9 8 7 6 5 4 3 2 1

--  1	JEM Base ad	 mode   FPGA sub add   Register address 

