A standard UART Receiver typically samples the incoming signal 16 times faster than the baud rate. This allows it to:
- Detect the falling edge of the Start Bit accurately.
- Sample the center of the bit period to avoid noise at the edges.
How do we derive 9600 bps from a 50 MHz system clock?
A standard UART Receiver typically samples the incoming signal 16 times faster than the baud rate. This allows it to:
Divisor = System_Clock_Freq / (Target_Baud * 16)
Example: System Clock = 50 MHz, Target Baud = 115200.
Since we can only count integers in RTL, we use 27. This introduces a small error. If the error is > 2-3%, communication fails.
Here is a simple Baud Tick Generator in SystemVerilog:
module baud_gen #(
parameter CLK_FREQ = 50000000,
parameter BAUD_RATE = 115200,
parameter OVERSAMPLE = 16
)(
input wire clk,
input wire rst_n,
output reg tick // Pulses 16x per bit
);
// Calculate limit at compile time
localparam LIMIT = CLK_FREQ / (BAUD_RATE * OVERSAMPLE);
reg [$clog2(LIMIT)-1:0] counter;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
counter <= 0;
tick <= 0;
end else begin
if (counter >= LIMIT - 1) begin
counter <= 0;
tick <= 1; // Trigger the UART Core
end else begin
counter <= counter + 1;
tick <= 0;
end
end
end
endmodule