Verilog Code for UART Receiver: Syntax and Example
A UART receiver in Verilog reads serial data bits and converts them into parallel data. The
uart_rx module typically uses a baud rate clock, start bit detection, data bit sampling, and stop bit verification to receive data correctly.Syntax
The basic UART receiver module includes inputs for the serial data line and clock, and outputs the received byte and a data valid signal. It uses a state machine to detect the start bit, sample data bits at the baud rate, and check the stop bit.
- clk: System clock input.
- rx: Serial data input line.
- data_out: 8-bit parallel output data.
- data_valid: Signal indicating data reception complete.
verilog
module uart_rx(
input wire clk,
input wire rx,
output reg [7:0] data_out,
output reg data_valid
);
// Parameters for baud rate generation and sampling
parameter CLKS_PER_BIT = 434; // Example for 115200 baud with 50MHz clock
// State machine states
localparam IDLE = 0, START = 1, DATA = 2, STOP = 3;
reg [9:0] clk_count = 0;
reg [3:0] bit_index = 0;
reg [1:0] state = IDLE;
reg [7:0] rx_shift_reg = 0;
always @(posedge clk) begin
case(state)
IDLE: begin
data_valid <= 0;
clk_count <= 0;
bit_index <= 0;
if (rx == 0) // Start bit detected
state <= START;
end
START: begin
if (clk_count == (CLKS_PER_BIT-1)/2) begin // Mid bit sample
if (rx == 0) begin
clk_count <= 0;
state <= DATA;
end else
state <= IDLE; // False start bit
end else
clk_count <= clk_count + 1;
end
DATA: begin
if (clk_count < CLKS_PER_BIT - 1) begin
clk_count <= clk_count + 1;
end else begin
clk_count <= 0;
rx_shift_reg[bit_index] <= rx;
if (bit_index < 7) begin
bit_index <= bit_index + 1;
end else begin
bit_index <= 0;
state <= STOP;
end
end
end
STOP: begin
if (clk_count < CLKS_PER_BIT - 1) begin
clk_count <= clk_count + 1;
end else begin
if (rx == 1) begin // Stop bit should be high
data_out <= rx_shift_reg;
data_valid <= 1;
end
state <= IDLE;
clk_count <= 0;
end
end
endcase
end
endmoduleExample
This example shows a complete UART receiver module that receives 8-bit data at 115200 baud with a 50 MHz clock. It outputs the received byte and a data valid pulse when a byte is received.
verilog
module uart_rx_example(
input wire clk, // 50 MHz clock
input wire rx, // UART serial input
output reg [7:0] data_out,
output reg data_valid
);
parameter CLKS_PER_BIT = 434; // 50MHz / 115200 baud
localparam IDLE = 0, START = 1, DATA = 2, STOP = 3;
reg [9:0] clk_count = 0;
reg [3:0] bit_index = 0;
reg [1:0] state = IDLE;
reg [7:0] rx_shift_reg = 0;
always @(posedge clk) begin
case(state)
IDLE: begin
data_valid <= 0;
clk_count <= 0;
bit_index <= 0;
if (rx == 0) // Detect start bit
state <= START;
end
START: begin
if (clk_count == (CLKS_PER_BIT-1)/2) begin
if (rx == 0) begin
clk_count <= 0;
state <= DATA;
end else
state <= IDLE;
end else
clk_count <= clk_count + 1;
end
DATA: begin
if (clk_count < CLKS_PER_BIT - 1) begin
clk_count <= clk_count + 1;
end else begin
clk_count <= 0;
rx_shift_reg[bit_index] <= rx;
if (bit_index < 7) begin
bit_index <= bit_index + 1;
end else begin
bit_index <= 0;
state <= STOP;
end
end
end
STOP: begin
if (clk_count < CLKS_PER_BIT - 1) begin
clk_count <= clk_count + 1;
end else begin
if (rx == 1) begin
data_out <= rx_shift_reg;
data_valid <= 1;
end
state <= IDLE;
clk_count <= 0;
end
end
endcase
end
endmoduleCommon Pitfalls
Common mistakes when writing a UART receiver in Verilog include:
- Incorrect baud rate clock division causing wrong sampling timing.
- Not sampling data bits in the middle of the bit period, leading to errors.
- Ignoring the stop bit check, which can cause framing errors.
- Not resetting state machine variables properly after each byte.
Always verify the clock frequency and baud rate match your hardware setup.
verilog
/* Wrong: Sampling data bits at start of bit period */ always @(posedge clk) begin if (clk_count == 0) begin rx_shift_reg[bit_index] <= rx; // Sampling at start, may cause errors end // ... rest of code end /* Right: Sampling data bits at middle of bit period */ always @(posedge clk) begin if (clk_count == (CLKS_PER_BIT-1)/2) begin rx_shift_reg[bit_index] <= rx; // Sample at middle for stability end // ... rest of code end
Quick Reference
- Start bit: Detect low (0) on RX line to begin reception.
- Data bits: Sample 8 bits at baud rate intervals, mid-bit.
- Stop bit: Check for high (1) to confirm byte end.
- Baud rate clock: Generate clock enable to sample bits correctly.
- State machine: Use states IDLE, START, DATA, STOP for control flow.
Key Takeaways
Sample UART data bits at the middle of each bit period for reliable reception.
Use a state machine with states IDLE, START, DATA, and STOP to manage UART reception.
Verify your clock frequency and baud rate to calculate correct clock cycles per bit.
Check the stop bit to detect framing errors and confirm valid data.
Reset counters and state variables properly after each received byte.