----------------------------------------------------------------------------------
-- Company: University of Connecticut
-- Engineer: Brendan Krueger
-- 
-- Create Date:    13:48:12 06/20/2007 
-- Design Name:    Controller for Analog Devices' AD5535 DAC
-- Module Name:    DAC_controller - DAC_control_arch 
-- Project Name:   Readout Electronics Digital Board
-- Target Devices: Xilinx Spartan-3A
-- Tool versions: Xilinx ISE WebPACK 9.1.03i
-- Description: Control block to communicate with DAC over serial interface
--
-- Dependencies: 
--
-- Revision:  Igor Senderovich
----------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity DAC_controller is
    port ( Clk : in std_logic;
	   Go : in std_logic;
	   Done : out std_logic;
           Addr : in std_logic_vector (4 downto 0);
           Code : in std_logic_vector (13 downto 0);
           SCLK : in std_logic;
           SYNC_low : out std_logic;
           DIN : out std_logic);
end DAC_controller;

architecture behavioral of DAC_controller is

	type stage_t is (S00,S01,S02,S03,S04,S05,S06,S07,
			 S08,S09,S0A,S0B,S0C,S0D,S0E,S0F,
			 S10,S11,S12,S13,S14,S15);
	signal stage : stage_t := S00;

	signal sync : std_logic := '0';
	signal DIN_reg : std_logic := '0';
	signal Done_reg : std_logic := '0';
begin
	SYNC_low <= not sync;
	DIN <= DIN_reg;
	Done <= Done_reg;

	ShiftData : process (SCLK)
	begin
 		if rising_edge(SCLK) then
			stage <= stage;
			sync <= '0';
			DIN_reg <= '0';
			Done_reg <= '0';

			-- Pad the 5 bits of address + 14 bits of data
			-- with 4 zeros to satisfy timing specs @ 20MHz.

			case stage is
			    when S00 =>
				if (Go = '1') then
					stage <= S01;
				end if;
			    when S01 =>
				sync <= '1';
				DIN_reg <= Addr(4);
				stage <= S02;
			    when S02 =>
				sync <= '1';
				DIN_reg <= Addr(3);
				stage <= S03;
			    when S03 =>
				sync <= '1';
				DIN_reg <= Addr(2);
				stage <= S04;
			    when S04 =>
				sync <= '1';
				DIN_reg <= Addr(1);
				stage <= S05;
			    when S05 =>
				sync <= '1';
				DIN_reg <= Addr(0);
				stage <= S06;
			    when S06 =>
				sync <= '1';
				DIN_reg <= Code(13);
				stage <= S07;
			    when S07 =>
				sync <= '1';
				DIN_reg <= Code(12);
				stage <= S08;
			    when S08 =>
				sync <= '1';
				DIN_reg <= Code(11);
				stage <= S09;
			    when S09 =>
				sync <= '1';
				DIN_reg <= Code(10);
				stage <= S0A;
			    when S0A =>
				sync <= '1';
				DIN_reg <= Code(9);
				stage <= S0B;
			    when S0B =>
				sync <= '1';
				DIN_reg <= Code(8);
				stage <= S0C;
			    when S0C =>
				sync <= '1';
				DIN_reg <= Code(7);
				stage <= S0D;
			    when S0D =>
				sync <= '1';
				DIN_reg <= Code(6);
				stage <= S0E;
			    when S0E =>
				sync <= '1';
				DIN_reg <= Code(5);
				stage <= S0F;
			    when S0F =>
				sync <= '1';
				DIN_reg <= Code(4);
				stage <= S10;
			    when S10 =>
				sync <= '1';
				DIN_reg <= Code(3);
				stage <= S11;
			    when S11 =>
				sync <= '1';
				DIN_reg <= Code(2);
				stage <= S12;
			    when S12 =>
				sync <= '1';
				DIN_reg <= Code(1);
				stage <= S13;
			    when S13 =>
				sync <= '1';
				DIN_reg <= Code(0);
				stage <= S14;
			    when S14 =>
				sync <= '1';
				DIN_reg <= '0';
				stage <= S15;
			    when S15 =>
				if (Go = '1') then
					Done_reg <= '1';
				else
					stage <= S00;
				end if;
			end case;
		else
			stage <= stage;
			sync <= sync;
			DIN_reg <= DIN_reg;
			Done_reg <= Done_reg;
		end if;
	end process;

end behavioral;
