Manchester Encoder/Decoder in Verilog with Code

Manchester encoding is a self-clocking line code in which every bit is represented by a transition in the middle of the bit period, so the clock is embedded in the data stream itself. In the IEEE 802.3 convention a logic 0 is sent high-then-low and a logic 1 low-then-high. This page gives complete, simulator-verified Manchester encoder Verilog code together with a matching decoder that recovers the original bit from the two half-bit samples.

Both designs are written in portable Verilog-2005, run a half-bit-rate clock (two code symbols per data bit), and are checked with a self-testing loopback testbench so you can paste them straight into Icarus Verilog, industry-standard simulators or Vivado.

A clocked encoder running at the half-bit rate drives the coded line, and a decoder samples the two halves to rebuild the bit. The testbench wires them in loopback, drives a known pattern, and checks both the 802.3 half-bit encoding and the recovered data.

// Manchester encoder/decoder (IEEE 802.3 convention) with wired loopback
// 802.3: bit 0 -> high-then-low, bit 1 -> low-then-high (mid-bit transition)

module manchester_enc (
    input  wire clk,       // half-bit-rate clock (2 edges per data bit)
    input  wire rst,
    input  wire data_bit,  // held stable for the whole bit period
    output wire code        // Manchester-coded serial output
);
    reg phase;             // 0 = first half-bit, 1 = second half-bit
    always @(posedge clk or posedge rst)
        if (rst) phase <= 1'b0;
        else     phase <= ~phase;
    // first half = ~data (high for a 0), second half = data (low for a 0)
    assign code = phase ? data_bit : ~data_bit;
endmodule

module manchester_dec (
    input  wire clk,
    input  wire rst,
    input  wire code,
    output reg  bit_out,   // recovered data bit
    output reg  bit_valid  // high for one clk when bit_out is fresh/valid
);
    reg phase;
    reg first_s;           // sampled first half-bit
    always @(posedge clk or posedge rst)
        if (rst) begin
            phase <= 1'b0; first_s <= 1'b0; bit_out <= 1'b0; bit_valid <= 1'b0;
        end else begin
            if (!phase) begin
                first_s   <= code;      // capture first half
                bit_valid <= 1'b0;
            end else begin
                bit_out   <= code;              // second half == data (802.3)
                bit_valid <= (first_s ^ code);  // valid symbol must have a transition
            end
            phase <= ~phase;
        end
endmodule

