`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nope
// Engineer: Jose
// 
// Create Date: 03/03/2026 03:02:49 AM
// Design Name: UART TX Module
// Module Name: uart_tx
// Project Name: riscv-ac
// Target Devices: Artix 7
// Tool Versions: 2025.2
// Description: Allows UART transmission
// 
// Dependencies: 
// 
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_tx (
    input  wire clk,
    input  wire [7:0] data_in,
    input  wire tx_en,
    output reg  tx = 1
);

    // 12e6 / 115200 = 104 ciclos
    localparam CLKS_PER_BIT =  104; // 104;
    
    localparam S_IDLE  = 2'b00;
    localparam S_START = 2'b01;
    localparam S_DATA  = 2'b10;
    localparam S_STOP  = 2'b11;

    reg [1:0] state = S_IDLE;
    reg [15:0] clk_count = 0;
    reg [2:0] bit_index = 0;
    reg [7:0] tx_data = 0;

    always @(posedge clk) begin
        case (state)
            S_IDLE: begin
                tx <= 1;
                clk_count <= 0;
                bit_index <= 0;
                if (tx_en) begin
                    tx_data <= data_in;
                    state <= S_START;
                end
            end
            
            S_START: begin
                tx <= 0;
                if (clk_count < CLKS_PER_BIT - 1) begin
                    clk_count <= clk_count + 1;
                end else begin
                    clk_count <= 0;
                    state <= S_DATA;
                end
            end
            
            S_DATA: begin
                tx <= tx_data[bit_index];
                if (clk_count < CLKS_PER_BIT - 1) begin
                    clk_count <= clk_count + 1;
                end else begin
                    clk_count <= 0;
                    if (bit_index == 7) begin
                        state <= S_STOP;
                    end else begin
                        bit_index <= bit_index + 1;
                    end
                end
            end
            
            S_STOP: begin
                tx <= 1;
                if (clk_count < CLKS_PER_BIT - 1) begin
                    clk_count <= clk_count + 1;
                end else begin
                    state <= S_IDLE;
                end
            end
        endcase
    end
endmodule