--
-- VHDL Architecture FACT_FAD_lib.spi_distributor.beha
--
-- Created:
--          by - Benjamin Krumm.UNKNOWN (EEPC8)
--          at - 09:24:21 23.04.2010
--
-- using Mentor Graphics HDL Designer(TM) 2009.1 (Build 12)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
LIBRARY FACT_FAD_lib;
USE FACT_FAD_lib.fad_definitions.all;

ENTITY spi_distributor IS

-- TEMP_MEASUREMENT_BEAT * clk ist the measurement period of the 
-- Temperature measurement
-- e.g. 5*10**6 means every second

  GENERIC(
    TEMP_MEASUREMENT_BEAT : integer := 5*10**6
    );

  PORT(
    clk						: IN 			std_logic; 
	
	-- interface nach aussen
    config_start			: IN 			std_logic;
    config_ready			: OUT			std_logic := '1'; 
    
	dac_array				: IN 			dac_array_type;
	current_dac_array		: OUT			dac_array_type := ( others => 0);
	sensor_array			: OUT 			sensor_array_type; 
    sensor_valid			: OUT 			std_logic := '0';
    
	
	sensor_read_start		: OUT			std_logic := '0';
    sensor_read_valid 		: IN			std_logic;
    dac_config_start		: OUT			std_logic := '0';
    dac_config_ready		: IN			std_logic;
	spi_channel_ready		: IN			std_logic;
    
	sclk_enable_override	: OUT			std_logic := '0';
    dac_id					: OUT			std_logic_vector(2 downto 0) := (others => '0');
    sensor_id				: OUT			std_logic_vector(1 downto 0) := (others => '0');
    data					: INOUT			std_logic_vector(15 downto 0) := (others => 'Z');
	measured_temp_data		: IN			std_logic_vector(15 downto 0)
  );
END ENTITY spi_distributor;

ARCHITECTURE beha OF spi_distributor IS

  type TYPE_SPI_DISTRIBUTION_STATE is (INIT, IDLE, 
		PRE_READ_SENSOR, 
		SENSOR_READ_START_ACK,
		READ_SENSOR, 
		PRE_CONFIG_DAC,
		DAC_CONFIG_START_ACK,
		CONFIG_DAC);
    
  signal spi_distr_state       : TYPE_SPI_DISTRIBUTION_STATE := INIT;
  signal int_sensor_read_start : std_logic := '0';
  signal int_sensor_valid      : std_logic := '0';
  signal int_sensor_array      : sensor_array_type;
  signal sensor_id_cnt         : integer range 0 to 4 := 0;
  signal dac_id_cnt            : integer range 0 to 7 := 0;
  
  signal internal_dac_array : dac_array_type;
  signal sclk_enable_override_sig : std_logic := '0';
  
  -- synching signals
  signal config_start_sr 		: std_logic_vector (1 downto 0) := "00";
  
  
  signal sensor_read_valid_sr : std_logic_vector (1 downto 0) := "00";
  signal dac_config_ready_sr :  std_logic_vector (1 downto 0) := "00";
  signal spi_channel_ready_sr :  std_logic_vector (1 downto 0) := "00";
  
