-- JunHao Ip
-- Jason Cardillo
-- Chih-Chieh Lin
-------------------
--FPGA rule, don't mix clock with signal
--use separate counter for each clock
--always work on either up latch or down latch

--------------ak4565 Audio Interface------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity ak4565 is
  port (
    clk      : in  std_logic;
    rst      : in  std_logic;
    mclk     : out std_logic;
    bclk     : out std_logic;
    lrclk    : out std_logic;
    sdti     : out std_logic;
    sdto0    : in  std_logic;
    csn      : out std_logic;
    cclk     : out std_logic;
    cdti     : out std_logic;

    adcdone : out std_logic;
    dacload : out std_logic;
    adc_dtout : out std_logic_vector(15 downto 0);  --data out to fpga
    dac_dtin  : in  std_logic_vector(15 downto 0);  --parallelload data from fpga
    c_datain : in std_logic_vector(15 downto 0);  --parallelload control from fpga
    c_wr     : in std_logic;
    c_done   : out std_logic
    );
end ak4565;

architecture Behavioral of ak4565 is

  signal fs256clk : std_logic;  --12.5Mhz = 256fs
  signal fs64clk, sbclk, snbclk : std_logic;  --1.5625Mhz = 32fs
  signal slrclk: std_logic;  --48.8Khz = fs
  --signal scclk : std_logic;  --3.125Mhz

  signal clkcount: std_logic_vector(1 downto 0):="00";
  signal adcount,dacount: std_logic_vector(7 downto 0):="00000000";
  signal ccount : std_logic_vector(3 downto 0):="0000";
  signal ad_capture, da_stream : std_logic;
  signal s_csn, sdone : std_logic;
  signal s_adcdone, s_dacload: std_logic;

  signal adc_data16: std_logic_vector(15 downto 0) := x"0000";
  signal in_shift_reg,out_shift_reg,c_shift_reg: std_logic_vector(15 downto 0) := x"0000";
  signal s_fpga2audio, s_fpga2audcntrl : std_logic;

----output to signal mapping-------------------------
begin
    mclk  <=not fs256clk;
    bclk  <=sbclk;
    lrclk <=slrclk;

    sdti  <=s_fpga2audio;

    csn   <=s_csn;
    cclk  <=not fs64clk;
    cdti  <=s_fpga2audcntrl;

    adcdone <= s_adcdone;
    dacload <= s_dacload;

    adc_dtout(15 downto 0)<=adc_data16(15 downto 0);
    c_done  <= sdone;

----clocks and counters------------------------------
  clkdiv1 : process(clk,rst)
  begin
    if rst = '1' then
      clkcount <= "00";
    elsif clk'event and clk = '1' then
      clkcount <= clkcount + 1;

    	-- phase doesn't matter? ak4565 spec page 11
    	fs256clk<=clkcount(1);  --sync with lrclk?
    end if;

  end process clkdiv1;

  clkdiv2 : process(fs256clk,rst)
  begin
    if rst = '1' then
      adcount <= "00000000";
      dacount <= "00000100";
    elsif fs256clk'event and fs256clk = '1' then
      adcount <= adcount+1;
      dacount <= dacount+1;

  	  fs64clk<=adcount(1);
      sbclk<=adcount(2);  --clocks
      snbclk<=dacount(2);
      slrclk<=adcount(7);

  	  ad_capture <=adcount(7);  --regular signal
  	  da_stream <=dacount(7);
    end if;
  end process clkdiv2;


------grab audio data---------------------------------
  get_audio : process(sbclk,rst)
  begin
    if rst = '1' then
      in_shift_reg <= X"0000";
      adc_data16 <= X"0000";
    elsif sbclk'event and sbclk = '1' then
      if ad_capture = '0' then
          in_shift_reg(15)<=in_shift_reg(14);
          in_shift_reg(14)<=in_shift_reg(13);
          in_shift_reg(13)<=in_shift_reg(12);
          in_shift_reg(12)<=in_shift_reg(11);
          in_shift_reg(11)<=in_shift_reg(10);
          in_shift_reg(10)<=in_shift_reg(9);
          in_shift_reg(9)<=in_shift_reg(8);
          in_shift_reg(8)<=in_shift_reg(7);
          in_shift_reg(7)<=in_shift_reg(6);
          in_shift_reg(6)<=in_shift_reg(5);
          in_shift_reg(5)<=in_shift_reg(4);
          in_shift_reg(4)<=in_shift_reg(3);
          in_shift_reg(3)<=in_shift_reg(2);
          in_shift_reg(2)<=in_shift_reg(1);
          in_shift_reg(1)<=in_shift_reg(0);
          in_shift_reg(0)<=sdto0;
      else
          adc_data16(15 downto 0)<= in_shift_reg(15 downto 0);
      end if;
    end if;
  end process get_audio;

  get_audio2 : process(sbclk,rst)
  begin
    if rst = '1' then
      s_adcdone<='0';
    elsif sbclk'event and sbclk = '1' then
      if ad_capture = '0' then
        s_adcdone<='0';
      else
        s_adcdone<='1';
      end if;
    end if;
 end process get_audio2;


