--
-- VHDL Architecture FACT_FAD_lib.spi_controller.beha
--
-- Created:
--          by - Benjamin Krumm.UNKNOWN (EEPC8)
--          at - 10:37:20 12.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;

ENTITY spi_controller IS
   PORT( 
      clk          : IN     std_logic;
      miso         : INOUT  std_logic := 'Z';
      mosi         : OUT    std_logic := '0';
      dac_id       : IN     std_logic_vector (2 DOWNTO 0);
      sensor_id    : IN     std_logic_vector (1 downto 0);
      data         : INOUT  std_logic_vector (15 DOWNTO 0) := (others => 'Z');
      dac_cs       : OUT    std_logic := '1';
      sensor_cs    : OUT    std_logic_vector (3 DOWNTO 0) := (others => '1');
      dac_start    : IN     std_logic;
      dac_ready    : OUT    std_logic := '0';
      sensor_start : IN     std_logic;
      sensor_valid : OUT    std_logic := '0'
   );
END spi_controller ;

ARCHITECTURE beha OF spi_controller IS
  
  type TYPE_SPI_STATE is (SPI_IDLE, SPI_LOAD_DAC, SPI_LOAD_COMMAND, SPI_GET_TEMP);
   
  signal spi_state     : TYPE_SPI_STATE := SPI_IDLE;
  signal spi_cycle_cnt : integer range 0 to 25 := 0;
  signal shift_reg     : std_logic_vector (23 downto 0) := (others => '0');
  signal data_reg      : std_logic_vector (15 downto 0) := (others => '0');
  
BEGIN
  
  spi_write_proc: process (clk)
  begin
    if falling_edge(clk) then
      dac_cs <= '1';
      sensor_cs <= (others => '1');
      miso <= 'Z';
      mosi <= '0';
      data <= (others => 'Z');
      case spi_state is
        when SPI_IDLE =>
          if (dac_start = '1') then
            dac_ready <= '0';
            spi_state <= SPI_LOAD_COMMAND; 
          elsif (sensor_start = '1') then
            sensor_valid <= '0';
            spi_state <= SPI_LOAD_COMMAND;
          end if;
          
        when SPI_LOAD_COMMAND =>
          spi_cycle_cnt <= 0;
            if (sensor_start = '1') then
              shift_reg <= X"C1" & X"0000";   -- command: Temperature register read
              spi_state <= SPI_GET_TEMP;
            elsif (dac_start = '1') then
              shift_reg <= "0011" & '0' & dac_id & data;
              spi_state <= SPI_LOAD_DAC;
            end if;
        
        -- start temperature sensor read  
        when SPI_GET_TEMP =>
          if (spi_cycle_cnt < 24) then -- must be on more cause MAX6662 provides data on falling edge
            sensor_cs(conv_integer(sensor_id)) <= '0';
            sensor_valid <= '0';
            spi_cycle_cnt <= spi_cycle_cnt + 1;
            if (spi_cycle_cnt < 9) then -- send data
              miso <= shift_reg(23);
              shift_reg <= shift_reg(22 downto 0) & shift_reg(23);
            end if;
          else
            data <= data_reg;             
            sensor_valid <= '1';
            spi_state <= SPI_IDLE;
          end if;
        
        -- start loading DACs 
       when SPI_LOAD_DAC => 
          dac_cs <= '0';
          if (spi_cycle_cnt < 24) then
            mosi <= shift_reg(23);
            shift_reg <= shift_reg(22 downto 0) & shift_reg(23);
            dac_ready <= '0';
            spi_cycle_cnt <= spi_cycle_cnt + 1;
            spi_state <= SPI_LOAD_DAC;
          else
            dac_cs <= '1';
            dac_ready <= '1';
            spi_state <= SPI_IDLE;
          end if;
      end case;
    end if;
  end process spi_write_proc;
  
  -- MAX6662 input must be read with rising edge
  spi_read_proc: process (clk) 
  begin
    if rising_edge(clk) then
      if (spi_state = SPI_GET_TEMP and spi_cycle_cnt >= 9) then
        data_reg(0) <= miso;
        data_reg(15 downto 1) <= data_reg(14 downto 0);
      end if;
    end if;
  end process spi_read_proc; 
    
END ARCHITECTURE beha;

