Verilog Code for UART Transmitter: Syntax and Example
A UART transmitter in Verilog sends serial data by shifting bits out one at a time using a clock. The
uart_tx module typically includes a state machine to handle start, data, parity, and stop bits, controlled by a baud rate clock.Syntax
The basic UART transmitter module in Verilog includes inputs for clock, reset, data to send, and a start signal. Outputs include the serial transmit line and a busy flag. Internally, it uses a state machine to send start bit, data bits, optional parity, and stop bit.
- clk: System clock input.
- rst: Reset signal to initialize the transmitter.
- tx_start: Signal to start transmission.
- tx_data: 8-bit data to transmit.
- tx_serial: Output serial data line.
- tx_busy: Indicates transmitter is busy sending data.
verilog
module uart_tx(
input wire clk,
input wire rst,
input wire tx_start,
input wire [7:0] tx_data,
output reg tx_serial,
output reg tx_busy
);
// Baud rate generator and state machine signals
// ... (implementation details)
endmoduleExample
This example shows a complete UART transmitter module that sends 8-bit data serially with 1 start bit and 1 stop bit at a fixed baud rate. It demonstrates how to use a baud rate counter and a state machine to control the transmission.
verilog
module uart_tx(
input wire clk, // System clock
input wire rst, // Reset signal
input wire tx_start, // Start transmission
input wire [7:0] tx_data,// Data byte to send
output reg tx_serial, // UART transmit line
output reg tx_busy // Busy flag
);
// Parameters for baud rate generation
parameter CLK_FREQ = 50000000; // 50 MHz clock
parameter BAUD_RATE = 9600;
localparam BAUD_COUNTER_MAX = CLK_FREQ / BAUD_RATE;
reg [15:0] baud_counter = 0;
reg baud_tick = 0;
// State machine states
typedef enum reg [2:0] {
IDLE = 3'b000,
START_BIT = 3'b001,
DATA_BITS = 3'b010,
STOP_BIT = 3'b011
} state_t;
state_t state = IDLE;
reg [3:0] bit_index = 0;
reg [7:0] tx_shift_reg = 8'b0;
// Baud rate generator
always @(posedge clk or posedge rst) begin
if (rst) begin
baud_counter <= 0;
baud_tick <= 0;
end else begin
if (baud_counter == BAUD_COUNTER_MAX - 1) begin
baud_counter <= 0;
baud_tick <= 1;
end else begin
baud_counter <= baud_counter + 1;
baud_tick <= 0;
end
end
end
// UART transmitter state machine
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= IDLE;
tx_serial <= 1'b1; // Idle line is high
tx_busy <= 0;
bit_index <= 0;
tx_shift_reg <= 8'b0;
end else if (baud_tick) begin
case (state)
IDLE: begin
tx_serial <= 1'b1; // Line idle high
tx_busy <= 0;
if (tx_start) begin
tx_busy <= 1;
tx_shift_reg <= tx_data;
state <= START_BIT;
end
end
START_BIT: begin
tx_serial <= 1'b0; // Start bit is low
state <= DATA_BITS;
bit_index <= 0;
end
DATA_BITS: begin
tx_serial <= tx_shift_reg[bit_index];
if (bit_index == 7) begin
state <= STOP_BIT;
end else begin
bit_index <= bit_index + 1;
end
end
STOP_BIT: begin
tx_serial <= 1'b1; // Stop bit is high
state <= IDLE;
tx_busy <= 0;
end
endcase
end
end
endmoduleOutput
No direct console output; tx_serial line outputs UART serial data stream at 9600 baud.
Common Pitfalls
Common mistakes when writing a UART transmitter include:
- Not generating the correct baud rate clock, causing timing errors.
- Forgetting to set the transmit line high when idle, which can cause framing errors.
- Not handling the
tx_busyflag properly, leading to data overwrites. - Incorrect bit order when shifting data out (LSB first is standard).
Always test with a known baud rate and verify the output with a logic analyzer or serial terminal.
verilog
/* Wrong: tx_serial line left low when idle */ // tx_serial <= 0; // Incorrect idle state /* Right: tx_serial line high when idle */ // tx_serial <= 1; // Correct idle state
Quick Reference
- Start bit: Always 0 (low) to signal start of transmission.
- Data bits: Usually 8 bits, sent LSB first.
- Stop bit: Always 1 (high) to signal end of transmission.
- Baud rate: Controls timing; must match receiver.
- Idle line: Always high when not transmitting.
Key Takeaways
Generate a precise baud rate clock to time UART bits correctly.
Send a low start bit, then data bits LSB first, and a high stop bit.
Keep the transmit line high when idle to avoid framing errors.
Use a busy flag to prevent starting a new transmission before the current one finishes.
Test your UART transmitter with a serial terminal or logic analyzer.