Skip to content
VLSI Mentor

UART · Module 4

Fractional Baud Generation

An accumulator keeps the remainder an integer divider discards, lengthening an occasional interval so the average converges on the ideal. That improves long-run accuracy by orders of magnitude while making individual intervals unequal — and a UART receiver never measures the average.

Chapter 4.3 discarded the fractional part of the ideal divisor and showed that at ordinary rates the cost is negligible — about 0.0006 UI over an 8N1 frame at 100 MHz and 115,200.

But it was discarded permanently. Every interval is the same integer length, so the residual error is systematic: the same sign, the same magnitude, on every interval, forever. It never averages out, because there is nothing to average against.

This chapter asks what happens if the remainder is kept. The mechanism is an accumulator, and the result is a genuine trade rather than a free improvement: the average gets dramatically better and the individual intervals get worse. Understanding which of those a link actually cares about is the engineering content.

1. The Problem With a Permanently Discarded Remainder

Recall the arithmetic from Chapter 4.2:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
100,000,000 / 115,200 = 15,625 / 18 = 868.0555...

An integer divider chooses 868 and throws 0.0556 away. Every interval is therefore short by 0.0556 clock cycles — about 0.556 ns — and since every interval is short by the same amount in the same direction, the shortfall accumulates:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ε = +0.006400%    (Chapter 4.3)

Over nine intervals that is +0.000576 UI, which Chapter 4.3 correctly called negligible. The interesting observation is why it is negligible: not because the mechanism is good, but because the divisor is large. At 868 cycles per interval, half a cycle of rounding is a small fraction. The same mechanism at a divisor of 20 leaves an error 40 times larger.

So the question is not whether integer division is acceptable — sometimes it obviously is — but whether a design can do better when it needs to, and what that costs.

2. Keep the Remainder

The idea is arithmetic before it is hardware. If the ideal divisor is 868.0556, then over 18 intervals the ideal total is:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
18 x 868.0556 = 15,625 clock cycles

An integer divider produces 18 x 868 = 15,624 — one cycle short over 18 intervals. So emit 17 intervals of 868 cycles and one of 869, and the total is exactly right. The average interval is exactly the ideal; only the individual intervals differ.

Generalising, that is the whole mechanism:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ideal  =  N_int  +  frac          with 0 <= frac < 1

each interval is N_int cycles, except that a fraction `frac` of
intervals are lengthened to N_int + 1

The hardware that decides which intervals are lengthened is an accumulator. Choose a width W, and represent the fraction as an integer increment:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
INC = round(frac x 2^W)

every interval:   acc = acc + INC
                  if acc overflows 2^W:
                      acc = acc − 2^W
                      this interval is N_int + 1 cycles
                  else:
                      this interval is N_int cycles

The accumulator is a fixed-point remainder. Each interval it collects INC, and when the collected remainder reaches a whole cycle it is spent by lengthening one interval.

3. The Sequence, Worked

At W = 8, the fraction 0.0556 becomes:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
INC = round(0.055556 x 256) = 14

Running the accumulator from zero produces a completely deterministic sequence. Intervals 14 through 23:

One long interval every 256/14 ≈ 18.3 intervals

10 cycles
Ten consecutive UART bit intervals numbered fourteen through twenty-three are shown. For each interval two values are given: the number of fabric clock cycles that interval lasted, and the accumulator value after that interval. Intervals fourteen through seventeen last 868 cycles with the accumulator rising through 210, 224, 238 and 252. At interval eighteen the accumulator would exceed 256, so that interval is lengthened to 869 cycles and the accumulator wraps to 10. Intervals nineteen through twenty-three return to 868 cycles with the accumulator rising again through 24, 38, 52, 66 and 80.accumulatingaccumulatingspentspentaccumulating againaccumulating againacc = 252, one more step to goacc = 252, one more step togooverflow: this interval is 869overflow: this interval is869acc wrapped to 10, back to 868acc wrapped to 10, back to868cycles868868868868869868868868868868acc210224238252102438526680t0t1t2t3t4t5t6t7t8t9
Figure 1 — ten consecutive bit intervals under an 8-bit fractional accumulator with INC = 14. Each column is one UART bit interval, not a fabric-clock cycle; the rows show how many fabric clocks that interval actually lasted and the accumulator value after it. The accumulator crosses 256 at interval 18, which is spent by making that one interval 869 cycles instead of 868.

One interval in every 256 / 14 ≈ 18.3 is lengthened. For an 8N1 frame of ten intervals, that means most frames contain no correction at all and roughly every other frame contains one — which is worth holding onto when §5 considers what a receiver experiences.

What it buys

The effective divisor becomes:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
N_eff = 868 + 14/256 = 868.054688

f_actual = 100,000,000 / 868.054688 = 115,200.1152 baud
ε        = +0.000100%  =  +1.00 ppm

against the integer divider's +0.006400% (+64.0 ppm):

SchemeEffective divisorActual rateεppm
Integer, N = 868868115,207.3733+0.006400%+64.0
Fractional, W = 8868.054688115,200.1152+0.000100%+1.00
Fractional, W = 16868.055557115,200.0≈ 0−0.002

