`timescale 1ns/1ps // 8-N-1 UART transmitter. module uart_tx #( parameter integer CLK_HZ = 25000000, parameter integer BAUD = 115200 )( input wire clk, input wire reset_n, input wire start, input wire [7:0] data, output reg tx, output reg busy, output reg done ); localparam integer CLKS_PER_BIT = CLK_HZ / BAUD; localparam [1:0] U_IDLE = 2'd0; localparam [1:0] U_START = 2'd1; localparam [1:0] U_DATA = 2'd2; localparam [1:0] U_STOP = 2'd3; reg [1:0] state; reg [15:0] clk_count; reg [2:0] bit_index; reg [7:0] data_latched; always @(posedge clk or negedge reset_n) begin if (!reset_n) begin state <= U_IDLE; clk_count <= 16'd0; bit_index <= 3'd0; data_latched <= 8'd0; tx <= 1'b1; busy <= 1'b0; done <= 1'b0; end else begin done <= 1'b0; case (state) U_IDLE: begin tx <= 1'b1; busy <= 1'b0; clk_count <= 16'd0; bit_index <= 3'd0; if (start) begin data_latched <= data; busy <= 1'b1; tx <= 1'b0; state <= U_START; end end U_START: begin busy <= 1'b1; tx <= 1'b0; if (clk_count == CLKS_PER_BIT - 1) begin clk_count <= 16'd0; bit_index <= 3'd0; tx <= data_latched[0]; state <= U_DATA; end else begin clk_count <= clk_count + 1'b1; end end U_DATA: begin busy <= 1'b1; tx <= data_latched[bit_index]; if (clk_count == CLKS_PER_BIT - 1) begin clk_count <= 16'd0; if (bit_index == 3'd7) begin tx <= 1'b1; state <= U_STOP; end else begin bit_index <= bit_index + 1'b1; end end else begin clk_count <= clk_count + 1'b1; end end U_STOP: begin busy <= 1'b1; tx <= 1'b1; if (clk_count == CLKS_PER_BIT - 1) begin clk_count <= 16'd0; busy <= 1'b0; done <= 1'b1; state <= U_IDLE; end else begin clk_count <= clk_count + 1'b1; end end default: state <= U_IDLE; endcase end end endmodule