-------------------------------------------------------------------------------
-- Title      : FLAC_DECODER
-------------------------------------------------------------------------------
-- File       : FLAC_DECODER.vhd
-- Author     : Sathishkumar Donthu
--              Sathish.Donthu@microsemi.com
-- Company    : Microsemi Corporation
-- Device     : SmartFusion 
-- Standard   : VHDL
-------------------------------------------------------------------------------
-- Description: writing to DAC0 for playing a decoded frame.
-- it reads the address of decoded frame first then sampling rate.
-------------------------------------------------------------------------------
-- Copyright (c) 2011   Actel Corporation
--                      All rights reserved.
--------------------------------------------------------------------------------- player.vhd
library   IEEE;
use       IEEE.std_logic_1164.all;
use       IEEE.std_logic_unsigned.all;

entity PLAYER is
port ( 
       PCLK                    : in  std_logic;
       PRESET                  : in  std_logic;       
       P_VALID                 : out  std_logic;
       
       --APB3 slave signals 
       
       SPENABLE                : in  std_logic;
       SPSEL                   : in  std_logic;
       SPWRITE                 : in  std_logic;
       SPWDATA                 : in  std_logic_vector(31 downto 0);
       SPADDR                  : in  std_logic_vector(19 downto 0);
       SPRDATA                 : out std_logic_vector(31 downto 0);
       SPREADY,SPSLVERR        : out std_logic;

       --APB3 master signals

       MPENABLE                : out std_logic;
       MPSEL                   : out std_logic;
       MPWRITE                 : out std_logic;
       MPWDATA                 : out std_logic_vector(31 downto 0);
       MPADDR                  : out std_logic_vector(31 downto 0);
       MPRDATA                 : in  std_logic_vector(31 downto 0);
       MPREADY,PSLVERR         : in  std_logic;

       --Signals for conncting to GPIO's of MSS

       START                   : in  std_logic;
       STOP                    : out std_logic
       );
      end PLAYER;

architecture beh of PLAYER is

type array2         is array (1  downto  0) of std_logic_vector(31  downto   0 ) ;
type state_type     is (idle,idle1,ssetup,saccess,msetup,maccess,wsetup,waccess,dacwait);
signal state        : state_type;
signal read         : std_logic;
signal clkdriven    : std_logic;
signal rx_data      : array2;
signal samplerate   : std_logic_vector(15 downto 0);
signal wsample      : std_logic_vector(15 downto 0);
signal length       : std_logic_vector(11 downto 0);
signal count        : std_logic_vector(15 downto 0);
constant one        : std_logic_vector(31 downto 0):=x"00000004";

begin

process(PCLK,PRESET,START)
variable args_read      :   integer range 1 downto 0;
begin

 if(START='0' or PRESET='0') then
    state<=idle;
    args_read:=0;    
    read<='1';
    STOP<='0';
    MPADDR<=x"00000000";
    MPWDATA<=x"00000000";    
    length<=x"001";   
    P_VALID<='0';    
 else 
    
  if (PCLK'event and PCLK = '1') then
    
      case state is
        --***************************************************************************
        --APB Slave states
        --***************************************************************************

        when idle       => if(SPSEL='1' and SPENABLE='0') then
                           state<=ssetup;
                           end if;
        when ssetup     => if(SPSEL='1' and SPENABLE='1'and SPADDR=x"50200") then                        
                           SPREADY<='1';
                           state<=saccess;
                           elsif(SPWRITE='0') then
                           SPREADY<='0';
                           state<=saccess;
                           end if;
        when saccess    => if(SPWRITE='1') then
                           SPREADY<='1';
                           rx_data(args_read)<=SPWDATA;
                            if(args_read=1) then
                            samplerate<=SPWDATA(15 downto 0);                                                                                                  
                            state<=msetup; 
                            else
                            state<=ssetup;
                            args_read:=args_read+1;
                            end if;                       
                           elsif (SPWRITE='0') then
                           state<=idle;
                           SPREADY<='1';
                           end if;

        --***************************************************************************
        --APB Master states
        --***************************************************************************

        when msetup     => SPREADY <= '0';
                           state   <= maccess;                           
                           MPADDR  <= rx_data(0);
                           P_VALID<='1';                                                      
        when maccess    => if(MPREADY='1') then
                           wsample <= MPRDATA(15 downto 0);
                           rx_data(0) <= rx_data(0) + one ;
                           length  <= length+x"001";
                           state   <= dacwait;
                           else                                
                           state   <= maccess;
                           end if;
                           P_VALID<='1';
        --******************************************************************************
        --Writing the Decoder status 
        --******************************************************************************
        when dacwait    => if(clkdriven='1') then
                           state   <= wsetup;
                           P_VALID<='1';
                           wsample <= wsample+x"8000";
                           else
                           P_VALID<='0';
                           state   <= dacwait;
                           end if;
                           MPADDR<=x"00000000";
                           MPWDATA<=x"00000000";
        when wsetup     => state<=waccess;                           
                           MPADDR<= x"40020500";--address of DAC0 
                           MPWDATA(15 downto 0)<=wsample;
                           P_VALID<='1';                           
        when waccess    => if(MPREADY='1') then 
                                if(length=x"fff") then
                                state<=idle1;
                                STOP<='1';
                                else                          
                                state<=msetup;                           
                                end if;
                           end if;  
                           P_VALID<='1';
        when idle1      => state<=idle1;
                           MPADDR<=x"00000000";
                           MPWDATA<=x"00000000";
                           P_VALID<='0';       
        when others     => state<=idle;
      end case;
   end if;
 end if;
end process;

--******************************************************************************
-- Registering MPSEL and MPENABLE
--******************************************************************************

sel2:process(PCLK)
begin

if (PCLK'event and PCLK = '1') then 
      if(state = waccess or state = maccess)then
        MPSEL<='1';
        MPENABLE<='1';        
      elsif(state = msetup or state = wsetup)then
        MPSEL<='1';
        MPENABLE<='0';        
      else
        MPSEL<='0';
        MPENABLE<='0';        
      end if;
end if;

end process sel2;

--******************************************************************************
-- deriving sampling frequency from fabclk
--******************************************************************************
clkgen:process(PCLK,PRESET,START)
begin
if(START='0' or PRESET='0') then
count<=x"0000";
else
if(PCLK'event and PCLK='0') then
    count<=count+1;
    if(count=samplerate) then
    clkdriven<='1';
    count<=x"0000";
    else
    clkdriven<='0';
    end if;
end if;
end if;
end process clkgen;
--******************************************************************************
-- Registering MPWRITE
--******************************************************************************
pwrite:process(PCLK)
begin
if(PCLK'event and PCLK='1') then
    if(state = wsetup) then
    MPWRITE <= '1';
    elsif(state=waccess) then
    MPWRITE<='1';    
    else
    MPWRITE <= '0';
    end if;
end if;
end process pwrite;

end beh;