A 64× improvement for eight bits of accumulator, and essentially exact representation at sixteen. The residual comes only from quantising the fraction itself into W bits, so it shrinks geometrically with width — which is why fractional generators are cheap to make accurate once the mechanism exists at all.

4. What It Costs: Unequal Intervals

The improvement is in the average. Individual intervals are now worse than the integer divider's, and precisely so:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
T_bit (ideal)      = 8680.556 ns
interval of 868    = 8680.000 ns    deviation −0.556 ns   = −0.0064% of T_bit
interval of 869    = 8690.000 ns    deviation +9.444 ns   = +0.1088% of T_bit

peak-to-peak variation = one clock cycle = 10.000 ns = 0.1152% of T_bit

So the integer divider produces intervals that are all 0.0064% short, while the fractional generator produces intervals that are mostly 0.0064% short and occasionally 0.1088% long. The worst single interval is seventeen times further from nominal than anything the integer divider produced.

That is the trade, and it is worth stating as a principle: fractional generation converts a small systematic error into a larger bounded one that averages away.

Now the judgement the chapter exists for, and the answer is not "the smaller number".

A receiver re-acquires its timing origin every frame (Chapter 2.3). It never integrates timing across more than one frame, so a rate error only matters through its accumulation over N_frame − 1 intervals — the result Chapter 2.5 evaluates.

That has a sharp consequence. The long-run average accuracy that fractional generation improves is a quantity no UART receiver ever measures. What the receiver experiences is the intervals of one frame, and over an 8N1 frame from §3's generator most frames contain no correction at all.

So compare what the receiver actually sees:

Over one 8N1 frame (9 intervals)Peak displacement within the frame
Integer N = 8680.000576 UI
Fractional W = 8, frame with no long interval0.000576 UI
Fractional W = 8, worst case — long interval first0.001088 UI

(Peak displacement is the largest cumulative deviation from the nominal grid at any point in the frame, which is where the long interval falls earliest.)

Both are far below the half-bit budget, so at this pairing neither scheme is the constraint and the choice does not matter. But notice the direction: within a single frame the fractional generator's worst case is 1.89× larger than the integer divider's, because the one long interval displaces the grid by more than the systematic error accumulates over nine.

6. The Hardware, in Outline

The structure follows directly from §2, and the point of showing it is that it is barely larger than the integer divider.

