-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.

-- Copyright (C) 1991-2004 Altera Corporation
-- Any  megafunction  design,  and related netlist (encrypted  or  decrypted),
-- support information,  device programming or simulation file,  and any other
-- associated  documentation or information  provided by  Altera  or a partner
-- under  Altera's   Megafunction   Partnership   Program  may  be  used  only
-- to program  PLD  devices (but not masked  PLD  devices) from  Altera.   Any
-- other  use  of such  megafunction  design,  netlist,  support  information,
-- device programming or simulation file,  or any other  related documentation
-- or information  is prohibited  for  any  other purpose,  including, but not
-- limited to  modification,  reverse engineering,  de-compiling, or use  with
-- any other  silicon devices,  unless such use is  explicitly  licensed under
-- a separate agreement with  Altera  or a megafunction partner.  Title to the
-- intellectual property,  including patents,  copyrights,  trademarks,  trade
-- secrets,  or maskworks,  embodied in any such megafunction design, netlist, 
-- support  information,  device programming or simulation file,  or any other
-- related documentation or information provided by  Altera  or a megafunction
-- partner, remains with Altera, the megafunction partner, or their respective
-- licensors. No other licenses, including any licenses needed under any third
-- party's intellectual property, are provided herein.


-- Generated by Quartus II Version 4.1 (Build Build 181 06/29/2004)
-- Created on Wed Sep 22 10:39:11 2004


LIBRARY IEEE ;
LIBRARY lpm ;

USE     IEEE.std_logic_1164.all ;
USE     IEEE.numeric_std.all;
USE     lpm.lpm_components.ALL;
use work.Types.all;

--  Entity Declaration

ENTITY VME_CONTROLLER IS
	-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
	PORT
	(
		reset       : in std_logic;
	    CLK           : in std_logic;  -- 50MHz PCI clock, same as for CPLD
--	VME signals
		v_am : IN STD_LOGIC_VECTOR(5 downto 0);
		n_v_ds : IN STD_LOGIC_VECTOR(1 downto 0);
		n_v_as : IN STD_LOGIC;
		n_v_lw : IN STD_LOGIC;
		n_v_iackin : IN STD_LOGIC;
		n_v_write : IN STD_LOGIC;
		n_v_sys_res : IN STD_LOGIC;
		v_dtack : OUT STD_LOGIC;
		v_berr : OUT STD_LOGIC;
		n_v_irq : OUT STD_LOGIC;
		n_v_iackout : OUT STD_LOGIC;
		v_ddir : OUT STD_LOGIC;
		n_v_doe : OUT STD_LOGIC_VECTOR(1 downto 0);
		va : IN STD_LOGIC_VECTOR(23 downto 1);
		vd : INOUT STD_LOGIC_VECTOR(31 downto 0);
		
		ModuleAddr    : in std_logic_vector(7 downto 0 );
		
-- spi interface for accessing the processor and serial number chip
        spi_CS      : in std_logic;          -- SPI slave select
        SPI_SI      : in  std_logic;           -- slave in
        SPI_SO      : out std_logic;           -- slaveout
        SPI_CLK     : in std_logic;         -- slave clock
		SPI_INT		: out std_logic;		-- SPI command interrupt for AVR
		
		CPLD_STAT	   : out   std_logic;  -- RS232 ifc indicator
		
		EXT_out : OUT STD_LOGIC_VECTOR(9 downto 1);
		test_out : OUT STD_LOGIC_VECTOR(31 downto 16);
		RSV : OUT STD_LOGIC_VECTOR(6 downto 0);

  -- fpga programming pins: active serial and passive serial
        fpga_nconfig  : out std_logic;  -- nconfig pulled low forces configuration
        fpga_nce      : out std_logic;  -- nce pulled high turns off the fpga
        as_asdo       : out   std_logic;       -- AS data out for the EPCS memory
        as_data       : in  std_logic;     -- AS data for the memory
        as_dclk       : out std_logic;       -- AD data for the memory
        as_ncs        : out std_logic;       -- chip select for activeserial memory
		
  --  PCI-like multiplexed communication
  -- address/data bus is 16 bit wide, BE0,BE1 are used as data strobes and command lines like in PCI
        IRDYn      	: out   std_logic;   -- CPLD not ready
        TRDYn      	: in    std_logic;   -- FPGA not ready
        FRAMEn     	: out   std_logic;   -- start of transfer
        AD         	: inout std_logic_vector(15 downto 0);       -- muletiplexed PCI-like address and data
        BEn      	: out   std_logic_vector(1 downto 0);    	 -- word strobes / command: 01- read, 11 - write
		INTn		: in 	std_logic	--interrupt
		
	);
	-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
	
