uart_tx¶
Source: Verilog/fpga/tang-nano-20k/sd-fat-test/src/uart_tx.v
Hierarchy: not instantiated by any of the 9 build tops (elaborated by yosys).
Module hierarchy - All modules

Schematic¶
Drawn from the Verilog: no build top uses this module, so it was elaborated from its own file with no defines and default parameters. Sub-modules are boxes (click the picture to open it full size; there every sub-module box links to its page, and every wire shows its Verilog name).
Description¶
UART transmitter (8N1) TX state machine borrowed from the ND-120 SC2661 EPCI model (Verilog/Shared/support/SC2661_UART.v), with the EPCI register interface stripped away. Same states, same bit timing. Last reviewed: 8-JUL-2026 Ronny Hansen
Parameters¶
| Parameter | Default |
|---|---|
DELAY_FRAMES |
2812 |
Ports¶
| Direction | Width | Name | Description |
|---|---|---|---|
| input | 1 |
clk |
|
| input | 1 |
rst_n (active low) |
|
| input | [7:0] |
tx_data |
byte to transmit |
| input | 1 |
tx_valid |
1-cycle pulse: latch tx_data and start (only when tx_busy=0) |
| output | 1 |
tx_busy |
high while a frame is being shifted out |
| output | 1 |
txd |
Verilog source¶
Verilog/fpga/tang-nano-20k/sd-fat-test/src/uart_tx.v on GitHub.
Show the Verilog of uart_tx (86 lines)
/****************************************************************************
** UART transmitter (8N1) **
** **
** TX state machine borrowed from the ND-120 SC2661 EPCI model **
** (Verilog/Shared/support/SC2661_UART.v), with the EPCI register **
** interface stripped away. Same states, same bit timing. **
** **
** Last reviewed: 8-JUL-2026 **
** Ronny Hansen **
*****************************************************************************/
module uart_tx #(
// Clock cycles per bit. 27 MHz / 9600 baud = 2812 (-0.02% error)
parameter DELAY_FRAMES = 2812
) (
input clk,
input rst_n,
input [7:0] tx_data, // byte to transmit
input tx_valid, // 1-cycle pulse: latch tx_data and start (only when tx_busy=0)
output tx_busy, // high while a frame is being shifted out
output reg txd
);
localparam TX_STATE_IDLE = 3'b000;
localparam TX_STATE_START_BIT = 3'b001;
localparam TX_STATE_WRITE = 3'b010;
localparam TX_STATE_STOP_BIT = 3'b011;
reg [ 2:0] txState;
reg [31:0] txCounter;
reg [ 2:0] txBitNumber;
reg [ 7:0] txShift;
assign tx_busy = (txState != TX_STATE_IDLE);
always @(posedge clk) begin
if (!rst_n) begin
txState <= TX_STATE_IDLE;
txd <= 1'b1; // line idles at MARK
txCounter <= 0;
txBitNumber <= 0;
txShift <= 8'b0;
end else begin
case (txState)
TX_STATE_IDLE: begin
txd <= 1'b1;
if (tx_valid) begin
txShift <= tx_data;
txCounter <= 0;
txState <= TX_STATE_START_BIT;
end
end
TX_STATE_START_BIT: begin
txd <= 1'b0;
if ((txCounter + 1) == DELAY_FRAMES) begin
txState <= TX_STATE_WRITE;
txBitNumber <= 0;
txCounter <= 0;
end else txCounter <= txCounter + 1;
end
TX_STATE_WRITE: begin
txd <= txShift[txBitNumber]; // LSB first
if ((txCounter + 1) == DELAY_FRAMES) begin
if (txBitNumber == 3'b111) begin
txState <= TX_STATE_STOP_BIT;
end else begin
txBitNumber <= txBitNumber + 1;
end
txCounter <= 0;
end else txCounter <= txCounter + 1;
end
TX_STATE_STOP_BIT: begin
txd <= 1'b1;
if ((txCounter + 1) == DELAY_FRAMES) begin
txState <= TX_STATE_IDLE;
txCounter <= 0;
end else txCounter <= txCounter + 1;
end
default: txState <= TX_STATE_IDLE;
endcase
end
end
endmodule