module lvds_tx (
    input        i_rst_b,
    input        i_ddr_clk,
    output reg[1:0] o_ddr_data,

    input             i_fifo_empty,
    output            o_fifo_read_clk,
    output          o_fifo_pull,
    input      [31:0] i_fifo_data,
    input [3:0]     i_sample_gap,
    input             i_tx_state,
    input             i_sync_input,
    input           i_debug_lb,    
    output          o_tx_state_bit,
    output          o_sync_state_bit,
);

    // STATES and PARAMS
    localparam
        tx_state_sync = 1'b0,
        tx_state_tx  = 1'b1;
    localparam sync_duration_frames = 4'd10;   // at least 2.5usec
    localparam zero_frame = 32'b00000000_00000000_00000000_00000000;
    localparam lb_frame =   32'b10000100_00000011_01110000_01001000;
  // Internal Registers
    reg [3:0] r_sync_count;
    wire frame_pull_clock;
    wire frame_assign_clock;
    reg r_state;
    reg [3:0] r_phase_count;
  reg [31:0] r_fifo_data;
    reg r_pulled;
    reg r_schedule_zero_frame;

  // Initial conditions
  initial begin
        r_phase_count = 4'd15;
        r_fifo_data <= zero_frame;
  end

  assign o_fifo_read_clk = i_ddr_clk;
    assign o_tx_state_bit = r_state;
    assign o_sync_state_bit = 1'b0;
    assign o_fifo_pull = r_pulled;

    // SHIFT REGISTER
    always @(posedge i_ddr_clk) begin
        if (i_rst_b == 1'b0) begin
            r_phase_count <= 4'd15;
        end else begin
            o_ddr_data[1:0] <= r_fifo_data[2*r_phase_count+1 : 2*r_phase_count];
            r_phase_count <= r_phase_count - 1;
        end
    end
    // SYNC AND MANAGEMENT
  always @(posedge i_ddr_clk) begin
    if (i_rst_b == 1'b0) begin
            r_state <= tx_state_sync;
            r_pulled <= 1'b0;
            r_fifo_data <= zero_frame;
            r_sync_count <= sync_duration_frames;
            r_schedule_zero_frame <= 1'b0;
    end else begin
            case (r_state)
                //----------------------------------------------
                tx_state_sync: 
                begin                
                    if (r_phase_count == 4'd0) begin
                        if (r_schedule_zero_frame) begin
                            r_fifo_data <= zero_frame;
                            r_schedule_zero_frame <= 1'b0;
                        end
                    end else if (r_phase_count == 4'd1) begin
                        if (r_sync_count == 4'd0) begin
                            if (i_debug_lb && !i_tx_state) begin
                                r_fifo_data <= lb_frame;
                                r_state <= tx_state_sync;
                            end else if (!i_debug_lb && i_tx_state) begin
                                r_pulled <= !i_fifo_empty;
                                r_state <= tx_state_tx;
                            end else begin
                                r_sync_count <= sync_duration_frames;
                                r_state <= tx_state_sync;
                                r_fifo_data <= zero_frame;
                            end
        end else begin
                            r_sync_count <= r_sync_count - 1;
                            r_schedule_zero_frame <= 1'b1;
                            //r_fifo_data <= zero_frame;
                            r_state <= tx_state_sync;
        end
                    end
                end
                //----------------------------------------------
                tx_state_tx: 
                begin
                    if (i_debug_lb || !i_tx_state) begin
                        r_state <= tx_state_sync;
                        r_sync_count <= sync_duration_frames;
                        r_pulled <= 1'b0;
                    end else if (r_phase_count == 4'd1) begin
                        r_pulled <= !i_fifo_empty;
                        r_state <= tx_state_tx;
                    end else if (r_phase_count == 4'd0) begin
                        if (r_pulled == 1'b0) begin
                            r_sync_count <= sync_duration_frames;
                            r_fifo_data <= zero_frame;
                            r_state <= tx_state_sync;
      end else begin
                            r_fifo_data <= i_fifo_data;
                            if (i_sample_gap > 0) begin
                                r_sync_count <= i_sample_gap;
                                r_state <= tx_state_sync;
                            end else begin
                                r_state <= tx_state_tx;
                            end
                        end
                        r_pulled <= 1'b0;
      end
                end
            endcase
    end
  end

endmodule