END VME_CONTROLLER;


--  Architecture Body

ARCHITECTURE VME_CONTROLLER_architecture OF VME_CONTROLLER IS

-------------------------------------------------------------------------------
-- declaration of components used
-------------------------------------------------------------------------------
    -- as programmer
     component as_programmer
       port (
	     testout    : out std_logic;
         clk          : in  std_logic;
         reset        : in  std_logic;
         fpga_nconfig : out std_logic;
         fpga_nce     : out std_logic;
         as_asdo      : out std_logic;       -- AS data out for the EPCS memory
         as_data      : in  std_logic;     -- AS data for the memory
         as_dclk      : out std_logic;       -- AD data for the memory
         as_ncs       : out std_logic;       -- chip select for activeserial memory
         dataIn       : in  std_logic_vector(31 downto 0);
         dataOut      : out std_logic_vector(7 downto 0);             -- every data read are just 8 bits
         dataRdy      : out std_logic;
         startRead    : in  std_logic;
         startWrite   : in  std_logic);
     end component;

     -- spi interface:
  component spi_link
    port (
      clk         : in  STD_LOGIC;
      reset       : in  STD_LOGIC;
      SCK         : in  STD_LOGIC;
      SDI         : in  STD_LOGIC;
      SDO         : out STD_LOGIC;
      SCS         : in  std_logic;
      data_in     : in  STD_LOGIC_VECTOR (7 downto 0);
      data_out    : out STD_LOGIC_VECTOR(7 downto 0);
      command_out : out STD_LOGIC_VECTOR(7 downto 0);
      write_en    : out STD_LOGIC;
	  transfer_done : out STD_LOGIC;
      byte_sel    : out STD_LOGIC_VECTOR (3 downto 0);
	  addr_sel : out STD_LOGIC_VECTOR (1 downto 0);
	  testout  : out STD_LOGIC_VECTOR (7 downto 0)
		);
  end component;

      


------------------------------------------------------------------------------
-- declaration of signals
-------------------------------------------------------------------------------
----------------------
-- Signal Declaration
----------------------
 Constant setad : std_logic_vector(23 downto 0) := x"ff0000";    --board base address
-- VME Signals 
  SIGNAL v_adsel,
			resetn        : STD_LOGIC ;
  SIGNAL valid_am,
			blt,blt_flag        : STD_LOGIC ;
  SIGNAL valid_address    : STD_LOGIC ;
  SIGNAL ad_reg            : STD_LOGIC_VECTOR (15 DOWNTO 0);


-- Internal Registers
  SIGNAL int_ad_reg       : STD_LOGIC_VECTOR (11 DOWNTO 0);
  SIGNAL data_reg         : STD_LOGIC_VECTOR (31 DOWNTO 0);
  SIGNAL intbus           : STD_LOGIC_VECTOR (31 DOWNTO 0);                                                          

-- Readout signals
  SIGNAL data_buffer_oe_0 : STD_LOGIC;
  SIGNAL data_buffer_oe_1 : STD_LOGIC;
  SIGNAL int_dtack,
		data_wren        : STD_LOGIC;
  signal VME_BE_command	: STD_LOGIC_VECTOR(4 downto 0);	
  SIGNAL IFC_data           : STD_LOGIC_VECTOR (31 DOWNTO 0); 
  SIGNAL IFC_address            : STD_LOGIC_VECTOR (15 DOWNTO 0);
  SIGNAL IFC_valid_address : STD_LOGIC;
 

