----------------------------------------------------------------------------------
-- Company:        ETH Zurich, Institute for Particle Physics
-- Engineer:       P. Vogler, Q. Weitzel
-- 
-- Create Date:    16:24:08 01/19/2010 
-- Design Name: 
-- Module Name:    FTU_dac_control - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description:    control DAC on FTU board to set trigger thresholds 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity FTU_dac_control is
  port(
    clk      : IN     STD_LOGIC;
    reset    : IN     STD_LOGIC;
    miso     : IN     STD_LOGIC;
    clr      : OUT    STD_LOGIC;
    mosi     : OUT    STD_LOGIC;
    sck      : OUT    STD_LOGIC;
    cs_ld    : OUT    STD_LOGIC
  );
end FTU_dac_control;

architecture Behavioral of FTU_dac_control is

  constant RESET_ACTIVE : std_logic := '0';
  
  component spi_interface_16
    port(
      clk              : IN    STD_LOGIC;
      clkdiv           : IN    STD_LOGIC_VECTOR (1 DOWNTO 0);
      cpha             : IN    STD_LOGIC;
      cpol             : IN    STD_LOGIC;
      miso             : IN    STD_LOGIC;
      rcv_cpol         : IN    STD_LOGIC;
      rcv_full_reset   : IN    STD_LOGIC;
      reset            : IN    STD_LOGIC;
      ss_in_n          : IN    STD_LOGIC;
      ss_mask_reg      : IN    STD_LOGIC_VECTOR (7 DOWNTO 0);
      start            : IN    STD_LOGIC;
      xmit_data        : IN    STD_LOGIC_VECTOR (15 DOWNTO 0);
      xmit_empty_reset : IN    STD_LOGIC;
      rcv_load         : INOUT STD_LOGIC;
      sck              : INOUT STD_LOGIC;
      ss_in_int        : INOUT STD_LOGIC;
      ss_n_int         : INOUT STD_LOGIC;
      xmit_empty       : INOUT STD_LOGIC;
      done             : OUT   STD_LOGIC;
      mosi             : OUT   STD_LOGIC;
      rcv_data         : OUT   STD_LOGIC_VECTOR (15 DOWNTO 0);
      rcv_full         : OUT   STD_LOGIC;
      ss_n             : OUT   STD_LOGIC_VECTOR (7 DOWNTO 0)
    );
  end component;

  component upcnt16
    port(
      full  : out STD_LOGIC;
      clr   : in  STD_LOGIC;
      reset : in  STD_Logic;
      clk   : in  STD_LOGIC
    );
  end component;

  signal clk_sig          : std_logic;
  signal done_sig         : std_logic;
  signal start_sig        : std_logic;
  signal slave_select_sig : std_logic;
  signal full_sig         : std_logic;
  signal clr_wcnt_sig     : std_logic;
  signal s_clock_sig      : std_logic;
  signal D_sig            : STD_LOGIC_VECTOR (15 DOWNTO 0);
  signal ss_n_sig         : STD_LOGIC_VECTOR (7 DOWNTO 0);
  signal reset_sig        : STD_LOGIC;
  signal reset_sig_inv    : STD_LOGIC;

  -- Build an enumerated type for the state machine
  type state_type is (Idle);

  -- Register to hold the current state
  signal state, next_state: state_type;
  
begin

  reset_sig <= reset;
  reset_sig_inv <= not(reset);
  clk_sig <= clk;
  sck <= s_clock_sig;
  clr <= reset_sig_inv;
  cs_ld <= ss_n_sig(0);

  -- FSM for dac control: first process
  FSM_Registers: process(clk_sig, reset_sig)
  begin
    if reset_sig = '1' then
      state <= Idle;
    elsif Rising_edge(clk_sig) then
      state <= next_state;
    end if;
  end process;

  -- FSM for dac control: second process
  FSM_logic: process(state)
  begin
    next_state <= state;
    case state is
      when Idle =>
        D_sig <= "0001000100000000";
        start_sig <= '0';
        slave_select_sig <= '0';
        clr_wcnt_sig <= '0';
    end case;
  end process;
    
  Inst_spi_interface_16 : spi_interface_16
    port map(
      clk=>clk_sig, clkdiv(1)=>'0', clkdiv(0)=>'0',
      cpha=>'1', cpol=>'1', miso=>'1', rcv_cpol=>'1',
      rcv_full_reset=>not(RESET_ACTIVE), reset=>reset_sig_inv, ss_in_n=>'1',
      ss_mask_reg(7)=>'0', ss_mask_reg(6)=>'0',
      ss_mask_reg(5)=>'0', ss_mask_reg(4)=>'0',
      ss_mask_reg(3)=>'0', ss_mask_reg(2)=>'0',
      ss_mask_reg(1)=>'0', ss_mask_reg(0)=>slave_select_sig,
      start=>start_sig,
      xmit_data(15)=>D_sig(15), xmit_data(14)=>D_sig(14),
      xmit_data(13)=>D_sig(13), xmit_data(12)=>D_sig(12),
      xmit_data(11)=>D_sig(11), xmit_data(10)=>D_sig(10),
      xmit_data(9)=>D_sig(9),   xmit_data(8)=>D_sig(8),
      xmit_data(7)=>D_sig(7),   xmit_data(6)=>D_sig(6),
      xmit_data(5)=>D_sig(5),   xmit_data(4)=>D_sig(4),
      xmit_data(3)=>D_sig(3),   xmit_data(2)=>D_sig(2),
      xmit_data(1)=>D_sig(1),   xmit_data(0)=>D_sig(0),
      xmit_empty_reset=>RESET_ACTIVE,
      rcv_load=>open,
      sck=>s_clock_sig,
      ss_in_int=>open,
      ss_n_int=>open,
      xmit_empty=>open,
      done=>done_sig, mosi=>mosi,rcv_data=>open,
      --rcv_data(15)=>open, rcv_data(14)=>open,
      --rcv_data(13)=>open, rcv_data(12)=>open,
      --rcv_data(11)=>open, rcv_data(10)=>open,
      --rcv_data(9)=>open,  rcv_data(8)=>open,
      --rcv_data(7)=>open,  rcv_data(6)=>open,
      --rcv_data(5)=>open,  rcv_data(4)=>open,
      --rcv_data(3)=>open,  rcv_data(2)=>open,
      --rcv_data(1)=>open,  rcv_data(0)=>open,
      rcv_full=>open,ss_n=>ss_n_sig
      --ss_n(7)=>open, ss_n(6)=>open, ss_n(5)=>open, ss_n(4)=>open,
      --ss_n(3)=>open, ss_n(2)=>open, ss_n(1)=>open, ss_n(0)=>cs_ld
    );

  wait_cnt: upcnt16
    port map(
      full  => full_sig,
      clr   => clr_wcnt_sig,
      reset => reset_sig,
      clk   => clk_sig
    );
  
end Behavioral;

