-------------------------------------------------------------------------------
-- Title      : DSP coprocessor 
-------------------------------------------------------------------------------
-- File       : Aapb_int_fft.vhd
-- Author     : Manish Kumar
--              manish.kumar@actel.com
-- Company    : Actel Corporation
-- Device     : SmartFusion 
-- Standard   : VHDL
-------------------------------------------------------------------------------
-- Description: The DSP coprocessor has CoreFFT IP, 64x16 FIFO 
--              and a custom-made APB3 interface.
-------------------------------------------------------------------------------
-- Copyright (c) 2010   Actel Corporation
--                      All rights reserved.
-------------------------------------------------------------------------------
-- Revisions  : V1.0 
-------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
USE work.fft_components.all;


entity Aapb_int_fft is
port (
      PRESETn    : in std_logic;
      PCLK       : in std_logic; 

      -- Address control

      PSEL_S0    : in std_logic;
      PADDR      : in std_logic_vector(31 downto 0);
      PWRITE     : in std_logic;
      PENABLE    : in std_logic;
      PWDATA     : in std_logic_vector(31 downto 0);

      -- Output signal and data

      PSLVERR    : out std_logic;
      PREADY     : out std_logic;
      PRDATA     : out std_logic_vector(31 downto 0);
      FFT_IP_RDY : out std_logic;
      FFT_OP_RDY : out std_logic;
      AEMPTY_OUT  : out std_logic;
      EMPTY_OUT  : out std_logic
      
);
end Aapb_int_fft;

--architecture behav of Aapb_int_fft is
--begin
--end behav;


architecture behav of Aapb_int_fft is

component fftTop 
  generic (
    LOGPTS      : integer := gLOGPTS;
    LOGLOGPTS   : integer := gLOGLOGPTS;
    WSIZE       : integer := gWSIZE;
    TWIDTH      : integer := gTWIDTH;
    DWIDTH      : integer := gDWIDTH;
    TDWIDTH     : integer := gTDWIDTH;
    RND_MODE    : integer := gRND_MODE;
    SCALE_MODE  : integer := gSCALE_MODE;
    PTS         : integer := gPTS;
    HALFPTS     : integer := gHALFPTS;
    inBuf_RWDLY : integer := gInBuf_RWDLY  );
  port (
    clk,ifiStart,ifiNreset : IN std_logic;
    ifiD_valid, ifiRead_y  : IN std_logic;
    ifiD_im, ifiD_re       : IN std_logic_vector(WSIZE-1 DOWNTO 0);
    ifoLoad, ifoPong       : OUT std_logic;
    ifoY_im, ifoY_re       : OUT std_logic_vector(WSIZE-1 DOWNTO 0);
    ifoY_valid, ifoY_rdy   : OUT std_logic);
end component;

component fifo512x32 
  port( DATA          : in std_logic_vector(31 downto 0);
        Q             : out std_logic_vector(31 downto 0);
        WE, RE, CLK   : in std_logic;
        FULL, EMPTY   : out std_logic;  
        RESET         : in std_logic;  
        AEMPTY, AFULL : out std_logic) ;
end component;

signal data_val_FFT : std_logic;
signal fifo_rd_en   : std_logic;
signal fft_out_en   : std_logic;
signal data_out_reg : std_logic_vector(31 downto 0);
signal ifoY_wire    : std_logic;
signal ifoY_valid   : std_logic;
signal ifoY_re      : std_logic_vector(15 downto 0);
signal ifoY_im      : std_logic_vector(15 downto 0);
signal q_out        : std_logic_vector(31 downto 0);
signal afull_wire   : std_logic;
signal START_FFT    : std_logic;
signal flag         : std_logic;
signal PREADY0      : std_logic;
signal PREADY1      : std_logic;
signal PSEL_reg     : std_logic;
signal PENABLE_reg  : std_logic;
signal EMPTY_OUT_REG: std_logic;

signal FFT_IP_RDY_int : std_logic;
signal EMPTY_OUT_int  : std_logic;


begin

data_val_FFT        <= (PSEL_S0 and PENABLE and PWRITE);
fifo_rd_en          <= (not((not PENABLE_reg) and PENABLE and PSEL_S0 and (not PWRITE)));
PRDATA(31 downto 0) <= q_out;
PREADY              <= FFT_IP_RDY_int when (PWRITE = '1') else (PREADY0 and PREADY1 and (not EMPTY_OUT_REG));
FFT_IP_RDY          <= FFT_IP_RDY_int;
EMPTY_OUT           <= EMPTY_OUT_int;


