///////////////////////////////////////////////////////////////////////////////////////////////////
// Company: Microsemi
//
// File: LMS_CONTROL_FSM.v
// File history:
//      1.0 : Date:28/10/2013 :Initial Release
//      <Revision number>: <Date>: <Comments>
//      <Revision number>: <Date>: <Comments>
//
// Description: This FSM provides control signals to LMS_ALGO block
//
// 
//
// Targeted device: <Family::Igloo2> <Die::M2GL010> <Package::484 FBGA>
// Author: Applications Engineering
//
/////////////////////////////////////////////////////////////////////////////////////////////////// 

`timescale 1 ns/100 ps
module LMS_CONTROL_FSM(
   CLK,
   ARST_N,
   START,
   COEF_DONE,
   ENABLE,
   OUTPUT_ENABLE,
   MUL_ENABLE,
   ADD_ENABLE,
   COEF_ON,
   UPDATE_ENABLE,
   DATAI_VALID,
   COUNT
  );

input CLK;
input ARST_N;
input START;
input COEF_DONE;

output MUL_ENABLE;
output ADD_ENABLE;
output UPDATE_ENABLE;
output COEF_ON;
output ENABLE;
output OUTPUT_ENABLE;
output [4:0] COUNT;
output DATAI_VALID;

reg ENABLE;
reg MUL_ENABLE;
reg ADD_ENABLE;
reg UPDATE_ENABLE;
reg COEF_ON;
reg OUTPUT_ENABLE;
reg [2:0] fsm;
reg [4:0] COUNT;
reg DATAI_VALID;

always@(posedge CLK or negedge ARST_N)
  if(~ARST_N)
    begin
      fsm <= 3'b000;
      ENABLE <= 1'b0;
      OUTPUT_ENABLE <= 1'b0;
      MUL_ENABLE <= 1'b0;
      ADD_ENABLE <= 1'b0;
      UPDATE_ENABLE <= 1'b0;
      COEF_ON <= 1'b0;
      COUNT <= 5'b00000;
      DATAI_VALID <=1'b1;
    end
  else
    begin
      case (fsm)
        3'b000 :  begin
                    COEF_ON <= 1'b0;
                    COUNT <= 5'b00000;
                    if (START)                             // when ever new sample comes go to next state 
                      begin 
                        ENABLE <= 1'b1;
                        DATAI_VALID <=1'b1;
                        fsm <= 3'b001;
                        ADD_ENABLE <= 1'b0;
                        MUL_ENABLE <= 1'b0;
                      end
                    else        
                      begin
                        ENABLE <= 1'b0;
                        OUTPUT_ENABLE <= 1'b0;
                        MUL_ENABLE <= 1'b0;
                        ADD_ENABLE <= 1'b0;
                        UPDATE_ENABLE <= 1'b0;
                        COEF_ON <= 1'b0;
                        fsm <= 3'b000;
                      end
                  end
        3'b001 :  begin
                    ENABLE <= 1'b0;          // wait for one clock cycle 
                    DATAI_VALID <=1'b0;
                    fsm <= 3'b010;
                  end
        3'b010 :  begin 
                    OUTPUT_ENABLE <= 1'b1;   // Generate control signal to find error signal
                    fsm <= 3'b011;
                  end
        3'b011 :  begin 
                    OUTPUT_ENABLE <= 1'b0;
                    MUL_ENABLE <= 1'b1;          // generate control signal to compute correction factor
                    fsm <= 3'b100;
                    COUNT <= COUNT+1'b1;
                  end
        3'b100 :  begin
                    ADD_ENABLE <= 1'b1;          // generate control signal to compute filter coefficient
                    fsm <= 3'b101;
                    COUNT <= COUNT+1'b1;
                  end
        3'b101 :  begin      
                    UPDATE_ENABLE <= 1'b1;    // generate control signal to send filter coefficient to core FIR
                    if(COUNT == 5'b01001) 
                      fsm <= 3'b110;
                    else 
                      begin
                        fsm <= 3'b101;
                        COUNT <= COUNT+1'b1;
                      end
                  end

        3'b110 :  begin 
                    fsm <= 3'b111;                     
                    UPDATE_ENABLE <= 1'b0;
                    ADD_ENABLE <= 1'b0;
                    MUL_ENABLE <= 1'b0;
                  end
        3'b111 :  begin 
                    fsm <= 3'b000;           // provides control signal to Core FIR to switch to new coefficient set loaded.
                    COEF_ON <= 1'b1;
                  end
       default :  fsm <= 3'b000;
       endcase
     end
   
endmodule



