///////////////////////////////////////////////////////////////////////////////////////////////////
// Company: Microsemi
//
// File: DATAHANDLE_FSM.v
// File history:
//               1.0 : Date:03/05/2013 :Initial Release
//               2.0 : Date: 29/07/2013 : 11.1 SP1 Update 
//               <Revision number>: <Date>: <Comments>
//               <Revision number>: <Date>: <Comments>
//
// Description: This FSM implements an APB wrapper to send and recieve data from APB bus and
// loads the recieved data to Input Buffer and read backs the data from Output Buffer and FFT buffers.
// 
// 
// Targeted device: <Family::SmartFusion2> <Die::M2S050T> <Package::896 FBGA>
// Author: Applications Engineering
//
/////////////////////////////////////////////////////////////////////////////////////////////////// 


`timescale 1 ns/100 ps
module DATAHANDLE_FSM(
  PCLK,
  PENABLE,
  PSEL,
  PRESETN,
  PWRITE,
  PREADY,
  PSLVERR,
  PADDR,
  PWDATA,
  PRDATA,
  FILTER_COMPLETE,
  FIR_FFT_RD_ENABLE, 
  INPUT_WR_ENABLE,
  WCLK, 
  RCLK,
  FFT_RE_RADDR,
  INPUT_WADDR,
  SEL,
  FIR_DATA_OUT,
  FIR_RADDR,
  FIR_ENABLE,
  FFT_IM_DATA,
  FFT_IM_RADDR,
  MEM_DATA_IN,
  FFT_VALID,
  FFT_RE_RD
  );



input  FILTER_COMPLETE;    
input  PCLK,PENABLE, PSEL, PRESETN, PWRITE;
input  [15:0] PADDR;
input  [15:0] PWDATA;
input  [15:0] FFT_RE_RD;
input  [15:0] FFT_IM_DATA;
input  [15:0] FIR_DATA_OUT;
input  [1:0] FIR_ENABLE;

output [15:0] PRDATA;
output PREADY, PSLVERR;
output FIR_FFT_RD_ENABLE;
output INPUT_WR_ENABLE;
output WCLK,RCLK;
output [9:0]  FFT_RE_RADDR,  INPUT_WADDR,FFT_IM_RADDR;
output [15:0] MEM_DATA_IN;
output [9:0] FIR_RADDR;
output SEL; 
output FFT_VALID;

reg SEL; 
reg [9:0]  FFT_RE_RADDR, FIR_RADDR,FFT_IM_RADDR;
reg FIR_FFT_RD_ENABLE;
reg INPUT_WR_ENABLE;
reg COEF_WR_EN;
reg PREADY;
reg [15:0] PRDATA;
reg  [1:0]   fsm;                     //state machine register
reg FFT_VALID;


wire WCLK,RCLK;
wire [9:0]  INPUT_WADDR;
wire [5:0] COEF_WADDR;
wire FILTER_COMPLETE; 
wire [15:0] MEM_DATA_IN;
wire [15:0] FFT_RE_RD;
wire [15:0] FIR_DATA_OUT,FFT_IM_DATA;

assign PSLVERR = 1'b0;
assign MEM_DATA_IN = PWDATA;
assign WCLK = PCLK;
assign RCLK = PCLK;
assign INPUT_WADDR[9:0] = PADDR[11:2];
assign COEF_WADDR  = PADDR[7:2];

always@(PADDR)
  begin
    if(FIR_ENABLE == 2'b00)
      begin
        FIR_RADDR[9:0] = PADDR[11:2];
        PRDATA = FIR_DATA_OUT;
      end
    else if(FIR_ENABLE == 2'b01)
      begin
         FFT_RE_RADDR[9:0] = PADDR[11:2];
         PRDATA = FFT_RE_RD;
      end
    else if(FIR_ENABLE == 2'b10)
      begin
        FFT_IM_RADDR[9:0] = PADDR[11:2];
        PRDATA = FFT_IM_DATA;
      end
  end

always@(posedge PCLK or negedge PRESETN)
  if(~PRESETN)
    begin
      fsm <= 2'b00;
      FIR_FFT_RD_ENABLE <= 1'b0;
      INPUT_WR_ENABLE <= 1'b0;
      FFT_VALID <= 1'b0;
      PREADY <= 1'b1;
	  SEL <= 1'b0;
    end
  else
    begin
      case (fsm)
      2'b00 :  begin
                 if (~PSEL)
                   begin
                     fsm <= 2'b00;                          
                   end
                 else        
                   begin
                     fsm <= 2'b01;
                     if (PWRITE)
                       begin
                         INPUT_WR_ENABLE <= 1'b1;
                         PREADY <= 1'b1;
                       end
                   end
               end
       2'b01 :  begin    
                  if (PWRITE)
                    begin 
                      FIR_FFT_RD_ENABLE <= 1'b0;
                      fsm <= 2'b00;
                      if (PADDR[11:2] == 10'b1111111111 )
					    begin
					      SEL <= 1'b1;
                          fsm<=2'b10;
					    end
                     end
                   else
                     begin      
                       INPUT_WR_ENABLE <= 1'b0;
					   COEF_WR_EN <= 1'b0;
                       FIR_FFT_RD_ENABLE <= 1'b1;
                       FFT_VALID <= 1'b1;
                       PREADY <= 1'b1;
                       fsm <= 2'b10; 
                     end
                end

      2'b10 :  begin       
                fsm <= 2'b11;
                FFT_VALID <= 1'b0;
                SEL <= 1'b0;
              end

      2'b11 :  begin     
                fsm <= 2'b00;
                SEL <= 1'b0;     
              end

      default : fsm <= 2'b00;
      endcase
    end 

endmodule