module lvds_rx (
    input       i_rst_b,
    input       i_ddr_clk,
    input [1:0] i_ddr_data,

    input             i_fifo_full,
    output            o_fifo_write_clk,
    output reg        o_fifo_push,
    output reg [31:0] o_fifo_data,
    input             i_sync_input,
    output     [ 1:0] o_debug_state
);

  // Internal FSM States
  localparam state_idle = 2'b00, state_i_phase = 2'b01, state_q_phase = 2'b11;

  // Modem sync symbols
  localparam modem_i_sync = 2'b10, modem_q_sync = 2'b01;

  // Internal Registers
  reg [1:0] r_state_if;
  reg [2:0] r_phase_count;
  reg r_sync_input;

  // Initial conditions
  initial begin
    r_state_if = state_idle;
    r_phase_count = 3'b111;
  end

  // Global Assignments
  assign o_fifo_write_clk = i_ddr_clk;
  assign o_debug_state = r_state_if;

  // Main Process
  always @(posedge i_ddr_clk or negedge i_rst_b) begin
    if (i_rst_b == 1'b0) begin
      r_state_if <= state_idle;
      o_fifo_push <= 1'b0;
      r_phase_count <= 3'b111;
      r_sync_input <= 1'b0;
    end else begin
      case (r_state_if)
        state_idle: begin
          if (i_ddr_data == modem_i_sync) begin
            r_state_if   <= state_i_phase;
            o_fifo_data[1:0]  <= 2'b10;
            r_sync_input <= i_sync_input;  // mark the sync input for this sample
          end
          r_phase_count <= 3'b110;
          o_fifo_push   <= 1'b0;
        end

        state_i_phase: begin
          if (r_phase_count == 3'b111) begin
            if (i_ddr_data == modem_q_sync) begin
              r_state_if <= state_q_phase;
            end else begin
              r_state_if <= state_idle;
            end
          end 
          
          r_phase_count <= r_phase_count - 1;
          o_fifo_push <= 1'b0;
          o_fifo_data <= {o_fifo_data[29:0], i_ddr_data};
        end

        state_q_phase: begin
          if (r_phase_count == 3'b000) begin
            o_fifo_push <= ~i_fifo_full;
            r_state_if  <= state_idle;
          end else begin
            o_fifo_push   <= 1'b0;
          end

          o_fifo_data   <= {o_fifo_data[29:0], i_ddr_data};
          r_phase_count <= r_phase_count - 1;
        end
      endcase
    end
  end

endmodule
