`timescale 1ns / 1ps
module uart_tx #(
parameter CLKS_PER_BIT = 868 // 100 MHz / 115200 Baud
)(
input wire clk,
input wire tx_start,
input wire [7:0] tx_data,
output reg tx,
output reg tx_busy
);
localparam IDLE = 2'b00, START_BIT = 2'b01, DATA_BITS = 2'b10, STOP_BIT = 2'b11;
reg [1:0] state = IDLE;
reg [9:0] clk_count = 0;
reg [2:0] bit_idx = 0;
reg [7:0] tx_data_latch = 0;
initial begin
tx = 1'b1;
tx_busy = 1'b0;
end
always @(posedge clk) begin
case (state)
IDLE: begin
tx <= 1'b1;
tx_busy <= 1'b0;
if (tx_start) begin
tx_data_latch <= tx_data;
tx_busy <= 1'b1;
state <= START_BIT;
clk_count <= 0;
end
end
START_BIT: begin
tx <= 1'b0;
if (clk_count < CLKS_PER_BIT-1) begin
clk_count <= clk_count + 1;
end else begin
clk_count <= 0;
bit_idx <= 0;
state <= DATA_BITS;
end
end
DATA_BITS: begin
tx <= tx_data_latch[bit_idx];
if (clk_count < CLKS_PER_BIT-1) begin
clk_count <= clk_count + 1;
end else begin
clk_count <= 0;
if (bit_idx < 7) bit_idx <= bit_idx + 1;
else state <= STOP_BIT;
end
end
STOP_BIT: begin
tx <= 1'b1;
if (clk_count < CLKS_PER_BIT-1) begin
clk_count <= clk_count + 1;
end else begin
state <= IDLE;
end
end
endcase
end
endmodule