module gtx_tx_reset_controller (
  input  wire clk,

  input  wire ref_clk,
  input  wire powerup_channel,
  
  input  wire plllock,
  
      
  input  wire txresetdone,

  output reg  tx_running,      //: out std_logic := '0';
  output reg  txreset,         //: out std_logic := '1';
  output reg  txuserrdy,       //: out std_logic := '0';
  output reg  txpmareset,      //: out std_logic := '1';
  output reg  txpcsreset,      //: out std_logic := '1';
  
  output reg  pllpd,           //: out std_logic := '1';
  output reg  pllreset,        //: out std_logic;
  output reg  plllocken,       //: out std_logic := '1';
  
  output reg  resetsel         //  out std_logic := '0'
);

    reg [3:0] state;
    reg [7:0] ref_clk_counter;
    reg [7:0] counter;
    reg       ref_clk_detect_last;
    reg       ref_clk_detect;       
    reg       ref_clk_detect_meta;  // TODO: Neet to set ASYNCREG
    reg       txresetdone_meta;     // TODO: Neet to set ASYNCREG
    reg       txresetdone_i;

initial begin
    state                = 4'b0000;
    ref_clk_counter      = 8'b00000000;
    counter              = 8'b00000000;

    ref_clk_detect_last  = 1'b0;
    ref_clk_detect       = 1'b0;       
    ref_clk_detect_meta  = 1'b0;
    txresetdone_meta     = 1'b1;
    txresetdone_i        = 1'b1;
    tx_running           = 1'b1;
    
    txreset    <= 1'b1;
    txuserrdy  <= 1'b0;
    txpmareset <= 1'b1;
    txpcsreset <= 1'b1;
    pllpd      <= 1'b1;
    pllreset   <= 1'b1;
    plllocken  <= 1'b0;
    resetsel   <= 1'b0;
end    
    
always @(posedge ref_clk) begin
     ref_clk_counter <= ref_clk_counter + 1;
end

always @(posedge clk) begin

    counter             <= counter + 1;

    case(state)
      4'b0000: begin // reset
                 txreset    <= 1'b1;
                 txuserrdy  <= 1'b0;
                 txpmareset <= 1'b0;
                 txpcsreset <= 1'b0;
                 pllpd      <= 1'b1;
                 pllreset   <= 1'b1;
                 plllocken  <= 1'b0;
                 resetsel   <= 1'b0;
                 state      <= 4'b0001;
               end

      4'b0001: begin // wait for reference clock
                 counter <= 8'b00000000;
                 if(ref_clk_detect == ref_clk_detect_last) begin
                   state <= 4'b0001;
                 end else begin
                   state <= 4'b0010;
                 end
               end

      4'b0010: begin // wait for 500ns
                 // counter will set high bit after 128 cycles
                 if(counter[7] == 1'b1) begin
                   state <= 4'b0011;
                 end
               end
  
      4'b0011: begin // start up the PLL
                 pllpd     <= 1'b0;
                 pllreset  <= 1'b0;
                 plllocken <= 1'b1;
                 state     <= 4'b0100;
               end

      4'b0100: begin // Waiting for the PLL to lock
                 if(plllock == 1'b1) begin
                   state <= 4'b0101;
                 end
               end

      4'b0101: begin //- Starting up the GTX
                 txreset   <= 1'b0;
                 state     <= 4'b0110;
                 counter   <= 8'b00000000;
               end

      4'b0110: begin // wait for 500ns
                 // counter will set high bit after 128 cycles
                 if(counter[7] == 1'b1) begin
                   state <= 4'b0111;
                 end
               end

      4'b0111: begin // power up the user data path
                 txuserrdy <= 1'b1;
                 if(txresetdone_i == 1'b1) begin
                   state <= 4'b1000;
                 end 
               end

      4'b1000: begin // All running
                 tx_running <= 1'b1;    
               end

      default: begin
                 state      <= 4'b0000;
               end
    endcase

    if(powerup_channel == 1'b0) begin
        state <= 4'b0000;
    end


    ref_clk_detect_last <= ref_clk_detect;
    ref_clk_detect      <= ref_clk_detect_meta;
    ref_clk_detect_meta <= ref_clk_counter[7];
            
    txresetdone_i    <= txresetdone_meta;
    txresetdone_meta <= txresetdone;
  end
endmodule