--SPI block signals
	signal  spi_data_in : std_logic_vector(7 downto 0);
    signal  spi_data_out,SPI_testout : std_logic_vector(7 downto 0);
    signal  spi_write_en, spi_transfer_done : std_logic;
    signal  spi_byte_sel : std_logic_vector(3 downto 0);
    signal  spi_addr_sel : std_logic_vector(1 downto 0);
	signal  spi_command_out : std_logic_vector(7 downto 0);
	signal  spi_address : std_logic_vector(15 downto 0);
	signal  SPI_data_o,SPI_data_i : std_logic_vector(31 downto 0);
	SIGNAL  Controlled_by_SPI, SPI_valid_address    : STD_LOGIC ;  

  signal programmingFinished,
		 writeProgrammerData,
    	 readProgrammerData      : std_logic;
-- '1' announces that the operation of programmer is finished and thus
-- we can pull dtack low in order to finish the write operation

  signal programmerData,ProgrammerData_in,
			CPLD_Config,
			CPLD_Status           : std_logic_vector(31 downto 0);
			
-- address decoder signals
	signal 	SERIALaddressed,
			CPLD_CFG_addressed,
			SPIaddressed,
			ProgrammerAddressed,
			n_v_write_synchr, 
			CPLD_addressed  : std_logic;
  signal    n_v_ds_synchr        : std_logic_vector(1 downto 0);			
		

  signal SPI_data :  std_logic_vector(31 downto 0) ;
  
	signal	SERIAL_data,
			FPGA_AD :  std_logic_vector(31 downto 0) ;

--VME-PCI state machine

	TYPE STATE_TYPE IS (
	idle,
	address_phase,
	SPI_selected,
	SPI_address_phase,
	data_MSB_phase_WR,
	data_LSB_phase_WR,
	data_MSB_phase_RD,
	data_LSB_phase_RD,
    generate_DTACK,
	go_burst			
	);

	SIGNAL state: STATE_TYPE;


BEGIN


--------------------
-- Logic Section
--------------------

  ad_reg(0) <= '0';

--controller responds to some subset of transfers only
  valid_am  <= '1' 	WHEN (( v_am (5 DOWNTO 0) = "111001" ) 
                    OR   ( v_am (5 DOWNTO 0) = "111010" ) 
                    OR   ( v_am (5 DOWNTO 0) = "111101" ) 
                    OR   ( v_am (5 DOWNTO 0) = "111110" ) 
                    OR   ( v_am (5 DOWNTO 0) = "111011" ) 
                    OR   ( v_am (5 DOWNTO 0) = "111111" ))
          			ELSE '0';

--block transfer detection
  blt       <= '1' 	WHEN  ((( v_am (5 DOWNTO 0) = "111011" ) OR   ( v_am (5 DOWNTO 0) = "111111" ))) ELSE '0';
-- controller selected
  v_adsel  <=     '1' WHEN (( va ( 23 DOWNTO 16 )) = (ModuleAddr(7 downto 0))) ELSE '0';


Address_gen : PROCESS (CLK, n_v_sys_res)
BEGIN
--address latching
  	IF   n_v_sys_res = '0' THEN
    		valid_address  <= '0';   
    		ad_reg (15 DOWNTO 1) <= (OTHERS => '0');
  	ELSIF   Rising_edge (CLK ) THEN 
	    IF  n_v_as  ='0' AND valid_am = '1' AND v_adsel ='1' THEN  
	    			ad_reg (15 DOWNTO 1) <= va (15 DOWNTO 1); 
		END IF;
