Research-Stack/4-Infrastructure/hardware/uart_tx.v

92 lines
2.9 KiB
Verilog

// UART Transmitter for Tang Nano 9K
// 115200 baud, 8N1 configuration
// Clock: 27 MHz
// Baud divider: 27MHz / 115200 = 234.375 ≈ 234
`timescale 1ns / 1ps
module uart_tx (
input clk,
input rst_n,
input tx_start,
input [7:0] tx_data,
output uart_tx,
output tx_busy
);
localparam BAUD_DIV = 16'd234; // 27MHz / 115200
localparam IDLE = 2'd0;
localparam START = 2'd1;
localparam DATA = 2'd2;
localparam STOP = 2'd3;
reg [15:0] baud_counter;
reg [2:0] bit_counter;
reg [1:0] state;
reg [7:0] tx_shift;
reg tx_busy_r;
reg uart_tx_r;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
baud_counter <= 16'd0;
bit_counter <= 3'd0;
tx_shift <= 8'd0;
tx_busy_r <= 1'b0;
uart_tx_r <= 1'b1;
end else begin
case (state)
IDLE: begin
if (tx_start) begin
state <= START;
tx_shift <= tx_data;
tx_busy_r <= 1'b1;
baud_counter <= 16'd0;
uart_tx_r <= 1'b0; // Start bit
end else begin
tx_busy_r <= 1'b0;
uart_tx_r <= 1'b1;
end
end
START: begin
if (baud_counter == BAUD_DIV) begin
state <= DATA;
baud_counter <= 16'd0;
bit_counter <= 3'd0;
uart_tx_r <= tx_shift[0]; // LSB first
end else begin
baud_counter <= baud_counter + 1'b1;
end
end
DATA: begin
if (baud_counter == BAUD_DIV) begin
if (bit_counter == 3'd7) begin
state <= STOP;
uart_tx_r <= 1'b1; // Stop bit
end else begin
bit_counter <= bit_counter + 1'b1;
tx_shift <= tx_shift >> 1;
uart_tx_r <= tx_shift[0];
end
baud_counter <= 16'd0;
end else begin
baud_counter <= baud_counter + 1'b1;
end
end
STOP: begin
if (baud_counter == BAUD_DIV) begin
state <= IDLE;
tx_busy_r <= 1'b0;
end else begin
baud_counter <= baud_counter + 1'b1;
end
end
endcase
end
end
assign uart_tx = uart_tx_r;
assign tx_busy = tx_busy_r;
endmodule