module tb;
    reg clk, rst, data;
    wire code, bit_out, bit_valid;
    integer i, err;
    reg [7:0] pattern;

    manchester_enc u_enc (.clk(clk), .rst(rst), .data_bit(data), .code(code));
    manchester_dec u_dec (.clk(clk), .rst(rst), .code(code),
                          .bit_out(bit_out), .bit_valid(bit_valid));

    always #5 clk = ~clk;

    initial begin
        clk = 1'b0; rst = 1'b1; data = 1'b0; err = 0;
        pattern = 8'b1011_0010;   // sent MSB first: 1 0 1 1 0 0 1 0

        @(negedge clk); @(negedge clk); rst = 1'b0;

        for (i = 0; i < 8; i = i + 1) begin
            data = pattern[7-i];       // set at negedge, stable over the pair
            #1;
            // --- check 802.3 encoding on the two half-bits ---
            // first half (phase 0) is present now, before edge A
            if (code !== ~pattern[7-i]) begin
                $display("FAIL bit %0d first-half: exp %b got %b", i, ~pattern[7-i], code);
                err = err + 1;
            end
            @(posedge clk);            // edge A: phase -> second half
            #1;
            if (code !== pattern[7-i]) begin
                $display("FAIL bit %0d second-half: exp %b got %b", i, pattern[7-i], code);
                err = err + 1;
            end
            @(posedge clk);            // edge B: decoder latches recovered bit
            #1;
            // --- check decoded bit equals the original (loopback) ---
            if (bit_valid !== 1'b1) begin
                $display("FAIL bit %0d not flagged valid", i); err = err + 1;
            end else if (bit_out !== pattern[7-i]) begin
                $display("FAIL bit %0d decode: exp %b got %b", i, pattern[7-i], bit_out);
                err = err + 1;
            end else begin
                $display("PASS bit %0d  data=%b  halves=%b%b  decoded=%b",
                         i, pattern[7-i], ~pattern[7-i], pattern[7-i], bit_out);
            end
            @(negedge clk);            // between second and next-first half
        end

        if (err == 0) $display("ALL TESTS PASSED");
        else          $display("TESTS FAILED: %0d error(s)", err);
        $finish;
    end
endmodule
PASS bit 0  data=1  halves=01  decoded=1
PASS bit 1  data=0  halves=10  decoded=0
PASS bit 2  data=1  halves=01  decoded=1
PASS bit 3  data=1  halves=01  decoded=1
PASS bit 4  data=0  halves=10  decoded=0
PASS bit 5  data=0  halves=10  decoded=0
PASS bit 6  data=1  halves=01  decoded=1
PASS bit 7  data=0  halves=10  decoded=0
ALL TESTS PASSED

The log shows, for every bit, the two transmitted half-bits (e.g. 01 for a 1, 10 for a 0) matching the IEEE 802.3 convention, and the decoder recovering the identical bit through the loopback, ending in ALL TESTS PASSED.

This variant parameterizes the convention: CONV=0 is IEEE 802.3 and CONV=1 is the inverted G.E. Thomas convention. Two encoder/decoder pairs process the same data in parallel so the testbench can loopback-check each and confirm the two coded waveforms are exact bit-inverses.

// Manchester encoder/decoder with selectable convention.
//   CONV = 0 -> IEEE 802.3 : 0 = high-then-low, 1 = low-then-high
//   CONV = 1 -> G.E.Thomas: 0 = low-then-high, 1 = high-then-low  (inverse)
// Two pairs run the same data in parallel; the TB loopback-checks each and
// also checks the invariant that the two coded waveforms are bit-inverses.

module manchester_enc #(parameter CONV = 0) (
    input  wire clk, input wire rst, input wire data_bit,
    output wire code
);
    reg phase;
    wire first_half  = CONV ? data_bit : ~data_bit;
    wire second_half = CONV ? ~data_bit : data_bit;
    always @(posedge clk or posedge rst)
        if (rst) phase <= 1'b0; else phase <= ~phase;
    assign code = phase ? second_half : first_half;
endmodule

module manchester_dec #(parameter CONV = 0) (
    input  wire clk, input wire rst, input wire code,
    output reg  bit_out, output reg bit_valid
);
    reg phase, first_s;
    always @(posedge clk or posedge rst)
        if (rst) begin
            phase <= 1'b0; first_s <= 1'b0; bit_out <= 1'b0; bit_valid <= 1'b0;
        end else begin
            if (!phase) begin first_s <= code; bit_valid <= 1'b0; end
            else begin
                // 802.3: data == second half; Thomas: data == first half
                bit_out   <= CONV ? first_s : code;
                bit_valid <= (first_s ^ code);
            end
            phase <= ~phase;
        end
endmodule

