
`timescale 1 ns/100 ps
/*-------------------------------------------------------------------------------
-- Title      : DSP coprocessor 
-------------------------------------------------------------------------------
-- File       : Aapb_int_fft.v
-- Author     : Manish Kumar
--              manish.kumar@actel.com
-- Company    : Actel Corporation
-- Device     : SmartFusion 
-- Standard   : Verilog
-------------------------------------------------------------------------------
-- 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 
-------------------------------------------------------------------------------*/

module Aapb_int_fft(
input                     PRESETn,
input                     PCLK,

// Address control

input                     PSEL_S0,
input              [31:0] PADDR,
input                     PWRITE,
input                     PENABLE,
input              [31:0] PWDATA,

//Output signal and data

output                    PSLVERR,
output                    PREADY,
output             [31:0] PRDATA,
output                    FFT_IP_RDY,        // FFT ready to accept data
output                    FFT_OP_RDY,        // FFT ready to send data
output                    AEMPTY_OUT,
output                    EMPTY_OUT);

wire                      data_val_FFT;
wire                      fifo_rd_en;
reg                       fft_out_en;

reg                [15:0] data_out_reg;
wire                      ifoY_wire;
reg                       ifoY_valid;
wire                [7:0] ifoY_re;
wire                [7:0] ifoY_im;
wire               [15:0] q_out;
wire                      afull_wire;
reg                       START_FFT;
reg                       flag;
reg                       PREADY0;
reg                       PREADY1;
reg                       PSEL_reg;
reg                       PENABLE_reg;
reg                       EMPTY_OUT_REG;



assign data_val_FFT = (PSEL_S0 & PENABLE & (PWRITE))? 1'b1: 1'b0;
assign fifo_rd_en   = (~((~PENABLE_reg) & PENABLE & PSEL_S0 & (~PWRITE)));
assign PRDATA[15:0] = q_out;
assign PREADY       = PWRITE ? FFT_IP_RDY : PREADY0 & PREADY1 & (~EMPTY_OUT_REG) ;

always @(negedge PRESETn or posedge PCLK)
begin
   if (PRESETn ==1'b0)
   begin
       EMPTY_OUT_REG <= 1'b0;
   end 
   else if((~PSEL_reg) & PSEL_S0)
   begin
      EMPTY_OUT_REG <= EMPTY_OUT;
   end
end

always @(negedge PRESETn or posedge PCLK)
begin
   if (PRESETn ==1'b0)
   begin
       START_FFT <= 1'b0;
       flag      <= 1'b0;
   end 
   else if(flag == 1'b0) 
   begin
       START_FFT <= 1'b1;
       flag      <= 1'b1;
   end
   else begin
       START_FFT <= 1'b0;
   end
end
/******************************************************************************/
// To put output in burst FFT_out_en is active high
// To put wait state in output bring it at low state
/******************************************************************************/

always @(negedge PRESETn or posedge PCLK)
begin
   if (PRESETn ==1'b0)
   begin
   fft_out_en  <= 1'b1;
   end
   else if(afull_wire == 1'b1)
   begin
       fft_out_en <= 1'b0;
   end
   else fft_out_en  <= 1'b1;
end

always @(negedge PRESETn or posedge PCLK)
begin
   if (PRESETn ==1'b0)
   begin
       data_out_reg <= 16'd0;
       ifoY_valid   <= 1'b1;
   end
   else if(ifoY_wire == 1'b1) 
   begin
       data_out_reg <= {ifoY_im,ifoY_re};
       ifoY_valid   <= 1'b0;
   end
   else
   begin
       data_out_reg <= {ifoY_im,ifoY_re};
       ifoY_valid   <= 1'b1;
   end
end   


always @(negedge PRESETn or posedge PCLK)
begin
   if (PRESETn ==1'b0)
   begin 
       PREADY0 <= 1'b1;
       PREADY1 <= 1'b1;
   end
   else if ((~PSEL_reg) & PSEL_S0)
   begin
        PREADY0 <= 1'b0;
        PREADY1 <=  PREADY0;
   end
   else begin
        PREADY0 <= 1'b1;
        PREADY1 <=  PREADY0;
   end

end

/******************************************************************************/
// Registering PSEL and PENABLE
/******************************************************************************/ 
always @(negedge PRESETn or posedge PCLK)
begin
   if (PRESETn ==1'b0)
   begin  
       PSEL_reg <= 1'b0;    
       PENABLE_reg <= 1'b0;
   end
   else
   begin
       PSEL_reg <= PSEL_S0;    
       PENABLE_reg <= PENABLE;

   end
end 

     
/******************************************************************************/
// Instantiation of Core FFT
/******************************************************************************/



fftTop  fftTop_inst(
	.clk(PCLK),
	.ifiStart(START_FFT),
	.ifiNreset(PRESETn),
	.ifiD_valid(data_val_FFT),
	.ifiD_im(PWDATA[15:8]),
	.ifiD_re(PWDATA[7:0]),
	.ifiRead_y(fft_out_en),
	.ifoLoad(FFT_IP_RDY),
	.ifoY_im(ifoY_im),
	.ifoY_re(ifoY_re),
	.ifoPong(),
	.ifoY_valid(ifoY_wire),
	.ifoY_rdy(FFT_OP_RDY));

/******************************************************************************/
// Instantiation of out put FIFO
/******************************************************************************/


fifo64x16 fifo64X16_inst(
	.DATA(data_out_reg),
	.Q(q_out),
	.WE(ifoY_valid),
	.RE(fifo_rd_en),
	.CLK(PCLK),
	.FULL(),
	.EMPTY(EMPTY_OUT),
	.RESET(PRESETn),
	.AEMPTY(AEMPTY_OUT),
	.AFULL(afull_wire));

endmodule