module UartTxTop #(parameter FIFOSIZE = 16)
(
  input clk,                        // system clock
  input [7:0]fifo_wr_push_data,     // data to be sent (put into fifo_wr)
  input fifo_wr_push,               // on pos edge data is written
  input clear,
  output fifo_wr_full,              
  output tx_pin                     
  );                                


  wire uart_clk;
  wire uart_rxclk;

  wire fifo_wr_empty;
  reg fifo_wr_pop = 0;
  wire [7:0]fifo_wr_pop_data;

  wire is_uart_tx_ready;
  reg [7:0]tx_data;
  reg tx_data_valid_state = 0;
  wire is_rx_data_valid;
  reg uart_clk_tm1 = 0;

  Fifo #(.FIFOSIZE(FIFOSIZE)) Fifo_wr
  (
  	.clk(clk) ,	                          // input  clk_sig
  	.data_push(fifo_wr_push_data) ,	      // input [7:0] data_push_sig
  	.push(fifo_wr_push) ,	                // input  push_sig
  	.pop(fifo_wr_pop) ,	                  // input  pop_sig
    .clear(clear),
  	.fifo_full(fifo_wr_full) ,	          // output  fifo_full_sig
  	.fifo_empty(fifo_wr_empty) ,	        // output  fifo_empty_sig
  	.data_pop(fifo_wr_pop_data) 	        // output [7:0] data_pop_sig
  );


  UartClock UartClock_inst
  (
  	.i_clk(clk) ,
  	.o_clk(uart_clk), 	
  	.o_clk2(uart_rxclk) 	
  );


  UartTx UartTx_inst
  (
  	.clk(clk) ,	
  	.uart_clk(uart_clk) ,	
  	.tx_data_in(tx_data) ,	              
  	.tx_data_valid(tx_data_valid_state) ,	
  	.is_ready_to_send(is_uart_tx_ready) ,	
  	.tx_pin(tx_pin) 	                    
  );



  function integer nextIndex (input integer idx);
      nextIndex = (idx +1) & (FIFOSIZE-1);
  endfunction

  always@(posedge clk) 
  begin
    if (uart_clk && !uart_clk_tm1) begin
      // pop data from fifo_wr and send it to UartTx   
      fifo_wr_pop <= 0;
      tx_data_valid_state <= 0;
      if (!fifo_wr_empty && is_uart_tx_ready) begin
        tx_data <= fifo_wr_pop_data; 
        tx_data_valid_state <= 1;
        fifo_wr_pop <= 1;
      end  
    end
    uart_clk_tm1 <= uart_clk;
  end


endmodule