A fractional baud generator. The integer part consists of a counter that increments each clock and a comparator against a terminal value, as in the integer divider. Added to it is an accumulator register which adds a fixed increment once per bit interval. When the accumulator overflows its width, the carry extends the terminal value by one for that single interval, making it one clock cycle longer, and the accumulator retains the remainder. The enable output is produced by the same terminal comparison as before.counter0 .. terminalterminal = N_int − 1+ carryextended by one, sometimesbaud_tickone cycle, an enableaccumulator+ INC per intervaloverflowspend one cyclecomparematch+ INCwraps+1 this interval12
Figure 2 — the fractional generator alongside the integer one. The counter and terminal comparison are unchanged; what is added is an accumulator whose overflow extends the terminal value by one for a single interval. The added hardware is one register, one adder, and a carry — which is why the accuracy is inexpensive once the mechanism exists.
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Conceptual SystemVerilog — the accumulator mechanism only.
//
// Shows how INC is derived and how the carry extends one interval. The
// PRODUCTION generator is Chapter 8.3: reset and start-up behaviour,
// runtime reconfiguration, whether RX and TX share an accumulator, and
// how the residual error is reported all belong there. This block is
// written to make Section 2's arithmetic concrete, not to be instantiated.
module uart_frac_accum #(
    parameter int unsigned CLK_HZ  = 100_000_000,
    parameter int unsigned BAUD_HZ = 115_200,
    parameter int unsigned ACC_W   = 8          // fraction resolution
) (
    input  logic clk,
    input  logic rst_n,
    input  logic interval_done_i,   // one pulse at the end of each bit interval
    output logic extend_o           // make the NEXT interval one cycle longer
);
    // Integer part, floor — the fraction is handled separately, so floor
    // is correct here rather than nearest (contrast Chapter 4.3 §1).
    localparam int unsigned N_INT = CLK_HZ / BAUD_HZ;

    // INC = round(frac x 2^ACC_W), computed with integer arithmetic:
    //   frac x 2^W = ((CLK_HZ % BAUD_HZ) x 2^W) / BAUD_HZ
    // The +BAUD_HZ/2 before dividing performs round-half-up.
    localparam int unsigned REMAINDER = CLK_HZ % BAUD_HZ;
    localparam int unsigned INC =
        (((REMAINDER << ACC_W) + (BAUD_HZ / 2)) / BAUD_HZ);

    // One bit wider than the fraction, so the carry out is bit ACC_W.
    logic [ACC_W:0] acc_q;

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            acc_q    <= '0;
            extend_o <= 1'b0;
        end else if (interval_done_i) begin
            // Add INC into the low ACC_W bits; bit ACC_W is the carry.
            // Assigning the sum back with the carry bit cleared is the
            // "subtract 2^ACC_W" of Section 2.
            acc_q    <= {1'b0, acc_q[ACC_W-1:0]} + ACC_W'(INC);
            extend_o <= (({1'b0, acc_q[ACC_W-1:0]} + ACC_W'(INC)) >> ACC_W) != 0;
        end else begin
            extend_o <= extend_o;   // hold across the interval
        end
    end
endmodule

INC is computed from the remainder, not from a float. CLK_HZ % BAUD_HZ is the numerator of the fraction and BAUD_HZ its denominator, so (REMAINDER << ACC_W) / BAUD_HZ is the fraction scaled by 2^ACC_W in pure integer arithmetic. Elaboration-time arithmetic is integer arithmetic; introducing a real here would be both unnecessary and less portable.

The accumulator is ACC_W + 1 bits wide so the overflow appears as a bit rather than having to be inferred from a comparison. The top bit is the carry, and clearing it when writing back performs the subtraction.

Floor is correct for N_INT here, which contrasts with Chapter 4.3 §1 where nearest was preferred. The reason is that the fraction is no longer being discarded — it is being handled by the accumulator — so rounding the integer part up would double-count it.

What is deliberately missing: the counter and terminal comparison that consume extend_o, the interaction with reset mid-frame, whether the accumulator is reset between frames or free-runs, and what happens when the configuration changes. Every one of those is a real decision and every one belongs to Chapter 8.3.

7. Verification and Measurement

Fractional generation changes what a checker can assert, and getting that wrong produces false failures.

A fixed-interval check is now wrong. The monitor from Chapter 4.3 §6 compares each observed interval against a single expected value. Against a fractional generator it fails on every long interval — correctly detecting behaviour that is correct. The check must become a membership test: every observed interval is N_int or N_int + 1, and nothing else.

The accuracy claim is a long-run property and must be checked as one. Over M intervals the total should be within one cycle of M x ideal:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
| sum(observed cycles over M intervals)  −  M x N_ideal |  <=  1

That is the assertion that actually captures what fractional generation promises, and it is the one a fixed-interval check cannot express. It also catches a real defect class: an accumulator that loses its remainder — reset between intervals, or wrongly cleared on a configuration write — passes the membership test on every interval and fails this one, because its average silently collapses back to the integer divisor.

Check the pattern's period, not just its values. With INC = 14 and W = 8 the long interval appears every 256/14 ≈ 18.3 intervals. An accumulator that is one bit too narrow, or whose INC was computed with the wrong rounding, produces a different period — which is visible in a long capture and invisible in a short one.

On hardware, the measurement technique from Chapter 4.3 §5 becomes essential rather than merely convenient. Measuring one interval now tells you almost nothing, because you may have measured a long one. Measuring across many intervals averages the pattern out and recovers the effective rate — which is exactly the quantity fractional generation was designed to make accurate.

8. Understanding Check

9. Summary

An integer divider discards the fractional part permanently, so its error is systematic — the same sign and magnitude on every interval, never averaging out. Whether that matters depends on the divisor: at 868 cycles per interval half a cycle of rounding is negligible; at 20 it is not.

A fractional accumulator keeps the remainder. Represent the fraction as INC = round(frac x 2^W), add it once per interval, and when it overflows, spend the accumulated cycle by making that one interval N_int + 1 long. At 100 MHz and 115,200 with W = 8, INC = 14 and one interval in every 256/14 ≈ 18.3 is lengthened.

It buys a 64× improvement in average rate error — +64.0 ppm to +1.00 ppm — for one register, one adder and a carry, improving geometrically with width: W = 16 is accurate to −0.002 ppm.

It costs interval equality. Intervals are mostly 0.0064% short and occasionally 0.1088% long, with a peak-to-peak variation of exactly one clock cycle. That is deterministic interval quantisation, not jitter — bounded, repeatable, and budgeted at its worst case rather than statistically.

The judgement is subtler than "smaller error is better". A UART receiver re-acquires every frame and never measures the long-run average, so the quantity fractional generation improves is one this protocol does not use. Over a single 8N1 frame the fractional generator's worst case is slightly larger than the integer divider's. It earns its place when the divisor is small, or when one generator must serve many rates — and not when it removes a term that was already a thousandth of the budget.

10. What Comes Next

Four chapters have produced terms: framing overhead, the divider's residual error, and the interval quantisation just described. Module 2 produced two more — the receiver's origin uncertainty and the far end's oscillator error — and Chapter 2.5 named the half-bit they are all spent from without assembling them.

Chapter 4.5 assembles the budget. It derives a tolerance from an explicitly stated model, shows exactly which assumptions produce the figure that folklore quotes as "about 5%", and then adds the real terms one at a time to show what the usable budget actually is for a stated design — and why no single number can be correct for all of them.

Browse the full path on the UART tutorials index. For accumulator-based rate generation applied to a different problem, see Clock Dividers and Timers.

Continue learning

Where this fits

Part of the UART curriculum.