--valid address generation		
	    IF ( n_v_as AND n_v_ds (1) AND n_v_ds (0)) =  '1'  THEN 
	    	valid_address <= '0';
	    ELSIF (not n_v_as AND valid_am AND v_adsel ) = '1'  OR valid_address = '1' THEN   
	    	valid_address <= '1';
	    END IF;
	-- block trnasfer flag genration
    	IF n_v_as = '1' THEN 
			blt_flag  <=   '0' ;
    	ELSIF  ( blt AND v_adsel AND NOT n_v_as ) = '1' THEN 
			blt_flag  <=   '1'; 
    	END IF;
	
  	END IF;
END PROCESS Address_gen;

-- VME BERR Generation 

  v_berr       <= '0';

-- VME IRQ Generation 

  n_v_irq      <= '0';
  n_v_iackout  <= not n_v_iackin;

-------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------  VME-PCI state machine   -----------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------
		
		
--VME signals synchronisation:
PROCESS (clk)
	BEGIN
	IF clk'EVENT AND clk = '0' THEN
		n_v_ds_synchr <= n_v_ds;
		n_v_write_synchr <= n_v_write;
	end if;
end process;	
		
  
PROCESS (clk,reset)
	BEGIN
		IF reset = '1' or IFC_valid_address = '0' THEN
		--IF reset = '1' THEN
			state <= idle;
		ELSIF clk'EVENT AND clk = '1' THEN	
				CASE state IS
					WHEN idle =>
						IF valid_address = '1' and (n_v_ds_synchr(1) ='0' or n_v_ds_synchr(0) = '0') THEN
							Controlled_by_SPI <= '0';
							state <=address_phase;
						elsif 	spi_addr_sel(0) = '1' then   --start PCi transaction just after latching first address
							Controlled_by_SPI <= '1';
							state <=SPI_Selected;
						END IF;
						
					when address_phase =>
 						IF  valid_address = '1' and (n_v_ds_synchr(1) ='0' or n_v_ds_synchr(0) = '0') and n_v_write_synchr = '0' THEN
							state <=data_MSB_phase_WR;	--start PCI write
						ELSIF  valid_address = '1' and (n_v_ds_synchr(1) ='0' or n_v_ds_synchr(0) = '0') and n_v_write_synchr = '1' THEN
							state <=data_MSB_phase_RD;	--start PCI read	
						ELSE
							state <= idle;
						END IF;
						
					when SPI_Selected => 
						if spi_command_out(7)= '0' or (spi_command_out(7)= '1' and spi_byte_sel(0) = '1' and spi_write_en = '1') then
							state <= SPI_address_phase;
						end if;
						
					when SPI_address_phase =>
						if spi_command_out(7)= '0' then
							state <=data_MSB_phase_RD;	--start PCI read				
 						ELSe --make sure that all the data is latched
							state <=data_MSB_phase_WR;	--start PCI write								
						END IF;	

	----------------------------- PCI-like write trnsaction
						
						
					when data_MSB_phase_WR =>
						if CPLD_addressed = '1' then -- CPLD registers transfer - bypass all PCI transaction mechanism
							state <= generate_DTACK;
		 				elsIF  TRDYn = '0' THEN		--wait until target gets ready
							state <=data_LSB_phase_WR;
						ELSIF IFC_valid_address = '0' then
							state <= idle;
						END IF;
						
					when data_LSB_phase_WR =>  
						IF IFC_valid_address = '0' then
							state <= idle;
						ELSif ProgrammerAddressed = '0' and TRDYn = '0' then
