module uart_tx #(
	parameter       CLK_FREQ = 27_000_000,
	parameter       BAUD_RATE = 115200
)(
    input wire      clk,
    input wire      rst_p,
    input wire[7:0] data,
    input wire      tx_data_valid,
    
    output wire     tx,
    output reg      tx_data_ready
);

    localparam CYCLE = CLK_FREQ / BAUD_RATE; 

    localparam IDLE  = 2'd0;
    localparam START = 2'd1;
    localparam DATA  = 2'd2;
    localparam STOP  = 2'd3;

    reg [1:0]   state = IDLE;
    reg [1:0]   next_state;
    reg [15:0]  cycle_cnt;      //baud counter       
    reg         tx_reg;
    reg [2:0] bit_cnt; 
    reg [7:0] tx_data_latch = 0; 


    assign tx = tx_reg;

    always@(posedge clk or posedge rst_p)begin // Avance d'etat 
        if(rst_p == 1'b1)
            state <= IDLE;
        else
            state <= next_state;
    end

    always@(*) begin
        case(state)
            IDLE:
                if(tx_data_valid == 1'b1)
                    next_state = START;
                else
                    next_state = IDLE;

            START:
                if(cycle_cnt == CYCLE - 1)
                    next_state = DATA;
                else
                    next_state = START;

            DATA:
                if(cycle_cnt == CYCLE - 1  && bit_cnt == 3'd7)
                    next_state = STOP;
                else
                    next_state = DATA;

            STOP:
                if(cycle_cnt == CYCLE - 1)
                    next_state = IDLE;
                else
                    next_state = STOP;
            default:
                next_state = IDLE;
        endcase
    end

    always@(posedge clk or posedge rst_p)begin  // tx_data_ready block
        if(rst_p == 1'b1)
            tx_data_ready <= 1'b0;  // Reset
        else if(state == IDLE && tx_data_valid == 1'b1)
            tx_data_ready <= 1'b0;  // Pas prêt tant que les données sont valides
        else if(state == IDLE)
            tx_data_ready <= 1'b1;
        else if(state == STOP && cycle_cnt == CYCLE - 1)
            tx_data_ready <= 1'b1;  // Prêt une fois le bit STOP envoyé
        else
            tx_data_ready <= tx_data_ready;  // Reste inchangé dans d'autres cas
    end



    always@(posedge clk or posedge rst_p) begin // tx_data_latch block
        if(rst_p == 1'b1) begin
            tx_data_latch <= 8'd0;
        end else if(state == IDLE && tx_data_valid == 1'b1) begin
            tx_data_latch <= data;  // Charger les données de `data` dans `tx_data_latch`
        end
    end


    always@(posedge clk or posedge rst_p)begin  // DATA bit_cnt block
        if(rst_p == 1'b1)begin
                bit_cnt <= 3'd0;

        end else if(state == DATA)
            if(cycle_cnt == CYCLE - 1)
                bit_cnt <= bit_cnt + 3'd1;
            else
                bit_cnt <= bit_cnt;
        else
            bit_cnt <= 3'd0;
    end


    always@(posedge clk or posedge rst_p)begin  // Cycle counter
        if(rst_p == 1'b1)
            cycle_cnt <= 16'd0;

        else if((state == DATA && cycle_cnt == CYCLE - 1) || next_state != state)
            cycle_cnt <= 16'd0;
        else
            cycle_cnt <= cycle_cnt + 16'd1;	
    end

    always@(posedge clk or posedge rst_p)begin  // tx state managment
        if(rst_p == 1'b1)
            tx_reg <= 1'b1;
        else
            case(state)
                IDLE,STOP:
                    tx_reg <= 1'b1; 
                START:
                    tx_reg <= 1'b0; 
                DATA:
                    tx_reg <= tx_data_latch[bit_cnt]; // SENDING BYTE HERE
                default:
                    tx_reg <= 1'b1; 
            endcase
    end
endmodule
