Skip to content
VLSI Mentor

UART · Module 3

Data Bits and LSB-First Transmission

Three different orderings get called bit order: numerical significance, array index, and time on the wire. UART fixes only the third, and the byte is never reversed — a verified byte-to-wire walkthrough, the shift-register invariant, and how to annotate a capture without fooling yourself.

Chapter 3.1 anchored the frame: a transition supplies the origin, a start interval occupies the first position, and the payload begins at the next one. The positions exist. This chapter decides what goes in them.

The question sounds trivial and is responsible for a disproportionate share of bring-up time:

Given a value held in parallel inside a device, which of its bits goes onto the conductor first?

UART's answer is the least significant bit. The trouble is not the rule — it is one line — but that three different things are casually called "bit order", and an engineer holding two of them at once will mis-annotate a perfectly good capture and conclude the hardware is broken. Separating the three is most of this chapter.

1. Three Things Called Bit Order

Write an eight-bit value down and three different orderings are already present. They agree often enough to be confused and differ exactly where it matters.

Numerical significance. Bit 7 contributes 128, bit 0 contributes 1. This is a property of the value and has nothing to do with wires or time.

Array index. In logic [7:0] data, data[0] is the least significant element and data[7] the most. This is a property of the declaration, and it is a convention the designer chose — [0:7] would reverse the indices while leaving the value identical.

Temporal order. Which bit occupies the earliest bit interval on the conductor. This is a property of the protocol, and it is the only one UART specifies.

UART's rule is stated entirely in the third: the least significant payload bit occupies the first payload interval. Under the usual [N-1:0] declaration that makes data[0] first and data[N-1] last — but that correspondence comes from the declaration convention, not from the protocol.

2. A Byte on the Wire

Take a deliberately asymmetric value. Symmetric patterns like 0x55 are a poor first example precisely because a bit-order mistake leaves them looking correct.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
value            = 0xA6
binary, b7..b0   = 1010_0110

significance:
  bit    7  6  5  4  3  2  1  0
  value  1  0  1  0  0  1  1  0
  weight 128 64 32 16  8  4  2  1

Now the same value laid out along time, LSB first:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
interval  D0 D1 D2 D3 D4 D5 D6 D7
source    b0 b1 b2 b3 b4 b5 b6 b7
line       0  1  1  0  0  1  0  1

Read the line row left to right — 0110 0101 — and it is not 1010 0110. Both are correct descriptions of 0xA6; they are laid out along different axes.

A second value, chosen because its wire pattern differs from the first in a way a careless reading would miss:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
value            = 0x96
binary, b7..b0   = 1001_0110

interval  D0 D1 D2 D3 D4 D5 D6 D7
line       0  1  1  0  1  0  0  1

0xA6 and 0x96 differ in one bit position — bit 5 versus bit 4 — and on the conductor that difference appears at intervals D4 and D5. Anyone annotating a capture by eye, without writing the interval labels down, will mix these two values up.

0xA6 = 1010_0110, transmitted LSB first

10 cycles
A UART line is shown over ten bit intervals. Interval zero is the start interval at the space level. Intervals one through eight carry the eight payload bits of the value 0xA6 in least-significant-first order, so the line values are zero, one, one, zero, zero, one, zero, one, corresponding to bit zero through bit seven of the binary value 1010 0110. Interval nine returns to the mark level. Markers label the start interval and the payload intervals D0, D3 and D7, identifying which bit of the source value each one carries.STARTSTARTpayload D0..D7, LSB firstpayload D0..D7, LSB firstmarkmarkSTARTSTARTD0 = bit 0 = 0 (LSB, first)D0 = bit 0 = 0 (LSB, first)D3 = bit 3 = 0D3 = bit 3 = 0D7 = bit 7 = 1 (MSB, last)D7 = bit 7 = 1 (MSB, last)linet0t1t2t3t4t5t6t7t8t9
Figure 1 — the byte 0xA6 on the conductor. Each column is one UART bit interval, not a system-clock cycle. The payload occupies intervals D0 through D7 after the start interval, with D0 carrying bit 0 — the least significant. Reading the payload columns left to right gives 0110 0101, which is the same value as 1010 0110 written along the significance axis instead of the time axis.

3. The Mapping, on Both Sides

The convention is one rule, and each endpoint implements it as an invariant rather than as a transformation.

