Skip to content
VLSI Mentor

UART · Module 9

False Starts, Noise and Malformed Frames

A glitch, a hot-plug or a reset released onto live traffic can put a receiver into a frame nobody transmitted. Idle detection suppresses it — at a cost worth pricing before adopting.

Every failure so far involved a frame that was really sent. This chapter covers the opposite: a frame the receiver assembled that nobody transmitted.

Chapter 5.2 built start qualification and established its exact guarantee — it rejects disturbances shorter than the validation delay, and nothing more. Chapter 6.2 §7 then demonstrated the case qualification cannot help with: a receiver released from reset onto a live line produced 0xFA from a frame carrying 0xA6, with clean status.

Both chapters stated the limit and deferred the remedy here. So this chapter does three things: it maps the space of start-side failures precisely, it builds the idle detection that closes the mid-frame case, and it prices that remedy honestly — because it is not free and it is not always wanted.

1. Four Start-Side Failures, by What Rejects Them

They are usually lumped together as "noise", and they are rejected — or not — by completely different mechanisms.

FailureShape on the wireRejected byCost when it gets through
Narrow glitchlow for less than the validation delayqualification5.2none; it never becomes a frame
Wide disturbancelow past the validation pointnothinga fabricated frame, timed from the glitch
Mid-sample noisetransient at one sampling instantmajority voting, if fitted — 5.4one wrong bit, possibly caught by parity
Mid-frame attachthe line is mid-frame when we start lookingidle detection — §4a fabricated frame from someone else's data

Only the first is handled by the receiver as built in Module 6. The second and fourth produce complete, well-formed-looking frames that the receiver has no basis to reject, and the third is Chapter 5.4's trade.

2. The Glitch That Is Rejected

The case qualification handles, for completeness and as the positive control every other case is measured against.

A disturbance shorter than M/2 oversample ticks: the edge detector produces a candidate, the qualifier starts counting, and at the validation point the line has returned to mark. The candidate is abandoned, no frame begins, and nothing is reported — there is no error, because nothing was lost.

That silence is correct and worth defending. A receiver that reported every rejected candidate would produce a stream of "errors" on any electrically busy board, and the events it reported would carry no information: a rejected candidate is the mechanism working.

Where a counter is genuinely useful is bring-up. A rejected-candidate count that is zero on a healthy board and climbing on a marginal one is a sensitive early indicator — and it belongs as a debug output rather than an error flag, for the reason above.

3. The Glitch That Is Not

Widen the same disturbance past the validation point and everything changes:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
candidate at t=0                     edge detector fires
line still at space at M/2           qualification PASSES
-> start accepted, timing origin set to a disturbance
-> eight data samples taken at 1.5, 2.5, ... UI from nothing in particular
-> a stop sample taken at 9.5 UI
-> a byte is delivered

The receiver has no basis to reject this. Every check it performs passes or fails on its own terms: the start qualified, the data intervals were sampled at their scheduled positions, and the stop sample lands wherever the real traffic happens to be. If it happens to find mark there, the frame is delivered with completely clean status.

The observable consequences:

A framing error is likely but not guaranteed. The stop sample lands at an arbitrary point relative to real traffic, so it is mark roughly half the time on a busy line and always mark on an idle one.

The payload is meaningless, and there is no flag for that. Chapter 9.2 applies: parity over a fabricated payload is satisfied about half the time.

The receiver's timing origin is now wrong for subsequent frames too, until it returns to idle and re-anchors on a real start edge — which is Chapter 9.6's subject.

Narrow glitch rejected, wider glitch accepted

16 cycles
A comparison across sixteen oversample ticks of two disturbances on a receive line. Both begin with a mark-to-space transition at tick zero which the edge detector reports as a start candidate. The first disturbance returns to the mark level after four ticks, so when qualification samples the line at tick eight it finds mark and abandons the candidate with no frame begun and nothing reported. The second disturbance persists to tick twelve, so at tick eight qualification finds the line still at space and accepts it as a genuine start bit, after which the receiver schedules an entire frame of samples timed from a disturbance.qualification windowqualification windowwide one is now a framewide one is now a framecandidate — bothcandidate — bothVALIDATE: narrow=mark reject / wide=space ACCEPTVALIDATE: narrow=markreject / wide=space ACCEPTos tick101112131415narrowwidet0t1t2t3t4t5t6t7t8t9t10t11t12t13t14t15
Figure 1 — the qualification boundary. Columns are OVERSAMPLE TICKS at M = 16; validation occurs at tick 8, half a bit interval after the candidate. The two disturbances differ only in width. The narrow one has ended by the validation point and is discarded silently; the wider one is still at space there, so it is accepted as a start and the receiver times an entire frame from it.