module tb;
    reg clk, rst, data;
    wire code0, code1, bo0, bo1, bv0, bv1;
    integer i, err;
    reg [11:0] pattern;

    manchester_enc #(.CONV(0)) e0 (.clk(clk), .rst(rst), .data_bit(data), .code(code0));
    manchester_dec #(.CONV(0)) d0 (.clk(clk), .rst(rst), .code(code0), .bit_out(bo0), .bit_valid(bv0));
    manchester_enc #(.CONV(1)) e1 (.clk(clk), .rst(rst), .data_bit(data), .code(code1));
    manchester_dec #(.CONV(1)) d1 (.clk(clk), .rst(rst), .code(code1), .bit_out(bo1), .bit_valid(bv1));

    always #5 clk = ~clk;

    initial begin
        clk = 0; rst = 1; data = 0; err = 0;
        pattern = 12'b1100_1010_0111;   // 12-bit sweep, MSB first

        @(negedge clk); @(negedge clk); rst = 0;

        for (i = 0; i < 12; i = i + 1) begin
            data = pattern[11-i];
            #1;
            // invariant: 802.3 and Thomas codes are bit-inverses (first half)
            if (code0 === code1) begin
                $display("FAIL bit %0d first-half not inverted (%b/%b)", i, code0, code1);
                err = err + 1;
            end
            @(posedge clk); #1;
            if (code0 === code1) begin
                $display("FAIL bit %0d second-half not inverted (%b/%b)", i, code0, code1);
                err = err + 1;
            end
            @(posedge clk); #1;
            if (bv0 !== 1'b1 || bv1 !== 1'b1) begin
                $display("FAIL bit %0d valid flags (%b/%b)", i, bv0, bv1); err = err + 1;
            end else if (bo0 !== pattern[11-i] || bo1 !== pattern[11-i]) begin
                $display("FAIL bit %0d decode 802.3=%b thomas=%b exp=%b",
                         i, bo0, bo1, pattern[11-i]); err = err + 1;
            end else begin
                $display("PASS bit %0d data=%b  802.3=%b  thomas=%b (both decode %b)",
                         i, pattern[11-i], code0, code1, pattern[11-i]);
            end
            @(negedge clk);
        end

        if (err == 0) $display("ALL TESTS PASSED");
        else          $display("TESTS FAILED: %0d error(s)", err);
        $finish;
    end
endmodule
PASS bit 0 data=1  802.3=0  thomas=1 (both decode 1)
PASS bit 1 data=1 802.3=0 thomas=1 (both decode 1)
PASS bit 2 data=0 802.3=1 thomas=0 (both decode 0)
PASS bit 3 data=0 802.3=1 thomas=0 (both decode 0)
PASS bit 4 data=1 802.3=0 thomas=1 (both decode 1)
PASS bit 5 data=0 802.3=1 thomas=0 (both decode 0)
PASS bit 6 data=1 802.3=0 thomas=1 (both decode 1)
PASS bit 7 data=0 802.3=1 thomas=0 (both decode 0)
PASS bit 8 data=0 802.3=1 thomas=0 (both decode 0)
PASS bit 9 data=1 802.3=0 thomas=1 (both decode 1)
PASS bit 10 data=1 802.3=0 thomas=1 (both decode 1)
PASS bit 11 data=1 802.3=0 thomas=1 (both decode 1)
ALL TESTS PASSED

The log confirms that at each half-bit the 802.3 and Thomas lines are inverses of one another, and that both decoders independently recover the original data bit across a 12-bit sweep, ending in ALL TESTS PASSED.

Why Manchester coding is self-clocking

The defining property of Manchester encoding is a guaranteed transition in the middle of every bit, regardless of the data value. A receiver can lock onto those mid-bit edges to regenerate a sampling clock, which is why the scheme is called self-clocking. There is no separate clock wire and no risk of losing synchronization during long runs of identical bits, unlike NRZ where a string of zeros or ones gives the receiver no edges to track.

In the designs above the encoder divides each bit period into two half-bits driven by a phase register that toggles on every clock. The first half carries one level and the second half the opposite level, so the mandatory mid-bit edge always appears. The decoder uses the same phase alignment to capture the first and second half, and it flags a symbol as valid only when the two halves differ (first_s ^ code) — a missing transition indicates a framing or bit-slip error.

The two conventions: IEEE 802.3 vs G.E. Thomas

There are two mutually inverse definitions of Manchester coding, and mixing them up is a classic interview trap.

  • IEEE 802.3 (used by 10BASE-T Ethernet): a logic 0 is high then low, a logic 1 is low then high. Here the data bit equals the second half-bit.
  • G.E. Thomas (the original 1949 convention): a logic 0 is low then high, a logic 1 is high then low. Here the data bit equals the first half-bit.