A parallel value held in a transmitter's register is serialised onto a single conductor by presenting its least significant bit first, advancing through increasing bit significance across successive bit intervals. The conductor carries one bit per interval. A receiver stores the first payload sample into its own least significant position and advances through increasing significance in the same order, reconstructing the original parallel value. Neither endpoint performs a reversal; both traverse the bit index in the same direction.TX parallel valuebit 0 … bit N−1presents bit 0 firstindex ascends per intervalstores into bit 0firstindex ascends per intervalRX parallel valuebit 0 … bit N−1load1 bitassemble12
Figure 2 — the byte-to-wire mapping. The transmitter presents its least significant payload bit to the line first and advances through increasing significance; the receiver stores the first payload sample into its least significant position and advances the same way. Neither side reverses anything — both walk the same index in the same direction, so the value arrives unchanged.

Transmitter: the shift-register invariant

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Synthesizable SystemVerilog — payload serialisation only.
// Deliberately absent: baud timing (Modules 4 and 8) produces bit_advance_i,
// and the frame sequencer (Module 7) decides when load_i and the start,
// parity and stop intervals occur. This is the payload field alone.
module uart_tx_shift #(
    parameter int unsigned DATA_W = 8
) (
    input  logic              clk,
    input  logic              rst_n,
    input  logic              load_i,          // capture a new payload
    input  logic [DATA_W-1:0] data_i,
    input  logic              bit_advance_i,   // one pulse per bit interval
    output logic              serial_bit_o     // drives the line this interval
);
    logic [DATA_W-1:0] shreg;

    // THE INVARIANT: shreg[0] is always the next payload bit to place on
    // the line. Everything else follows from maintaining it.
    assign serial_bit_o = shreg[0];

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            shreg <= '0;
        end else if (load_i) begin
            shreg <= data_i;                       // bit 0 is now at shreg[0]
        end else if (bit_advance_i) begin
            shreg <= {1'b0, shreg[DATA_W-1:1]};    // shift right: bit 1 moves in
        end
    end
endmodule

Why bit 0 is presented first is not a property of the shift direction — it is the assignment on serial_bit_o. The output is tied to element 0, so whatever occupies element 0 is what the line carries. After load_i, that is data_i[0], the least significant bit.

Why it shifts right follows from the invariant rather than the other way round. To make data_i[1] the next bit on the line, it must arrive at element 0 — so the register moves toward lower indices. Stating the invariant first makes the direction a consequence; stating the shift first makes the direction a thing to memorise and get backwards.

What shifts in is a zero here, and it does not reach the line within this frame: after DATA_W advances the payload field is complete and the sequencer moves to the next field. The fill value is a don't-care that is given a definite value rather than left undriven.

bit_advance_i is one pulse per bit interval, produced by the rate logic of Modules 4 and 8. It is an enable in this clock domain, not a second clock — the architecture Chapter 2.2 §7 introduced.

Reset clears rather than loading. The payload is meaningless until load_i, and the frame sequencer will not be driving payload onto the line before then.

Receiver: store into the index, do not reverse the stream

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Conceptual SystemVerilog — payload assembly only, not a receiver.
// bit_index_i comes from the phase counter of Chapter 2.3, and
// sample_valid_i from the sampling mechanism of Module 5.
always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n)                 rx_data <= '0;
    else if (sample_valid_i)    rx_data[bit_index_i] <= sampled_bit_i;
end

This is the receive-side counterpart of the same invariant, and it is written as an indexed store for a reason.

The tempting alternative is to shift samples into a register and reverse at the end, or to shift left because the arriving bits "look reversed". Both work if the direction is chosen correctly and both are easy to get backwards, because neither expresses what is actually true. The indexed form states it directly: the sample taken during payload interval k belongs in bit position k. That sentence is the protocol rule, and code shaped like it cannot be off by a reversal.

It also generalises to a configurable width without change, which the shift-and-reverse form does not — reversing an eight-bit register and using the low seven bits is not the same as assembling a seven-bit value.

4. Payload Width Is a Configuration Choice

The payload field does not have a universal length. Implementations commonly expose a choice among five, six, seven, eight and nine payload bits, and which subset a particular UART offers is a capability of that IP, published in its documentation — not something the framing guarantees. A design that assumes every UART it meets supports nine-bit payloads will be disappointed; so will one that assumes every UART supports five.

Two consequences matter here, with the full configuration treatment in Chapter 3.5.

Width changes the frame's length, not just its content. Chapter 2.2 gave N_frame as a sum of field counts. A narrower payload makes a shorter frame, which — by Chapter 2.4's linear accumulation — is a frame with less drift at its end.

"Frame" and "byte" are not synonyms. They coincide at eight payload bits and diverge elsewhere. A seven-bit configuration carries seven payload bits per frame, and calling that "a byte" is the kind of slip that leads to buffers sized wrongly and masks forgotten.

5. Reading a Capture Without Fooling Yourself

This is the practical skill the chapter exists to produce, and the failure mode is specific enough to name.