4. Mid-Frame Attach, and the Block That Fixes It

Chapter 6.2 §7 demonstrated this and left it open. A receiver begins observing a line that is already carrying traffic — after reset, after hot-plug, after a connector is inserted — and the first mark-to-space transition it sees is not a start bit. It is a data edge inside someone else's frame.

The receiver qualifies it correctly, samples eight intervals from it correctly, and delivers a byte assembled from the tail of one frame and the head of the next. Simulation of the Module 6 receiver produced 0xFA from a frame carrying 0xA6, with the framing check passing because the line happened to be at mark where the stop sample landed.

Nothing in a UART frame identifies itself as a continuation. That is the direct consequence of Chapter 3.1's observation that framing is re-established from scratch at every start bit — there is no frame counter, no sequence number and no header. A receiver joining mid-stream cannot know it has.

The remedy is to refuse to trust a start until the line has been quiet long enough to prove no frame is in progress:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
Require the line to have been continuously at MARK for one full frame time
before any start candidate may be qualified.

A valid frame cannot hold the line at mark for a full frame time — the start interval is space — so observing that condition proves the line is genuinely idle rather than mid-frame.

A receiver joining live traffic

13 cycles
A trace of thirteen bit intervals of ongoing UART traffic. The first frame is already in progress when the receiver begins observing, indicated by an attach marker partway through it. The receiver sees the next mark-to-space transition and treats it as a start bit, but that transition is a data edge inside the frame already in flight. The receiver then samples eight intervals from that false origin, spanning the remainder of the first frame and the beginning of the next, and assembles a byte from intervals that were never a single transmitted character. The resulting byte is delivered, and the stop check may pass if the line happens to be at mark where that sample lands.frame already in flightframe already in flightthe frame the receiver inventedthe frame the receiver inventedreceiver attaches herereceiver attaches heredata edge read as a STARTdata edge read as a STARTfabricated byte deliveredfabricated byte deliveredreal framed4d5d6d7STOPSTd0d1d2d3d4d5d6rx_iRX thinksSTd0d1d2d3d4d5d6d7STOPSTOPt0t1t2t3t4t5t6t7t8t9t10t11t12
Figure 2 — mid-frame attach. Columns are BIT INTERVALS of traffic already in progress. The receiver begins observing partway through a frame and latches the next mark-to-space transition — which is a data edge, not a start bit. It then samples eight intervals from that origin, spanning the tail of one frame and the head of the next, and delivers a byte that was never transmitted.

