//! ADC trigger
//!
//! ADC trigger sends adc requests to the Gowin ADC hardware module.
//!
//! Waits for hardware adc ready signal to go low before releasing
//! the request. If for some reason the ready signal is NOT high
//! when the trigger is requested, simply waits a few cycles and
//! releases the request.

module adctrig
( 
    input   CLK,
    input   RESET,
    input   ADC_TRIG, //! Trigger input from controller
    output  ADC_TRIG_ACK, //! Acknowledge output to controller

    input   ADC_READY, //! Ready from Gowin ADC
    output  ADC_REQ  //! Request output to Gowin ADC
);

reg ack;
reg req;
reg [1:0] ready_cdc;
wire adcready = ready_cdc[1];
reg [3:0] reqcounter;

reg [1:0] state;
localparam      IDLE = 2'b00,
                WAIT_READY_FALL = 2'b01,
                WAIT_COUNTER = 2'b10,
                WAIT_ACK = 2'b11;

//! Clock domain crossing for hardware signals
always @(posedge CLK or posedge RESET) begin
    if(RESET)
        ready_cdc <= 2'b00;
    else 
        ready_cdc <= {ready_cdc[0], ADC_READY};
end

always @(posedge CLK or posedge RESET) begin
    if(RESET) begin
        ack <= 1'b0;
        req <= 1'b0;
        reqcounter <= 4'd0;
        state <= IDLE;
    end 
    else begin
        case(state) 
        IDLE: begin
            ack <= 1'b0;
            if(ADC_TRIG) begin
                req <= 1'b1;
                if(adcready) begin
                    state <= WAIT_READY_FALL;
                end
                else begin
                    state <= WAIT_COUNTER;
                    reqcounter <= 4'd15;
                end
            end 
        end
        
        WAIT_READY_FALL: begin
            if(!adcready) begin
                state <= WAIT_ACK;
                ack <= 1'b1;
                req <= 1'b0;
            end            
        end

        WAIT_COUNTER: begin
            if(reqcounter == 4'd0) begin
                state <= WAIT_ACK;
                ack <= 1'b1;
                req <= 1'b0;
            end
            else begin
                reqcounter <= reqcounter - 4'd1;
            end
        end

        WAIT_ACK: begin
            if(!ADC_TRIG) begin
                ack <= 1'b0;
                state <= IDLE;
            end
        end

        endcase
    end
end

assign ADC_REQ = req;
assign ADC_TRIG_ACK = ack;

endmodule