A sequence showing payload transfer between a transmitter and a receiver. The transmitter loads a parallel value and presents its bit zero on the line during the first payload interval. The receiver samples that interval and stores the result into its own bit zero. For each following interval the transmitter advances to the next higher bit index and the receiver stores into the matching index, so both traverse the index in the same ascending direction. After the final payload interval the receiver holds a value identical to the one the transmitter loaded, with no reversal performed at either end.TransmitterLineReceiverload value — bit 0at shreg[0]interval D0 carriesbit 0sample stored intobit 0interval Dk carriesbit ksample stored intobit kfinal intervalcarries bit N−1value complete —nothing reversed
Figure 3 — the two sides as an ordered exchange, showing that both traverse the index in the same direction. The transmitter's first payload interval carries its bit 0 and the receiver stores that sample into its bit 0; each subsequent interval advances both by one. No step in the sequence reverses anything.

6. What This Means for Verification

Bit ordering is a property that a badly chosen stimulus set will not test at all.

Symmetric payloads are nearly useless here. 0x00, 0xFF and 0x55 are all invariant or near-invariant under bit reversal, so a design that serialises in the wrong direction passes every one of them. A test suite built from convenient constants can miss a total inversion of the payload order. Asymmetric values are the ones that discriminate, and a value and its bit-reversal — 0xA6 and 0x65 — make an excellent pair, because a reversed implementation maps one onto the other exactly.

Walking patterns locate the fault. A payload with exactly one bit set, applied at each position in turn, maps each source bit to a specific interval. When something is wrong, the position that fails tells you which mapping is broken, where a random payload only tells you that something is.

Width is an axis. Every supported payload width should be exercised, and the extremes matter most: the narrowest and widest supported configurations exercise the sequencer's field-length comparison at its boundaries, and an off-by-one there transmits or assembles the wrong number of intervals.

The checker should assemble, not compare raw. A scoreboard that reconstructs the value by the same indexed rule as §3 is checking the protocol. One that compares a captured bit string against a literal is encoding an assumption about layout, and will report a failure the first time someone changes the capture format.

7. What This Means on an FPGA

Instrument the payload with labels, not with a bus. An internal logic-analyser capture of rx_i shows the same time axis a bench instrument does, so the same annotate-then-read discipline applies. Capturing the assembled parallel value alongside the line is more useful still: the two together immediately separate an ordering fault from a sampling fault.

Width parameterisation is where re-targeting breaks. A design parameterised on DATA_W needs its payload register, its interval counter and the sequencer's comparison to move together. Deriving the counter width from the parameter, as Chapter 2.2 §7 did, is what keeps them consistent when the parameter changes.

The shift register is small and the temptation is to hand-optimise it. Writing the shift as an explicit concatenation, as §3 does, synthesises to exactly the intended structure and stays readable. A design that reverses on load to allow a left shift produces the same waveform and an implementation nobody can review against the protocol rule.

8. Understanding Check

9. Summary

Three orderings are casually called bit order: numerical significance, a property of the value; array index, a property of the declaration; and temporal order, a property of the protocol. UART specifies only the third — the least significant payload bit occupies the first payload interval. Under the usual [N-1:0] declaration that makes data[0] first, but that correspondence comes from the declaration convention, not from the framing.

Nothing is reversed. A written value runs along the significance axis and a capture runs along the time axis, which makes them look like mirror images. 0xA6 = 1010_0110 appears on the conductor as 0110 0101 across D0 to D7, and both describe the same unchanged value. Believing a reversal occurs leads to implementing one, and a design that reverses interoperates only with itself.

Each side maintains an invariant rather than performing a transformation. The transmitter's is shreg[0] is the next bit to place on the line — from which the right shift follows as a consequence. The receiver's is the sample from payload interval k belongs in bit position k, which an indexed store expresses directly and a shift-and-reverse expresses only accidentally, breaking when the width becomes configurable.

Payload width is a configuration choice, commonly a subset of five to nine bits, and which subset exists is a capability of a particular IP rather than a framing guarantee. Width changes the frame's length as well as its content, and frame and byte are not synonyms outside the eight-bit case.

The practical discipline is to annotate before reading: label the start interval, then D0 onward, then assemble by index. Reading a capture left to right as a binary literal compares two different axes and always disagrees, which makes it useless for distinguishing a working link from a broken one.

10. What Comes Next

The payload field is defined and its positions are unambiguous. Chapter 3.3 adds the field that may follow it: a single optional interval carrying a parity bit, derived from the payload by an XOR reduction. It is the smallest error-detection mechanism in common use, and the chapter's real subject is the sharp boundary between the corruption it provably catches and the corruption it provably cannot.

Browse the full path on the UART tutorials index. For the same serialisation problem treated as an RTL pattern rather than a protocol rule, see UART (FSM + shift register + baud timer).

Continue learning

Where this fits

Part of the UART curriculum.