--						if ProgrammerAddressed = '0' and TRDYn = '0' then
							state <= generate_DTACK;
						elsif ProgrammerAddressed = '1' and programmingFinished = '1' then  --hold data ACK until serial trnasfer is completed
							state <= generate_DTACK;
						END IF;	

	------------------------------- PCI-like read trnsaction
						
						
						
					when data_MSB_phase_RD =>
						if CPLD_addressed = '1' then -- CPLD registers transfer - bypass all PCI transaction mechanism
							state <= generate_DTACK;
		 				elsIF  TRDYn = '0' THEN		--wait until target gets ready
							state <=data_LSB_phase_RD;
						ELSIF IFC_valid_address = '0' then
							state <= idle;
						END IF;
						
					when data_LSB_phase_RD =>  
						IF IFC_valid_address = '0' then
							state <= idle;
						ELSif (ProgrammerAddressed = '0' and TRDYn = '0') then  
						--if (ProgrammerAddressed = '0' and TRDYn = '0') then  
							state <= generate_DTACK;
						elsif ProgrammerAddressed = '1' and programmingFinished = '1' then --hold data ACK until serial trnasfer is completed
							state <= generate_DTACK;
						END IF;
	


	----------------------------- PCI-like transaction end or block trnasfers
						

					when generate_DTACK => 
						if Controlled_by_SPI = '1' then
							state <= idle;
						elsif IFC_valid_address = '0' then
							state <= idle;
						elsif (CPLD_addressed = '1' and n_v_ds_synchr(1) ='1' and n_v_ds_synchr(0) = '1') then  -- CPLD transfer only
							state <= idle;
						elsif (n_v_ds_synchr(1) ='1' and n_v_ds_synchr(0) = '1') and blt_flag = '1' THEN	--block transfers
							state <= go_burst;
						elsif (n_v_ds_synchr(1) ='1' and n_v_ds_synchr(0) = '1') THEN	--non-block transfers
							state <= idle;
						END IF;
						
					when go_burst => --block transfers only -wait for the next data cycle
						IF  IFC_valid_address = '1' and (n_v_ds_synchr(1) ='0' or n_v_ds_synchr(0) = '0') and n_v_write_synchr = '0' THEN
							state <=data_MSB_phase_WR;	--start PCI write
						ELSIF  IFC_valid_address = '1' and (n_v_ds_synchr(1) ='0' or n_v_ds_synchr(0) = '0') and n_v_write_synchr = '1' THEN
							state <=data_MSB_phase_RD;	--start PCI read
						elsif IFC_valid_address = '0' then
							state <= idle;
						END IF;	
						
							
					when others =>
							state <=idle;

						


				END CASE;
		END IF;
	END PROCESS;


	WITH state  SELECT
		IRDYn 	<=			'1' when address_phase,
							'1' when SPI_address_phase,
							'0' when data_MSB_phase_WR,							
							'0' when data_LSB_phase_WR,
							'0' when data_MSB_phase_RD,							
							'0' when data_LSB_phase_RD,	
							'1' when go_burst,													
							'1' when others;

	WITH state  SELECT
		FRAMEn 	<=			'0' when address_phase,
							'0' when SPI_address_phase,
							'0' when data_MSB_phase_WR,							
							'0' when data_LSB_phase_WR,
							'0' when data_MSB_phase_RD,							
							'0' when data_LSB_phase_RD,	
							'0' when generate_DTACK,	
							'0' when go_burst,					
							'1' when others;
							
	WITH state  SELECT
		BEn 	<=			(not n_v_write_synchr) & '1' 	when address_phase,
							(spi_command_out(7)) & '1' 		when SPI_address_phase,
							(not spi_command_out(7)) & '1'		when SPI_Selected,
											"01" 			when data_MSB_phase_WR,							
											"10"			when data_LSB_phase_WR,
											"01"			when data_MSB_phase_RD,							
											"10"			when data_LSB_phase_RD,							
											"11"			when others;
	WITH state  SELECT
	v_dtack 	<=			'1' when generate_DTACK,		--dtack is inverted (ext inverter)						
							'0' when others;
								
	WITH state  SELECT
	data_wren 	<=			'1' when data_MSB_phase_WR,		--data strobe for VME registers					
							'0' when others;

	WITH state  SELECT
		AD 	<=			"00" & IFC_address(15 downto 2) 	when 	address_phase,
						"00" & IFC_address(15 downto 2) 	when	SPI_address_phase,
						"00" & IFC_address(15 downto 2)		when 	SPI_Selected,
						IFC_data(31 downto 16)				when 	data_MSB_phase_WR,							
						IFC_data(15 downto 0)				when 	data_LSB_phase_WR,
						(others => 'Z') 					when	data_MSB_phase_RD,							
						(others => 'Z') 					when 	data_LSB_phase_RD,	
						(others => 'Z') 					when 	generate_DTACK,						
						(others => 'Z') 					when 	others;