--------push data to output port-----------------------

  output_audiostream : process(snbclk,rst)
  begin
    if rst ='1' then
      out_shift_reg(15 downto 0)<=X"0000";
      s_fpga2audio<='0';
    elsif snbclk'event and snbclk = '1' then
      if da_stream='0' then
          out_shift_reg(15)<=out_shift_reg(14);
          out_shift_reg(14)<=out_shift_reg(13);
          out_shift_reg(13)<=out_shift_reg(12);
          out_shift_reg(12)<=out_shift_reg(11);
          out_shift_reg(11)<=out_shift_reg(10);
          out_shift_reg(10)<=out_shift_reg(9);
          out_shift_reg(9)<=out_shift_reg(8);
          out_shift_reg(8)<=out_shift_reg(7);
          out_shift_reg(7)<=out_shift_reg(6);
          out_shift_reg(6)<=out_shift_reg(5);
          out_shift_reg(5)<=out_shift_reg(4);
          out_shift_reg(4)<=out_shift_reg(3);
          out_shift_reg(3)<=out_shift_reg(2);
          out_shift_reg(2)<=out_shift_reg(1);
          out_shift_reg(1)<=out_shift_reg(0);
          out_shift_reg(0)<='0';
          s_fpga2audio <= out_shift_reg(15);
      else
          out_shift_reg(15 downto 0)<= dac_dtin(15 downto 0);
          s_fpga2audio<='0';
      end if;
    end if;
  end process output_audiostream;

 output_audiostream2 : process(snbclk,rst)
  begin
    if rst = '1' then
      s_dacload<='0';
    elsif snbclk'event and snbclk = '1' then
      if da_stream = '0' then
        s_dacload<='0';
      else
        s_dacload<='1';
      end if;
    end if;
 end process output_audiostream2;



----- audio port initialization -------------------------
process (fs64clk,c_wr)
   begin
   if c_wr='1' then
   		ccount<="0000";
   		sdone<='0';
   		s_csn<='1';
   elsif fs64clk'event and fs64clk='1' then
   		if sdone<='0' then
   			ccount<=ccount+1;
   			s_csn<='0';
   		end if;

   		if ccount = "1111" then
   			sdone<='1';
   		end if;

   		if sdone='1' then
   			s_csn<='1';
   		end if;
   end if;
end process;

process (fs64clk,c_wr,c_datain)
   begin
   if c_wr='1' then
   		c_shift_reg(15 downto 0) <= c_datain(15 downto 0);
      s_fpga2audcntrl<='0';
   elsif fs64clk'event and fs64clk='1' then
   		if sdone ='0' then
   			c_shift_reg(15) <= c_shift_reg(14);
   			c_shift_reg(14) <= c_shift_reg(13);
   			c_shift_reg(13) <= c_shift_reg(12);
   			c_shift_reg(12) <= c_shift_reg(11);
   			c_shift_reg(11) <= c_shift_reg(10);
   			c_shift_reg(10) <= c_shift_reg(9);
   			c_shift_reg(9) <= c_shift_reg(8);
   			c_shift_reg(8) <= c_shift_reg(7);
   			c_shift_reg(7) <= c_shift_reg(6);
   			c_shift_reg(6) <= c_shift_reg(5);
   			c_shift_reg(5) <= c_shift_reg(4);
   			c_shift_reg(4) <= c_shift_reg(3);
   			c_shift_reg(3) <= c_shift_reg(2);
   			c_shift_reg(2) <= c_shift_reg(1);
   			c_shift_reg(1) <= c_shift_reg(0);
        c_shift_reg(0) <= '0';
   			s_fpga2audcntrl <= c_shift_reg(15);
   		end if;
   end if;
end process;



end Behavioral;