process (PRESETn,PCLK)
begin
   if (PRESETn = '0') then
      EMPTY_OUT_REG <= '0';
   elsif (PCLK'event and PCLK='1') then
     if(((not PSEL_reg) and PSEL_S0) = '1') then
      EMPTY_OUT_REG <= EMPTY_OUT_int;
     end if;
   end if;
end process;

process (PRESETn,PCLK)
begin
   if (PRESETn = '0') then
       START_FFT <= '0';
       flag      <= '0';
   elsif (PCLK'event and PCLK='1') then
     if(flag = '0') then 
       START_FFT <= '1';
       flag      <= '1';
     else
       START_FFT <= '0';
     end if;
   end if;
end process;


--******************************************************************************
-- To put output in burst FFT_out_en is active high
-- To put wait state in output bring it at low state
--******************************************************************************

process (PRESETn,PCLK)
begin
   if (PRESETn = '0') then
      fft_out_en <= '1';
   elsif (PCLK'event and PCLK='1') then
     if(afull_wire = '1') then 
       fft_out_en <= '0';
     else
       fft_out_en  <= '1';
     end if;
   end if;
end process;

process (PRESETn,PCLK)
begin
   if (PRESETn = '0') then
      data_out_reg  <= (others => '0');
      ifoY_valid    <= '1';
   elsif (PCLK'event and PCLK='1') then
     if(ifoY_wire = '1') then 
       data_out_reg <= (ifoY_im & ifoY_re);
       ifoY_valid   <= '0';
     else
       data_out_reg <= (ifoY_im & ifoY_re);
       ifoY_valid   <= '1';
     end if;
   end if;
end process;

process (PRESETn,PCLK)
begin
   if (PRESETn = '0') then
       PREADY0 <= '1';
       PREADY1 <= '1';
   elsif (PCLK'event and PCLK='1') then
     if (((not PSEL_reg) and PSEL_S0) = '1') then 
       PREADY0 <= '0';
       PREADY1 <= PREADY0;
     else
       PREADY0 <= '1';
       PREADY1 <= PREADY0;
     end if;
   end if;
end process;

--******************************************************************************
-- Registering PSEL and PENABLE
--******************************************************************************

process (PRESETn,PCLK)
begin
   if (PRESETn = '0') then
     PSEL_reg    <= '0';    
     PENABLE_reg <= '0';
   elsif (PCLK'event and PCLK='1') then
     PSEL_reg    <= PSEL_S0;    
     PENABLE_reg <= PENABLE;
   end if;
end process;

--******************************************************************************
-- Instantiation of Core FFT
--******************************************************************************

fftTop_inst : fftTop 
  generic map (
    LOGPTS      => gLOGPTS,
    LOGLOGPTS   => gLOGLOGPTS,
    WSIZE       => gWSIZE,
    TWIDTH      => gTWIDTH,
    DWIDTH      => gDWIDTH,
    TDWIDTH     => gTDWIDTH,
    RND_MODE    => gRND_MODE,
    SCALE_MODE  => gSCALE_MODE,
    PTS         => gPTS,
    HALFPTS     => gHALFPTS,
    inBuf_RWDLY => gInBuf_RWDLY)
  port map (
    clk         => PCLK,
    ifiStart    => START_FFT,
    ifiNreset   => PRESETn,
    ifiD_valid  => data_val_FFT,
    ifiRead_y   => fft_out_en,
    ifiD_im     => PWDATA(31 downto 16),
    ifiD_re     => PWDATA(15 downto 0),
    ifoLoad     => FFT_IP_RDY_int,
    ifoPong     => open,
    ifoY_im     => ifoY_im,
    ifoY_re     => ifoY_re,
    ifoY_valid  => ifoY_wire,
    ifoY_rdy    => FFT_OP_RDY
   );

--******************************************************************************
-- Instantiation of out put FIFO
--******************************************************************************

fifo512X32_inst : fifo512x32 
  port map (
	DATA     => data_out_reg,
	Q        => q_out,
	WE       => ifoY_valid,
	RE       => fifo_rd_en,
	CLK      => PCLK,
	FULL     => open,
	EMPTY    => EMPTY_OUT_int,
	RESET    => PRESETn,
	AEMPTY   => AEMPTY_OUT,
	AFULL    => afull_wire
  );

end behav;