The RTL

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------------
//  9.5 — idle qualification. The technique Chapter 6.2 §7 deferred: refuse to
//  accept a start until the line has been at mark for a full frame time, so a
//  receiver joining a live line cannot mis-frame on the remainder.
// ---------------------------------------------------------------------------
module uart_idle_qualify #(
    parameter int unsigned OVERSAMPLE = 16,
    parameter int unsigned FRAME_BITS = 10
) (
    input  logic clk,
    input  logic rst_n,
    input  logic os_tick_i,
    input  logic rx_sync_i,
    output logic line_idle_o        // LEVEL: mark held for a full frame time
);
    localparam int unsigned IDLE_TICKS = FRAME_BITS * OVERSAMPLE;
    localparam int unsigned CNT_W = (IDLE_TICKS <= 1) ? 1 : $clog2(IDLE_TICKS + 1);

    logic [CNT_W-1:0] mark_cnt_q;

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            mark_cnt_q  <= '0;
            line_idle_o <= 1'b0;      // NOT idle out of reset — must be earned
        end else if (rx_sync_i == 1'b0) begin
            mark_cnt_q  <= '0;
            line_idle_o <= 1'b0;
        end else if (os_tick_i) begin
            if (mark_cnt_q == CNT_W'(IDLE_TICKS)) begin
                mark_cnt_q <= mark_cnt_q;              // saturate
            end else begin
                mark_cnt_q <= mark_cnt_q + 1'b1;
                if (mark_cnt_q == CNT_W'(IDLE_TICKS - 1)) line_idle_o <= 1'b1;
            end
        end
    end
endmodule

It is the break detector's structure with the polarity inverted, which is not a coincidence: both answer "has the line held one level long enough to prove something?" — one about space, one about mark. Sharing the shape means sharing the reasoning, including the saturation and the +1 width derivation of Chapter 9.4 §4.

line_idle_o resets to 0, not 1. Idle must be earned, not assumed. A receiver out of reset has observed nothing and has no basis to claim the line is quiet — which is precisely the mid-frame case this block exists to catch. Resetting it high would defeat the entire mechanism at the one moment it matters most.

A single low sample clears it immediately, without waiting for a tick, for the same reason the break detector resets on a single mark: the condition is continuous, and deferring the clear would let a narrow disturbance be absorbed.

Integration is one extra term at the qualifier:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Conceptual SystemVerilog — gating start acceptance on proven idle.
// The qualifier itself is Chapter 5.2's, unmodified; this adds a
// precondition rather than changing the mechanism.
if (start_cand_i && line_idle_o) begin
    // ... Chapter 5.2's qualification proceeds from here
end

The measured behaviour

StimulusExpectedResult
line lownot idlepass
159 mark ticks (one short of a frame)not idlepass
160 mark ticks (a full frame)idlepass
counter after thresholdsaturates at 160pass
a single low sampleidle cleared immediatelypass

5. What Idle Detection Costs

It is a real remedy with a real price, and adopting it without the price is how a fix becomes a new problem.

Reception latency after every quiet period. The first frame after any idle gap shorter than a full frame time is rejected, because the line has not yet proven itself idle. On a link that sends isolated bytes with short gaps, this can reject a substantial fraction of traffic — and the rejection is silent, which is worse than a reported error.

It does not help a line that is never idle. A continuously saturated link — back-to-back frames with no gaps, which Chapter 7.4 showed a transmitter producing deliberately — never presents a full frame time of mark. A receiver attaching to such a link with idle detection enabled receives nothing at all, indefinitely, which is a far worse failure than one fabricated byte.

It cannot distinguish a genuinely idle line from a disconnected one. Chapter 1.3 noted that idle and several faults are indistinguishable; this block declares idle for both.

Without idle detectionWith idle detection
Mid-frame attachone fabricated byte, then correctcorrect from the first frame
Isolated bytes, short gapsall receivedsome silently rejected
Saturated link, attach mid-streamone fabricated byte, then correctnothing received, ever
Hardwarenonea counter and a comparator

So it is the right default for a link with natural gaps and the wrong default for a saturated one, which is why Module 6 left it out of the base receiver and named it here rather than adding it silently. A design should choose deliberately, and a design that cannot predict its traffic pattern should probably accept the one bad byte and let the layer above discard it.

6. Malformed Frames: What Is Observable

A frame that starts legitimately can still go wrong in several ways, and the useful question for each is not "what happened" — the receiver cannot know — but what can hardware observe, and what status is justified?

ShapeWhat hardware observesJustified statusPayload delivered?
Valid start, corrupted datanothing unusual at allnone — unless parity is enabled and the corruption is odd-weightyes, wrong
Valid start, parity failsthe parity relation does not holdparity_erroryes, with the flag
Valid start, stop is spacethe stop sample is not markframing_erroryes, with the flag
Line goes low and staysthe stop sample fails, then the break threshold is reachedframing_error then breakyes for the frame, then nothing
Wide glitch accepted as startnothing distinguishable from a real framenone guaranteedyes, meaningless

The first and last rows are the important ones, and they say the same thing from opposite directions: the receiver has no mechanism that reports "this frame is meaningless". It reports specific relation failures, and a frame can be entirely fabricated while satisfying every one of them.

The fourth row shows why two detectors are better than one. A line that goes low mid-frame and stays produces a framing error immediately and a break declaration one frame time later. The framing error alone is ambiguous; followed by a break, the interpretation is unambiguous — and this is why Chapter 9.4's detector runs as an observer rather than inside the FSM, so it keeps counting through a frame that is already failing.

7. Verification

Sweep glitch width across the qualification boundary. Narrower than M/2 must be rejected silently; wider must be accepted. The boundary is where a defect in the qualifier shows, and testing only "very short" and "a real frame" leaves it untouched.

Sweep glitch phase as well as width. A disturbance of fixed width lands differently depending on where it falls relative to the tick grid, so sweeping both finds the region rather than a single point — the same argument Chapter 5.4 §7 made about the voting window.

Test mid-frame attach explicitly. Release the receiver from reset while a frame is in flight and assert what actually happens — which, without idle detection, is a fabricated byte. Chapter 6.2 §7's simulation did exactly this and the expected result is not "no byte":

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
reset released mid-frame, no idle detection
-> one fabricated byte (0xFA from a frame carrying 0xA6), status clean
-> subsequent frames correct

A testbench that asserts no byte appears will fail on a correct receiver. That is worth knowing before spending a day on it.

Then test the same scenario with idle detection enabled and assert the byte is suppressed — and, separately, that a saturated link with idle detection receives nothing, because that is the cost and it should be visible in the suite rather than discovered in the field.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Assertion — idle is never claimed while the line is low.
property p_idle_implies_mark;
    @(posedge clk) disable iff (!rst_n)
        line_idle_o |-> rx_sync_i;
endproperty
assert property (p_idle_implies_mark);

// Assertion — idle cannot be claimed before a full frame time of mark.
property p_no_early_idle;
    @(posedge clk) disable iff (!rst_n)
        $rose(line_idle_o) |-> ($past(mark_cnt_q) == CNT_W'(IDLE_TICKS - 1));
endproperty
assert property (p_no_early_idle);

// Assertion — the counter saturates, matching Chapter 9.4's policy.
property p_idle_counter_saturates;
    @(posedge clk) disable iff (!rst_n)
        mark_cnt_q <= CNT_W'(IDLE_TICKS);
endproperty
assert property (p_idle_counter_saturates);

// Assertion — with idle gating fitted, no start is accepted from a line
// that has not proven itself idle. This is the block's entire purpose.
property p_no_start_without_idle;
    @(posedge clk) disable iff (!rst_n)
        start_accept_o |-> $past(line_idle_o);
endproperty
assert property (p_no_start_without_idle);

8. Debugging

9. What This Means on an FPGA

A floating receive input is the most common source of fabricated frames, and it is a board-level fix rather than an RTL one. An unconnected pin with no pull-up will produce edges, some of them wide enough to qualify, and the receiver will faithfully deliver bytes assembled from noise. A pull-up to the idle level costs one resistor and removes the entire failure class.

Probe start_cand alongside start_accept. The ratio between them is the qualifier's rejection rate, and it is a direct measure of line quality that no error flag provides. A board where candidates vastly outnumber acceptances is telling you something before any data is corrupted.

Idle detection is one counter, the same size as the break detector's, and the two can share nothing because they count opposite levels — but they can share the derivation and the review.

If both are fitted, expect them to be mutually exclusive. line_idle_o and break_active_o can never be true together, since one requires a full frame of mark and the other a full frame of space. An assertion to that effect is cheap and catches a polarity error in either block.

10. Understanding Check

11. Summary

Four start-side failures, rejected by four different mechanisms — or by none. A narrow glitch is rejected by qualification. A wide disturbance is rejected by nothing and produces a fabricated frame timed from noise. Mid-sample noise is Chapter 5.4's trade. Mid-frame attach is rejected only by idle detection.

Oversampling narrows the damaging class; it does not eliminate it. Qualification rejects what is narrower than the validation delay — 4.34 µs at 115,200 baud with M/2. Voting rejects what is narrower than one tick — 542.5 ns at 16×. A wide, well-placed disturbance is untouched by both.

A rejected candidate is not an error and should not be reported as one; as a debug counter it is a sensitive indicator of line quality.

Mid-frame attach produces a complete, clean-looking, entirely fabricated byte0xFA from a frame carrying 0xA6 in Module 6's simulation. Nothing in a UART frame identifies itself as a continuation, so the receiver cannot know.

Idle detection closes it: require a full frame time of continuous mark before qualifying any start, since a valid frame cannot hold mark that long. line_idle_o resets to 0 — idle is earned, not assumed.

And it costs. The first frame after any short gap is silently rejected, and on a saturated link the receiver gets nothing at all, indefinitely — a worse failure than the byte it was fitted to prevent. Right default for links with gaps; wrong for links without.

No status means "this frame is meaningless." The receiver reports relation failures, and a fabricated frame can satisfy every relation — which is the argument for framing above the byte layer.

12. What Comes Next

Five chapters have produced events: framing, parity, overrun, break, and the start-side failures that produce no event at all. None of them has said what the receiver should do.

Chapter 9.6 closes the module with that. It separates transient events from persistent state, builds the sticky flags with an explicit collision policy — what happens when software clears on the same cycle a new error arrives — distinguishes per-character status from historical status, and builds the re-synchronisation that returns the receiver to a trustworthy frame boundary without turning one bad frame into many.

Browse the full path on the UART tutorials index. For the qualification mechanism this chapter attacks, read back to Chapter 5.2; for the fabricated byte it explains, Chapter 6.2.

Continue learning

Where this fits

Part of the UART curriculum.