-------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------  FPGA read data buffer   -----------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------
PROCESS (CLK,  n_v_sys_res)
begin
	if  n_v_sys_res = '0'  THEN 
			FPGA_AD <= (others => '0');
	ELSIF Rising_edge ( CLK ) THEN
		if  state = data_MSB_phase_RD and TRDYn = '0' then
			FPGA_AD(31 downto 16) <= AD;
		elsif  state = data_LSB_phase_RD and TRDYn = '0' then
			FPGA_AD(15 downto 0) <= AD;
		end if;
	end if;
end process;





-------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------ Data Buffer Chip Control -----------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------
-- one CLK period delay od output enable lines to increase data hold time
process (clk, n_v_sys_res)
begin
	if  n_v_sys_res = '0'  THEN 
		VME_BE_command <= (others => '1');
	elsif rising_edge(clk) then
		VME_BE_command	<=  n_v_ds(1) & n_v_ds(0) & va(1) & n_v_lw & n_v_write;
	end if;	
end process;

--		CPLD_3_state_buffer0_control:
		with VME_BE_command select
		 	data_buffer_oe_0 <=  valid_address when "00011",	--byte 01
								 valid_address when "00001",	--bytes 0123
								 '0' when others;
								
--		CPLD_3_state_buffer1_control:
		with VME_BE_command select
		 	data_buffer_oe_1 <=  valid_address when "00111",	--byte 23
								 valid_address when "00001",	--bytes 0123
								 '0' when others;						           
		 
--		VME_card_3_state_buffer0_control:
		with VME_BE_command(4 downto 1) select
		 	n_v_doe (0) <=  	(not valid_address) when "0001",	--byte 01
								(not valid_address) when "0000",	--bytes 0123
								 '1' when others;
								
--		VME_card_3_state_buffer1_control:
		with VME_BE_command(4 downto 1) select
		 	n_v_doe (1) <=  	 (not valid_address) when "0011",	--byte 23
								 (not valid_address) when "0000",	--bytes 0123
								 '1' when others;

--VME buffers direction
v_ddir       <= NOT n_v_write;


-- VME 3 state buffer
lo_data_bus_driver : lpm_bustri 
  GENERIC MAP (LPM_WIDTH  => 16
              )
  PORT MAP    (data       => intbus ( 15 DOWNTO 0),
               enableDT   => data_buffer_oe_0,
               enableTR   => '1',
               tridata    => vd ( 15 DOWNTO 0)
               );

hi_data_bus_driver : lpm_bustri 
  GENERIC MAP (LPM_WIDTH  => 16
              )
  PORT MAP    (data       => intbus ( 31 DOWNTO 16),
               enableDT   => data_buffer_oe_1,
               enableTR   => '1',
               tridata    => vd ( 31 DOWNTO 16)
               );

-------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------ SPI/VME multiplexer-----------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------


	IFC_data <= vd when Controlled_by_SPI = '0' else SPI_data_o;
	IFC_address <= ad_reg when Controlled_by_SPI = '0' else SPI_address;
	IFC_valid_address <= valid_address or not SPI_CS;
	
	CPLD_STAT <= Controlled_by_SPI AND SPI_CS;

