----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    18:29:55 08/26/2006 
-- Design Name: 
-- Module Name:    ac_io - 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.NUMERIC_STD.ALL;

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

entity ac_io is
    Port (
			rst				: in  std_logic;
			clk				: in  std_logic;
			ready			: out std_logic;
			sync_strobe		: out unsigned(0 to 2);
			slot_valid 		: out unsigned(0 to 12);
			stat_addr		: out unsigned (19 downto 0);
			stat_data		: out unsigned (19 downto 0);
			rx_pcm_addr		: in  unsigned (3 downto 0);
			rx_pcm_data		: out unsigned (19 downto 0);
			cmd_addr 		: in  unsigned(19 downto 0);
			cmd_data		: in  unsigned(19 downto 0);
			cmd_we			: in  std_logic;
			tx_pcm_addr		: in  unsigned(3 downto 0);
			tx_pcm_data		: in  unsigned(19 downto 0);
			tx_pcm_we		: in  std_logic;
			ac_sdata_in		: in std_logic;
			ac_bit_clk		: in  std_logic;          
			ac_reset_n		: out std_logic;
			ac_sdata_out	: out std_logic;
			ac_ssync		: out std_logic);

end ac_io;

architecture Behavioral of ac_io is

	COMPONENT ac_in
    Port (
		rst 			: in  std_logic;
		clk 			: in  std_logic;
		sync_frame	 	: out std_logic;
		sync_status	 	: out std_logic;
		slot_valid 		: out unsigned(0 to 12);
		stat_addr		: out unsigned (19 downto 0);
		stat_data		: out unsigned (19 downto 0);
		pcm_out_addr	: in  unsigned (3 downto 0);
		pcm_out_data	: out unsigned (19 downto 0);
		ac_reset		: in std_logic; 
		ac_bit_clk		: in  std_logic;
		ac_sdata_in		: in std_logic;
		ac_ssync		: in std_logic
		);
	END COMPONENT;

	COMPONENT ac_out
	PORT(
		rst				: in  std_logic;
		clk				: in  std_logic;
		sync_tx		 	: out std_logic;
		cmd_addr 		: in  unsigned(19 downto 0);
		cmd_data		: in  unsigned(19 downto 0);
		cmd_we			: in  std_logic;
		pcm_in_addr		: in  unsigned(3 downto 0);
		pcm_in_data		: in  unsigned(19 downto 0);
		pcm_in_we		: in  std_logic;
		ac_bit_clk		: in  std_logic;          
		ac_reset		: in  std_logic;
		ac_sdata_out	: out std_logic;
		ac_ssync		: out std_logic
		);
	END COMPONENT;

	SIGNAL ac_reset :  std_logic;
	SIGNAL ssync_rx :  std_logic;
	SIGNAL ssync_tx :  std_logic;
	SIGNAL sync_frame :  std_logic;
	SIGNAL sync_status :  std_logic;
	SIGNAL sync_tx :  std_logic;

begin

	inst_ac_in: ac_in PORT MAP(
		rst => rst,
		clk => clk,
		sync_frame => sync_frame,
		sync_status => sync_status,
		slot_valid => slot_valid,
		stat_addr => stat_addr,
		stat_data => stat_data,
		pcm_out_addr => rx_pcm_addr,
		pcm_out_data => rx_pcm_data,
		ac_reset => ac_reset,
		ac_bit_clk => ac_bit_clk,
		ac_sdata_in => ac_sdata_in,
		ac_ssync => ssync_rx
	);
	
	inst_ac_out: ac_out PORT MAP(
		rst => rst,
		clk => clk,
		sync_tx => sync_tx,
		cmd_addr => cmd_addr,
		cmd_data => cmd_data,
		cmd_we => cmd_we,
		pcm_in_addr => tx_pcm_addr,
		pcm_in_data => tx_pcm_data,
		pcm_in_we => tx_pcm_we,
		ac_reset => ac_reset,
		ac_bit_clk => ac_bit_clk,
		ac_sdata_out => ac_sdata_out,
		ac_ssync => ssync_tx
	);

	------------------------------------------------------------------
	ready <= not ac_reset;
	ac_ssync <= ssync_tx;
	ssync_rx <= ssync_tx;
	sync_strobe <= sync_frame & sync_status & sync_tx;
	
	------------------------------------------------------------------
	proc_reset_gen:
	process (rst, clk, ac_bit_clk)
	type rstate_t is (s0, s1);
	variable rstate, rstaten : rstate_t;
	subtype cnt_t is integer range 0 to 999;
	variable cnt : cnt_t;
	begin
		if rising_edge(clk) then
			if rst = '1' then
				rstate := s0;
				cnt := cnt_t'high;
				ac_reset <= '1';
				ac_reset_n <= '0';
			else
				rstaten := rstate;
				case rstate is
					when s0 =>
					if cnt /= 0 then
						cnt := cnt - 1;
					else
						ac_reset_n <= '1';
						if ac_bit_clk = '1' then
							rstaten := s1;
							cnt := cnt_t'high;
						end if;	
					end if;
					
					when s1 =>
					if cnt /= 0 then
						cnt := cnt - 1;
					else
						ac_reset <= '0';
					end if;
				end case;
				rstate := rstaten;
			end if;
		end if;
	end process;	
	
	------------------------------------------------------------------
	
end Behavioral;