The second example makes this explicit with a CONV parameter. Because the two conventions simply swap the two half-bit levels, their coded waveforms are exact logical inverses of each other for the same data — an invariant the testbench verifies directly. Always state which convention you mean when you say “Manchester”.

DC balance and the bandwidth cost

Every Manchester symbol spends exactly half the bit period high and half low, so each bit is inherently DC-balanced: the long-term average of the line sits at the midpoint no matter what the data is. That makes the code friendly to transformer and capacitive (AC) coupling, which cannot pass a DC component, and it keeps receiver slicers centered.

The price is bandwidth. Because there can be a transition at the mid-bit and another at the bit boundary, the maximum fundamental rate is twice that of NRZ for the same data rate. Manchester therefore needs roughly double the bandwidth of plain NRZ — the reason 10BASE-T uses it but faster Ethernet (100BASE-TX and up) moved to more spectrally efficient codes such as 4B5B/MLT-3 and 8B10B.

Clock recovery and decoding

A real receiver does not share the transmitter clock, so it must recover timing from the mid-bit transitions. A common approach is a digital phase-locked loop (DPLL) or an oversampling scheme: sample the line at several times the bit rate, detect the guaranteed mid-bit edge, and phase-align a local half-bit clock to it. Once aligned, the receiver reads the two half-bit samples per bit exactly as the decoder in these examples does.

The decoders here assume phase alignment is already established (the loopback shares the clock), which isolates the coding logic for clarity. In silicon you would precede them with a transition-based clock-recovery block and a preamble (such as a run of alternating bits) that lets the DPLL settle before real data arrives.

Common mistakes and synthesis notes

Common mistakes

  • Wrong convention. Encoding with 802.3 and decoding with Thomas inverts every bit. Pin down the convention on both ends.
  • Losing phase alignment. If the decoder starts in the wrong half-bit phase it samples across bit boundaries and the validity check fails — use the mid-bit transition for alignment.
  • Forgetting the validity check. Two equal half-bits are not a legal Manchester symbol; treating them as data hides bit-slip errors.

Synthesis notes

Both modules are synthesizable: the encoder is a single toggling phase flop plus combinational muxing, and the decoder is two flops and a sample register. Drive the module clock at the half-bit rate (twice the data rate). For higher integration, replace the shared clock with an oversampled recovered clock and register the combinational code output at the pad to keep the transmit waveform glitch-free.

FAQ

Is Manchester encoding still used?

Yes — in 10BASE-T Ethernet, many RFID and NFC links, IR remote protocols, and low-speed industrial buses where self-clocking and DC balance matter more than spectral efficiency.

What clock does the encoder need?

Run it at twice the data rate (the half-bit rate), because two code symbols are transmitted per data bit.

Why is the data rate half the signalling rate?

Each bit uses two half-bit cells to guarantee a mid-bit transition, so Manchester trades half the throughput of NRZ for embedded clocking and DC balance.

Have questions about this topic?
Share your question in comments or talk to our mentor team for batch guidance.
▶ Try it in the ChipXpert Lab

Open this design in the free in-browser simulator — edit, compile and see the waveform/log instantly.

Run it in the Lab

Learn Verilog with mentors, labs and placement support

This free series is maintained by the ChipXpert training team in Hyderabad & Bengaluru. Go deeper with instructor-led courses on real EDA tools.

Explore VLSI Courses
Next batch starts 18th November 2026
Start your VLSI career with ChipXpert

Live online and classroom batches in Hyderabad & Bengaluru. Fill in your details and a counsellor will call you back.

  • Real EDA tools in your browser: industry-standard EDAReal EDA tools in your browser
  • Recorded sessions on the elearn portalRecorded sessions
  • Placement assistance: resume, mock interviewsPlacement assistance
  • Merit scholarship up to 60% · EMI optionsScholarship up to 60%
Hi! Ask me about courses, fees, batches or discounts. ×
BENGALURU
HYDERABAD