-------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------ address decoder --------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------



  SPIaddressed  		<= '1' WHEN  IFC_valid_address =  '1'  AND "00" & IFC_address( 15 DOWNTO 2 ) = X"3FF0"    ELSE '0'; --FFC0
  ProgrammerAddressed  	<= '1' WHEN  IFC_valid_address =  '1'  AND "00" & IFC_address( 15 DOWNTO 2 ) = X"3FF1"    ELSE '0'; --FFC4
  SERIALaddressed  		<= '1' WHEN  IFC_valid_address =  '1'  AND "00" & IFC_address( 15 DOWNTO 2 ) = X"3FF2"    ELSE '0'; --FFC8
  CPLD_CFG_addressed  	<= '1' WHEN  IFC_valid_address =  '1'  AND "00" & IFC_address( 15 DOWNTO 2 ) = X"3FF3"    ELSE '0'; --FFCC
--skip PCI tranfer when CPLD registers are addressed
  CPLD_addressed <= SPIaddressed or ProgrammerAddressed or 	SERIALaddressed or CPLD_CFG_addressed;

-------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------     CPLD registers write     -----------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------

Wr_Regs : PROCESS  (  n_v_sys_res, CLK )
BEGIN
  IF   n_v_sys_res = '0' THEN 
    SPI_data    <= (OTHERS => '0');      
--    SERIAL_data   <= (OTHERS => '0');
   -- ProgrammerData	<= (OTHERS => '0');
    CPLD_Config    <= (OTHERS => '0');
    
  ELSIF  Rising_edge ( CLK) THEN
		
--writing VME data to registers		

	IF  SPIaddressed  = '1' AND data_wren='1' THEN
	  SPI_data  <=  IFC_data ; 
	END IF;

--	IF  SERIALaddressed  = '1' AND data_wren='1' THEN		--read only
--	  SERIAL_data   <=  IFC_data; 
--	END IF;
  

	IF  CPLD_CFG_addressed  = '1' AND data_wren='1' THEN
	  CPLD_Config   <=  IFC_data ; 
	END IF;
	

  END IF;
END PROCESS Wr_Regs;



-------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------     CPLD registers read      -----------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------


   
  intbus (31 DOWNTO 0) <=   SPI_data  WHEN  SPIaddressed  = '1'
                   	ELSE    SERIAL_data  WHEN  SERIALaddressed  = '1'
--                   	ELSE    ProgrammerData_in  WHEN  ProgrammerAddressed  = '1'
                   	ELSE    x"12345678" WHEN  ProgrammerAddressed  = '1'
                   	ELSE    CPLD_Status  WHEN  CPLD_CFG_addressed  = '1'
					ELSE	FPGA_AD ;			--all other transfers come from FPGA

-------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------     SPI block instantiation  -----------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------




-- spi memory interface accesible via VME
      spi_link_1: spi_link
      port map (
      clk         => clk,
      reset       => reset,
      SCK         => SPI_CLK,
      SDI         => SPI_SI,
      SDO         => SPI_SO ,
      SCS         => SPI_CS,
      data_in     => spi_data_in,
      data_out    => spi_data_out,
      command_out => spi_command_out,
      write_en    => spi_write_en,
	  transfer_done =>  spi_transfer_done,
      byte_sel    => spi_byte_sel,
	  addr_sel	  => spi_addr_sel,
	  testout	  => SPI_testout );






--SPI_data_i <= x"12345677";
	SPI_data_i <= intbus;
--SPi output data register write
 process (reset,Clk)
  begin
  	if reset='1' then
     SPI_data_o <=(others => '0');
  	elsif rising_edge(Clk) then
--latch SPI data
		   	if spi_byte_sel(0) = '1' and spi_write_en = '1' then
				SPI_data_o(7 downto 0) <= spi_data_out;
		    elsif spi_byte_sel(1) = '1' and spi_write_en = '1' then
				SPI_data_o(15 downto 8) <= spi_data_out;		  	
		   	elsif spi_byte_sel(2) = '1' and spi_write_en = '1' then
				SPI_data_o(23 downto 16) <= spi_data_out;
		  	elsif spi_byte_sel(3) = '1' and spi_write_en = '1' then
				SPI_data_o(31 downto 24) <= spi_data_out;
		  	end if;