BEGIN
  sclk_enable_override <= sclk_enable_override_sig;
  
  spi_distribute_proc: process (clk)
  begin
    
    
    if rising_edge(clk) then
		sensor_read_valid_sr <= sensor_read_valid_sr(0) & sensor_read_valid;
		dac_config_ready_sr <= dac_config_ready_sr(0) & dac_config_ready;
		spi_channel_ready_sr <= spi_channel_ready_sr(0) & spi_channel_ready;
		-- synch in
		config_start_sr <= config_start_sr(0) & config_start;
		
      data <= (others => 'Z');
      case spi_distr_state is
        when INIT =>
          data <= (others => 'Z');
          int_sensor_valid <= '0';
          spi_distr_state <= PRE_READ_SENSOR;
		  
        when IDLE =>
			sclk_enable_override_sig <= '0';
          if (int_sensor_valid = '1') then
            sensor_array <= int_sensor_array;
            sensor_valid <= '1';
          end if;
          data <= (others => 'Z');
         -- start DAC configuration
          if (config_start_sr(1) = '1' AND int_sensor_valid = '1') then
			internal_dac_array <= dac_array;
            spi_distr_state <= PRE_CONFIG_DAC;
          -- start temperature sensor reading
          elsif (dac_config_ready <= '1' AND int_sensor_read_start = '1' ) then
			spi_distr_state <= PRE_READ_SENSOR;
          end if;
		
		when PRE_READ_SENSOR =>
			
            int_sensor_valid <= '0';
            sensor_read_start <= '1';
            sensor_id <= conv_std_logic_vector(sensor_id_cnt, sensor_id'length);
			spi_distr_state <= SENSOR_READ_START_ACK;
		
		when SENSOR_READ_START_ACK =>
			if (spi_channel_ready_sr(1) = '0') then
				sensor_read_start <= '0';
				spi_distr_state <= READ_SENSOR;
			end if;
	   
		when PRE_CONFIG_DAC =>
			config_ready <= '0';
			sclk_enable_override_sig <= '1';
            dac_config_start <= '1';
            dac_id <= conv_std_logic_vector(dac_id_cnt, dac_id'length);
            data <= conv_std_logic_vector(internal_dac_array(dac_id_cnt),data'length);
            spi_distr_state <= DAC_CONFIG_START_ACK;
			
			
		when DAC_CONFIG_START_ACK =>
			dac_id <= conv_std_logic_vector(dac_id_cnt, dac_id'length);
            data <= conv_std_logic_vector(internal_dac_array(dac_id_cnt),data'length);
			
			if (spi_channel_ready_sr(1) = '0') then
				dac_config_start <= '0';
				spi_distr_state <= CONFIG_DAC;
			end if;
	   
        -- sensor reading   
        when READ_SENSOR =>

			if (sensor_read_valid_sr(1) = '1') then
				int_sensor_array(sensor_id_cnt) <= conv_integer(measured_temp_data);
				--sensor_read_start <= '0';
				if (sensor_id_cnt < 3) then
					sensor_id_cnt <= sensor_id_cnt + 1;
					--sensor_read_start <= '1';
					spi_distr_state <= PRE_READ_SENSOR;
				else
					sensor_id_cnt <= 0;
					sensor_valid <= '0';
					int_sensor_valid <= '1';
					spi_distr_state <= IDLE;
				end if;
			end if;
        
		
		  
		
        -- DAC configuration
        when CONFIG_DAC =>
          --dac_config_start <= '1';
          --dac_id <= conv_std_logic_vector(dac_id_cnt, dac_id'length);
          --data <= conv_std_logic_vector(internal_dac_array(dac_id_cnt),data'length);
          --if (dac_config_ready = '1') then
		  if (spi_channel_ready_sr(1) = '1') then
            --dac_config_start <= '0';
            if (dac_id_cnt < 7) then 
              dac_id_cnt <= dac_id_cnt + 1;
              --dac_config_start <= '1';
              spi_distr_state <= PRE_CONFIG_DAC;
            else
              dac_id_cnt <= 0;
              config_ready <= '1';
			  current_dac_array <= internal_dac_array;
              spi_distr_state <= IDLE;
            end if;
          end if; 
      end case;  
    end if;
    
  end process spi_distribute_proc;

  sensor_tmr_proc: process (clk)
    variable Z: integer range 0 to (TEMP_MEASUREMENT_BEAT - 1);
  begin
    if rising_edge(clk) then
      int_sensor_read_start <= '0';
      if (Z < TEMP_MEASUREMENT_BEAT - 1) then 
        Z := Z + 1;
      else 
        Z := 0;
      end if;
      if (Z = 0) then 
        int_sensor_read_start <= '1';
      end if;
    end if;
  end process sensor_tmr_proc;
  
  
END ARCHITECTURE beha;

