library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity de2_wm8731_audio is
port (
    clk : in std_logic;       --  Audio CODEC Chip Clock AUD_XCK (18.43 MHz)
	reset_n : in std_logic;
    chipselect : in std_logic;
    --test_mode : in std_logic;       --    Audio CODEC controller test mode
    --audio_request : out std_logic;  --    Audio controller request new data
    --data : in unsigned(15 downto 0);

    writedata : in unsigned (15 downto 0);
    readdata : out unsigned(15 downto 0);
	irq : out std_logic;
	address : in std_logic_vector(15 downto 0);
	read, write: in std_logic;
  
    -- Audio interface signals
    AUD_ADCLRCK  : out  std_logic;   --    Audio CODEC ADC LR Clock
    AUD_ADCDAT   : in   std_logic;   --    Audio CODEC ADC Data
    AUD_DACLRCK  : out  std_logic;   --    Audio CODEC DAC LR Clock
    AUD_DACDAT   : out  std_logic;   --    Audio CODEC DAC Data
    AUD_BCLK     : inout std_logic  --    Audio CODEC Bit-Stream Clock
  );
end  de2_wm8731_audio;

architecture rtl of de2_wm8731_audio is     

    signal lrck : std_logic;
    signal bclk : std_logic;
    signal xck  : std_logic;
    
    signal lrck_divider : unsigned(11 downto 0); 
    signal bclk_divider : unsigned(3 downto 0);
    
    signal set_bclk : std_logic;
    signal set_lrck : std_logic;
    signal clr_bclk : std_logic;
    signal lrck_lat : std_logic;
    
    signal shift_out : unsigned(15 downto 0);

    signal sin_out     : unsigned(15 downto 0);
    signal sin_counter : unsigned(4 downto 0);  
	signal buf_add : unsigned(4 downto 0) := "00000";
	signal input : unsigned(15 downto 0);
	type RAM_type is array (0 to 31) of unsigned(15 downto 0);
    signal buffer1 : RAM_type :=
 (

X"0000",
X"0fff",
X"0000",
X"ffff",
X"0000",
X"0fff",
X"0000",
X"ffff",
X"0000",
X"0fff",
X"0000",
X"ffff",
X"0000",
X"0fff",
X"0000",
X"ffff",
X"0000",
X"0fff",
X"0000",
X"ffff",
X"0000",
X"0fff",
X"0000",
X"ffff",
X"0000",
X"0fff",
X"0000",
X"ffff",
X"0000",
X"0fff",
X"0000",
X"ffff"
);

signal audio_clock : unsigned(1 downto 0) := "00";
signal clk25: std_logic;
signal clk6: std_logic;
signal audio_clock2 : unsigned(3 downto 0) := "0000";

begin
  
  process (CLk)
  begin
    if rising_edge(CLk) then
      audio_clock <= audio_clock + "1";
    end if;
  end process;
clk25<=audio_clock(1);

  process (CLk)
  begin
    if rising_edge(CLk) then
      audio_clock2 <= audio_clock2 + "1";
    end if;
  end process;
clk6<=audio_clock2(1);
    
  process (clk25)
  begin
    if rising_edge(clk25) then
      if reset_n = '0' then 
        lrck_divider <= (others => '0');
	----lrck_divider = X"1EB" clk=25M, sample rate 6.3K, actual rate 25M/1EB = 54K   irq rate=32k/64 = 500
      elsif lrck_divider = X"320"  then        -- "C0" minus 1
        lrck_divider <= X"000";
      else 
        lrck_divider <= lrck_divider + 1;
      end if;
    end if;   
  end process;

  process (clk25)
  begin
    if rising_edge(clk25) then      
      if reset_n = '0' then 
        bclk_divider <= (others => '0');
      elsif bclk_divider = X"B" or set_lrck = '1'  then  
        bclk_divider <= X"0";
      else 
        bclk_divider <= bclk_divider + 1;
      end if;
    end if;
  end process;

  set_lrck <= '1' when lrck_divider = X"320" else '0';
    
  process (clk25)
  begin
    if rising_edge(clk25) then
      if reset_n = '0' then
        lrck <= '0';
      elsif set_lrck = '1' then 
        lrck <= not lrck;
      end if;
    end if;
  end process;
    
  -- BCLK divider
  set_bclk <= '1' when bclk_divider(3 downto 0) = "0101" else '0';
  clr_bclk <= '1' when bclk_divider(3 downto 0) = "1011" else '0';
  
  process (clk25)
  begin
    if rising_edge(clk25) then
      if reset_n = '0' then
        bclk <= '0';
      elsif set_lrck = '1' or clr_bclk = '1' then
        bclk <= '0';
      elsif set_bclk = '1' then 
        bclk <= '1';
      end if;
    end if;
  end process;

  -- Audio data shift output
  process (clk25)
  begin
    if rising_edge(clk25) then
      if reset_n = '0' then
        shift_out <= (others => '0');
      elsif set_lrck = '1' then
        --if test_mode = '1' then 
          shift_out <= sin_out;
        --else 
          --shift_out <= data;
        --end if;
      elsif clr_bclk = '1' then 
        shift_out <= shift_out (14 downto 0) & '0';
      end if;
    end if;   
  end process;

    -- Audio outputs
    
    AUD_ADCLRCK  <= lrck;          
    AUD_DACLRCK  <= lrck;          
    AUD_DACDAT   <= shift_out(15); 
    AUD_BCLK     <= bclk;          

    -- Self test with Sin wave
    
    process(clk25)      
    begin
      if rising_edge(clk25) then
        if reset_n = '0' then 
            sin_counter <= (others => '0');
        elsif lrck_lat = '1' and lrck = '0'  then  
          if sin_counter = "11111" then 
            sin_counter <= "00000";
          else  
            sin_counter <= sin_counter + 1;
          end if;
        end if;
      end if;
    end process;

    process(clk25)
    begin
      if rising_edge(clk25) then
        lrck_lat <= lrck;
      end if;
    end process;

    process (clk25) 
    begin
      if rising_edge(clk25) then 
        if lrck_lat = '1' and lrck = '0' then
          --audio_request <= '1';
        else 
          --audio_request <= '0';
        end if;
      end if;
    end process;

audio_input: process (clk)
begin
if rising_edge(clk) then
	--if reset_n='0' then
	    --buf_add <= "000000";
	--else 
		if chipselect = '1' then
			if write ='1' then
			 
					
										--if address(7 downto 0)="0001110" then  
				  buffer1(to_integer(unsigned(address))) <=  writedata(15 downto 0);
--				if buf_add = "101111" then
--					buf_add <= "000000";
--				else
--					buf_add <= buf_add + 1;				
			end if;
			
			if read ='1' then
 
				  readdata(15 downto 0) <= buffer1(to_integer(unsigned(address)));
unsigned(address); --buffer1(

		
			end if;
		end if;
	--end if; 
end if;
end process;


process(clk25)
begin 
  if rising_edge(clk25) then
	if reset_n='0' then
		irq <= '0'; 
	else
	    if write = '1' and chipselect ='1' then
			irq <= '0';
		elsif(sin_counter = "11111") then
			irq <= '1';
		elsif not(sin_counter = "11111") then
			irq <= '0'; 
		end if;
	end if; 
end if;
end process;

 sin_out <= buffer1(to_integer(sin_counter));
--buffer1(to_integer(sin_counter))<= input;

end architecture;







