----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    15:52:07 03/18/2012 
-- Design Name: 
-- Module Name:    Control_Block - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- 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 using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

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

entity Control_Block is
    Port ( TAG_output_data : out  STD_LOGIC_VECTOR (4 downto 0);			-- data for output frame
           ID_output_data : out  STD_LOGIC_VECTOR (1 downto 0);			-- ID of codec
           RNW_output_data : out  STD_LOGIC;										-- RNW flag (see AC'97_core.vhd)
           ADDR_output_data : out  STD_LOGIC_VECTOR (6 downto 0);			-- register address (see AC'97_core.vhd)
           DATA_WR_output_data : out  STD_LOGIC_VECTOR (15 downto 0);	-- data to codec register
           PCM_DATA : out  STD_LOGIC_VECTOR (19 downto 0);					-- audio data to codec
           clk : in  STD_LOGIC;														-- clock signal
			  done_input : in  STD_LOGIC;												-- control input
			  Audio_data : in STD_LOGIC_VECTOR (17 downto 0);					-- audio data input
			  Slot_valid_data : in STD_LOGIC_VECTOR (4 downto 0);				-- data from codec
           RST_output_data : out  STD_LOGIC;										-- reset signal			
           Load_output_data : out  STD_LOGIC;									-- control signal
			  volume_LED:	out STD_LOGIC_VECTOR (7 downto 0);					-- volume indicator output	
			  button_vol_down: in STD_LOGIC;											-- volume control input(+)
			  button_vol_up: in STD_LOGIC			  									-- volume control input(-)
			  );
end Control_Block;

architecture Behavioral of Control_Block is

signal counter: STD_LOGIC_VECTOR (3 downto 0):= X"0"; 
signal TAG_sig: STD_LOGIC_VECTOR (4 downto 0):= "00000";
signal ID_sig : STD_LOGIC_VECTOR (1 downto 0):= "00";
signal RNW_sig: STD_LOGIC:= '0';
signal ADDR_sig:STD_LOGIC_VECTOR (6 downto 0):= "0000000";
signal DATA_WR_sig:  STD_LOGIC_VECTOR (15 downto 0):= X"0000";
signal PCM_DATA_sig: STD_LOGIC_VECTOR (19 downto 0):= X"00000";
signal RST_sig: STD_LOGIC := '0';
signal Load_sig: STD_LOGIC := '0';
signal Freq: STD_LOGIC_VECTOR (15 downto 0):= X"0001";
signal reset_counter: STD_LOGIC_VECTOR (3 downto 0):= X"0"; 
signal pressed_vol_up: STD_LOGIC := '0';
signal pressed_vol_down: STD_LOGIC := '0';
signal vol_refresh: STD_LOGIC := '0';
signal volume: STD_LOGIC_VECTOR (2 downto 0):= "100"; 
 
begin

process (clk,done_input,Slot_valid_data,button_vol_down,button_vol_up) begin
	IF rising_edge(clk) THEN	
		-- button press detection for volume control
		if button_vol_down = '1' then
			pressed_vol_down <= '1';
		elsif pressed_vol_down = '1'	then
			pressed_vol_down <= '0';
			if volume < "111" then volume <= volume + "001"; vol_refresh <= '1'; else  vol_refresh <= '0'; volume <= "111"; end if;
		end if;
			
		if button_vol_up = '1' then
			pressed_vol_up  <= '1';
		elsif pressed_vol_up = '1'	then
			pressed_vol_up <= '0';
			if volume > "000" then volume <= volume - "001"; vol_refresh <= '1';  else  vol_refresh <= '0'; volume <= "000";  end if;					
		end if;
	
		-- state machine for codec cnfiguration
		if Slot_valid_data(4) = '1' AND done_input = '1' then 			 
			case counter is
				-- reset
				when X"0" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig 	<= '0';
								 ADDR_sig<= "0000000";
								 DATA_WR_sig<= X"0001";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';
				-- headphones volume
				when X"1" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig 	<= '0';
								 ADDR_sig<= "0000100";
								 DATA_WR_sig<= X"0010";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';
				-- mic volume			 
				when X"2" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig 	<= '0';
								 ADDR_sig<= "0001110";
								 DATA_WR_sig<= X"8008";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';			 
				-- record select
				when X"3" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig 	<= '0';
								 ADDR_sig<= "0011010";
								 DATA_WR_sig<= X"0000";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';	
				-- record gain
				when X"4" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig <= '0';
								 ADDR_sig<= "0011100";
								 DATA_WR_sig<= X"0002";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';
				-- PCM out volume
				when X"5" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig <= '0';
								 ADDR_sig<= "0011000";
								 DATA_WR_sig<= X"0808";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';
								 
				-- general purpose
				when X"6" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig	<= '0';
								 ADDR_sig<= "0100000";
								 DATA_WR_sig<= X"8000";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';
				-- dac sample rate(10 kHz)		 
				when X"7" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig	<= '0';
								 ADDR_sig<= "0101100";
								 DATA_WR_sig<= X"2710";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';	
				-- adc sample rate (10 kHz)	
				when X"8" => TAG_sig <= "11100";
								 ID_sig	<= "00";
								 RNW_sig	<= '0';
								 ADDR_sig<= "0110010";
								 DATA_WR_sig<= X"2710";
								 PCM_DATA_sig<= X"00000";
								 LOAD_sig<= '1';								 
				-- after configuration only audio data and volume control adjustment is sent
				when OTHERS =>	
					if vol_refresh = '1'  then
						vol_refresh <= '0';
						TAG_sig <= "11111";
						ID_sig	<= "00";
						RNW_sig <= '0';
						ADDR_sig<= "0011000";
						DATA_WR_sig<= "001"&volume&"00001"&volume&"00";
						PCM_DATA_sig<= Audio_data & "00";
						LOAD_sig<= '1';
					else	
						TAG_sig <= "10011";
						ID_sig	<= "00";
						RNW_sig <= '0';
						ADDR_sig<= "0000000";
						DATA_WR_sig<= X"0000";				
						PCM_DATA_sig<= Audio_data & "00";
						LOAD_sig<= '1';
					end if;
			end case;
			
			if counter < X"9" then	counter <= counter + 1;
			else
				counter <= counter;
			end if;
		end if;	
	 end if; 		 
end process;

process (clk) begin
	if rising_edge(clk) then	
		-- write data to outputs
		TAG_output_data <= TAG_sig; 
		ID_output_data <= ID_sig;	
		RNW_output_data <= RNW_sig; 	
		ADDR_output_data <= ADDR_sig;
		DATA_WR_output_data <= DATA_WR_sig;
		PCM_DATA <= PCM_DATA_sig;		
		Load_output_data <= LOAD_sig;
		RST_output_data <= RST_sig;
		
		CASE volume IS
			WHEN "000" => volume_LED <= X"FF";
			WHEN "001" => volume_LED <= X"7F";
			WHEN "010" => volume_LED <= X"3F";
			WHEN "011" => volume_LED <= X"1F";
			WHEN "100" => volume_LED <= X"0F";
			WHEN "101" => volume_LED <= X"07";
			WHEN "110" => volume_LED <= X"03";
			WHEN OTHERS => volume_LED <= X"01";
		END CASE;	
	
		if reset_counter<X"8" then
			RST_sig <= '1';
			reset_counter <= reset_counter + 1;
		else
			RST_sig <= '0';
			reset_counter <= reset_counter;
		end if;	
	end if;	
end process;	
		
end Behavioral;




               