///////////////////////////////////////////////////////////////////////////////////////////////////
// Company: Microsemi Corporation
//
// File: FILTERCONTROL_FSM.v
// File history:
//      1.0 Date: 7 Feb 2013 : Initial release
//      2.0 Date: 29 Jul 2013 : 11.1 SP1 Update
//      <Revision number>: <Date>: <Comments>
//      <Revision number>: <Date>: <Comments>
//
// Description: Controls the FIR filter and FFT operations. Loads the filtered data to
// corresponding output buffer and moves the FFT output data to the corresponding output data
// buffer.
// SmartFusion2: FIR FILTER DEMO
//
// Targeted device: <Family::SmartFusion2> <Die::M2S050T> <Package::896 FBGA>
// Author: Applications Engineering
//
/////////////////////////////////////////////////////////////////////////////////////////////////// 

`timescale 1 ns/100 ps
module FILTERCONTROL_FSM(
  PCLK,
  PRESETN,
  FILTER_COMPLETE, 
  FFT_START,
  FIR_WR_ENABLE,
  WCLK,
  RCLK,
  FIR_WR_ADDR,
  FFT_WADDR,
  SEL,
  COEF_RADDR,
  COEF_RD_ENABLE,
  COEF_ON
  );

parameter DATA_WIDTH = 16; // data width 
parameter ADDR_WIDTH = 16; // address width 



input PCLK, PRESETN;
input FFT_START;
input SEL;

output FILTER_COMPLETE; 
output FIR_WR_ENABLE;
output WCLK, RCLK;
output [9:0]   FFT_WADDR;
output [9:0]   FIR_WR_ADDR;
output  [5:0] COEF_RADDR;
output COEF_ON;
output COEF_RD_ENABLE;

 
reg  FILTER_COMPLETE;
reg  FIR_WR_ENABLE;
reg [9:0]   FFT_WADDR;
reg [9:0]   FIR_WR_ADDR;
reg  [2:0] fsm;             //state machine register
reg  COEF_RD_ENABLE;
reg  COEF_ON;
reg  [5:0] COEF_RADDR;

wire WCLK, RCLK;


assign WCLK = PCLK;
assign RCLK = PCLK;



always@(posedge PCLK or negedge PRESETN)
if(~PRESETN)
  begin
      fsm <= 3'b000;
      FIR_WR_ENABLE <= 1'b0;
      FIR_WR_ADDR <= 10'b0000000000;
      FFT_WADDR <= 10'b0000000000;
      FILTER_COMPLETE <=1'b0;
	  COEF_RADDR <= 6'b000000;
      COEF_RD_ENABLE <=1'b0;
      COEF_ON <= 1'b0;

  end
else
  begin
  
  case (fsm)
     3'b000 :  begin
                  if (SEL)
                       begin 
                         COEF_RD_ENABLE <= 1'b1;
                         FIR_WR_ENABLE <= 1'b0;
                         FIR_WR_ADDR <= 10'b0000000000;
                         FFT_WADDR <= 10'b0000000000;
                         COEF_RADDR <= 6'b000000;
                         COEF_ON <= 1'b0;
                         fsm <= 3'b001;
                        end
                  else        
                       begin
                          fsm <= 3'b000;
                          FIR_WR_ENABLE <= 1'b0;
                       end
                  end

     3'b001 :  begin 
                       COEF_RADDR <= COEF_RADDR+1;
                       if(COEF_RADDR == 6'b001111)
                           fsm <= 3'b010;
                       else
                          fsm <= 3'b001;
               end

     3'b010 : begin      
                       COEF_RD_ENABLE <=1'b0;
                       COEF_ON <= 1'b1;
                       fsm <= 3'b011;
              end

     3'b011 : begin      
                       FIR_WR_ADDR <= FIR_WR_ADDR+1;    
                       FIR_WR_ENABLE <= 1'b1;
                       COEF_ON <= 1'b0;
                       if(FIR_WR_ADDR == 10'b1111111111)
                          fsm <= 3'b100;
                       else
                          fsm <= 3'b011;
              end


     3'b100 :  begin            
                         if (FFT_START)
                         begin 
                           FFT_WADDR <= FFT_WADDR+1; 
                         if(FFT_WADDR == 10'b0011111111)
                         begin
                           FILTER_COMPLETE <=1'b1;
                           fsm <= 3'b000;
                         end
                         else 
                         begin
                          fsm <= 3'b100;                              
                         end
                        end
               end



    default : fsm <= 3'b000;
  endcase
end
   
endmodule