Baud Rate Generation

How do we derive 9600 bps from a 50 MHz system clock?

The Concept of Oversampling

A standard UART Receiver typically samples the incoming signal 16 times faster than the baud rate. This allows it to:

  1. Detect the falling edge of the Start Bit accurately.
  2. Sample the center of the bit period to avoid noise at the edges.

Calculating the Divisor

Formula

Divisor = System_Clock_Freq / (Target_Baud * 16)

Example: System Clock = 50 MHz, Target Baud = 115200.

  • Target Frequency = 115200 * 16 = 1,843,200 Hz
  • Divisor = 50,000,000 / 1,843,200 ≈ 27.12

Since we can only count integers in RTL, we use 27. This introduces a small error. If the error is > 2-3%, communication fails.

Verilog Implementation

Here is a simple Baud Tick Generator in SystemVerilog:

Baud generator

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