--latch SPI address
			if spi_addr_sel(0) = '1' then
				SPI_address(7 downto 0) <= spi_data_out;
		    elsif spi_addr_sel(1) = '1'  then
				SPI_address(15 downto 8) <= spi_data_out;	
			end if;		  			
				
  	end if;	
end process;

--SPI COMMAND
with spi_byte_sel select
spi_data_in <= 	SPI_data_i(7 downto 0)   when "0001",
				SPI_data_i(15 downto 8)  when "0010",
				SPI_data_i(23 downto 16) when "0100", 
				SPI_data_i(31 downto 24) when others;
      

process (reset,Clk)
  begin
  	if reset='1' then
     SERIAL_data <=(others => '0');
  	elsif rising_edge(Clk) then
		if SPI_address = X"FFC8" and spi_transfer_done = '1' and spi_command_out(7) = '1' then
			SERIAL_data <= SPI_data_o;
		end if;
	end if;
end process;


SPI_INT <= not (SPIaddressed and not n_v_write);
-------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------- EPCS programmer block instantiation ----------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------


	resetn <= not reset;
	writeProgrammerData <=	ProgrammerAddressed and data_wren;
	readProgrammerData <= ProgrammerAddressed and n_v_write;
 
 -- active serial programmer interface:
      as_programmer_2: as_programmer
        port map (
		  testout      => open,
          clk          => clk,
          reset        => resetn, -- not reset
          fpga_nconfig => fpga_nconfig,
          fpga_nce     => fpga_nce,
          dataIn       => IFC_data,
          dataOut      => ProgrammerData_in(7 downto 0),
		  as_asdo      => as_asdo,
          as_data      => as_data,
          as_dclk      => as_dclk,
          as_ncs       => as_ncs,
          dataRdy      => programmingFinished,
          startRead    => readProgrammerData,
          startWrite   => writeProgrammerData);
 -- process to change the state signal and initialize
 --internal signals



	--test_out(23 downto 16) <= va(23 downto 16);
	--test_out(31 downto 24) <= "00" & v_am (5 DOWNTO 0);
	
--	RSV(3) <=n_v_as ;
--	RSV(4) <=IFC_valid_address ;
--	RSV(5) <=v_adsel ;
--	RSV(6) <=valid_am ;
	
--test_out <= spi_data_in & spi_data_out;
--test_out(16) <= clk;
--test_out(17) <= SERIALaddressed;
--test_out(18) <= IFC_valid_address;
--test_out(19) <= valid_address;
--test_out(20) <= spi_byte_sel(0);
--test_out(21) <= spi_byte_sel(1);
--test_out(22) <= spi_byte_sel(2);
--test_out(23) <= spi_byte_sel(3);
--test_out(24) <= SPI_SI;
--test_out(25) <= SPI_CLK;
--test_out(26) <= Controlled_by_SPI;
--test_out(27) <= spi_write_en;

--test_out(31 downto 28) <= spi_testout(7 downto 4);
test_out(31 downto 16) <= IFC_address;


EXT_out(1) <= clk;
EXT_out(2) <= SERIALaddressed;
EXT_out(3) <= IFC_valid_address;
EXT_out(4) <= Controlled_by_SPI;
EXT_out(5) <= valid_am;
EXT_out(6) <= n_v_as;
EXT_out(7) <= valid_address;
EXT_out(8) <= v_adsel;

--EXT_out(8 downto 5) <= spi_testout(7 downto 4);
--EXT_out <= SERIAL_data(7 downto 0);
  --EXT_out(8 downto 1) <= spi_testout;


--EXT_out <= CPLD_Config (7 downto 0);
	CPLD_Status(7 downto 0) <= CPLD_Config (7 downto 0);
	CPLD_Status(8) <= not SPI_CS;
	
END VME_CONTROLLER_architecture;
