module ff_fsm(
        clk,
        reset,
        ff_start,
        ff_trig,
        serv_busy,
        wake_on_0,
        wake_on_out,
        serv_enable_req,
        serv_cmdbyte_req
    );
    input clk;
    input reset;
    input ff_start;
    input ff_trig;
    input serv_busy;
    input wake_on_0;
    output wake_on_out;
    output serv_enable_req;
    output [7:0]serv_cmdbyte_req;
    reg ff_trig_out;
    reg sync0;
    reg sync1;
    reg sync2;
    reg sync3;
    reg sync4;
    reg pulse;
    reg [1:0]mux_sel_state;
    reg mux_sel;
    reg [1:0]pres_state;
    reg serv_enable_req;
    reg [7:0]serv_cmdbyte_req;
	
	//---
	//parameter st0:2'd0, st1:2'd1, st2:2'd2
	//parameter mux_idle:2'd0, mux_disable:2'd1, mux_ff_wait:2'd2
	parameter mux_disable=2'd0, mux_idle=2'd1, mux_ff_wait=2'd2;
	parameter idle=2'd0, start_ff=2'd1, wait_in=2'd2;
	
    assign wake_on_out = wake_on_0;
	
	
	
	
	
    always @ (  mux_sel or  ff_trig or  serv_busy)
    begin
        if ( ( mux_sel == 1'b0 ) & ( serv_busy == 1'b0 ) ) 
        begin
            ff_trig_out <=  ~( ff_trig);
        end
        else
        begin 
            ff_trig_out <= 1'b0;
        end
    end
    always @ (  posedge clk or negedge reset )
    begin
        if ( reset == 1'b0 ) 
        begin
            sync0 <= 1'b0;
            sync1 <= 1'b0;
            sync2 <= 1'b0;
            sync3 <= 1'b0;
            sync4 <= 1'b0;
        end
        else
        begin 
            if ( clk ) 
            begin
                sync0 <= ff_trig_out;
                sync1 <= sync0;
                sync2 <= sync1;
                sync3 <= sync2;
                sync4 <= sync3;
            end
        end
    end
    always @ (  posedge clk )
    begin
        if ( reset == 1'b0 ) 
        begin
            pulse <= 1'b0;
        end
        else
        begin 
            if ( clk ) 
            begin
                if ( ( sync3 == 1'b1 ) & ( sync4 == 1'b0 ) ) 
                begin
                    pulse <= 1'b1;
                end
                else
                begin 
                    pulse <= 1'b0;
                end
            end
        end
    end
	
	//------------FSM ------------
	//	parameter mux_disable:2'd0, mux_idle:2'd1, mux_ff_wait:2'd2
	
    always @ (  posedge clk or negedge reset)
    begin
        if ( reset == 1'b0 ) 
        begin
           // mux_sel_state <= 1'b0;
		    mux_sel_state <= mux_idle;
        end
        else
        begin 
            if ( clk ) 
            begin
                case ( mux_sel_state ) 
                //1'b0:
				mux_idle:
                begin
                    if ( pulse == 1'b1 ) 
                    begin
                        //mux_sel_state <= 1'b1;
						mux_sel_state <= mux_disable;
                    end
                end
                //1'b1:
				mux_disable:
                begin
                    if ( ff_start == 1'b1 ) 
                    begin
                        //mux_sel_state <= 1'b10;
						mux_sel_state <= mux_ff_wait;
                    end
                end
				
                //1'b10:
				mux_ff_wait:
                begin
                    if ( ff_start == 1'b0 ) 
                    begin
                        //mux_sel_state <= 1'b0;
						mux_sel_state <= mux_idle;
                    end
                end
                default : mux_sel_state <= mux_disable;

                endcase
            end
        end
    end
	


    always @ (  posedge clk or negedge reset)
    begin
        if ( reset == 1'b0 ) 
        begin
            mux_sel <= 1'b0;
        end
        else
        begin 
            if ( clk ) 
            begin
                //if ( mux_sel_state == 1'b1 ) 
				if ( mux_sel_state == mux_disable ) 
                begin
                    mux_sel <= 1'b1;
                end
                else
                begin 
                    //if ( mux_sel_state == 1'b10 ) 
					if ( mux_sel_state == mux_ff_wait ) 
                    begin
                        mux_sel <= 1'b1;
                    end
                    else
                    begin 
                        mux_sel <= 1'b0;
                    end
                end
            end
        end
    end
	
	
	//----------------------------------	
//parameter idle:2'd0. start_ff:2'd1, wait_in:2'd2;
    always @ (  posedge clk or negedge reset)
    begin
        if ( reset == 1'b0 ) 
        begin
            //pres_state <= 0'b0;
            pres_state <= idle;
        end
        else
        begin 
            if ( clk ) 
            begin
                case ( pres_state ) 
                //0'b0:
				idle:
                begin
                    if ( ( pulse == 1'b1 ) & ( serv_busy == 1'b0 ) ) 
                    begin
                        //pres_state <= 1'b1;
						pres_state <= start_ff;
                    end
                end
               
			   //1'b1:
			   start_ff:
                begin
                   // pres_state <= 1'b10;
				   pres_state <= wait_in;
				   
                end
                
				//1'b10:
				wait_in:
                begin
                    if ( serv_busy == 1'b0 ) 
                    begin
                        //pres_state <= 0'b0;
						pres_state <= idle;
                    end
                end
                default : pres_state <= idle;
              
                endcase
            end
        end
    end
    always @ (  posedge clk or negedge reset)
    begin
        if ( reset == 1'b0 ) 
        begin
            serv_enable_req <= 1'b0;
            serv_cmdbyte_req <= 8'b00000000;
        end
        else
        begin 
            if ( clk ) 
            begin
                //if ( pres_state == 1'b1 ) 
                if ( pres_state == start_ff ) 
                begin
                    serv_enable_req <= 1'b1;
                    serv_cmdbyte_req <= 8'b00000010;
                end
                else
                begin 
                    serv_enable_req <= 1'b0;
                    serv_cmdbyte_req <= 8'b00000000;
                end
            end
        end
    end
endmodule 