Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Paths
  • Concept Map
  • How to Read the Diagrams
  • Part 0: What Is a Protocol?10
  • Part 1: Timing and Clocking11
  • Part 2: Encoding and Framing12
    • Line Codes
    • Framing Basics
    • Packet Anatomy
    • Bit Stuffing
    • DC Balance and Running Disparity
    • Block Codes
    • Scrambling
    • Alignment and Lock
    • Control Symbols and Ordered Sets
    • Flits, Phits and Packing
    • Protocols Compared: Encoding and Framing
    • Drills: Encoding and Framing
  • Part 3: Handshakes13
  • Part 4: Flow Control17
  • Part 5: Transactions19
  • Part 6: Concurrency and Performance17
  • Part 7: Ordering13
  • Part 8: Sharing and Arbitration12
  • Part 9: Deadlock and Liveness13
  • Part 10: Reliability and Recovery20
  • Part 11: Bring-Up and Link Management10
  • Part 12: Power8
  • Part 13: Shared State and Coherence9
  • Part 14: Security and Isolation7
  • Part 15: Specifying and Verifying11
  • Part 16: Protocols Dissected17
  • Part 17: Capstones5
  • Part 18: Interview Preparation6
Loading lesson

‹Part 2: Encoding and Framing
  1. Topics
  2. First Principles of Hardware Protocols
  3. Part 2: Encoding and Framing
  4. Block Codes

Part 2 · Encoding and Framing · Working (W)

Block Codes

8b/10b, 64b/66b and 128b/130b: what each block code guarantees about transitions, balance and control symbols, and what its overhead costs in real bandwidth.

On this page

    Note

    Level: Working (W) · Answers: Where does a message start and end?

    Before this: Bit Stuffing, DC Balance and Running Disparity

    Moving from one generation of a serial link to the next, the line rate goes from 5 to 8 gigatransfers per second, only 60% faster. Yet the useful bandwidth per lane almost doubles. No trick in the electronics explains it. The difference is entirely in how the bits are encoded.

    What do block codes guarantee, and what does each one cost?

    The obvious answer, and why it breaks

    Lessons 2.4 and 2.5 left a link needing three guarantees: transitions often enough for clock recovery, a bounded running disparity for AC coupling, and a way to send framing and control information that data can never imitate. Bit stuffing provides the first and third but makes frame length depend on data, which is awkward at high rates. Something with a fixed overhead and fixed-size blocks is needed, and that overhead is paid on every bit forever, so it had better be small.

    The idea: map fixed-size blocks to slightly larger ones

    A block code maps every n data bits to m line bits (m > n). The extra m − n bits buy guarantees. The overhead, as a share of the line rate, is:

    overhead=mm−n​,payload rate=line rate×mn​

    The three codes in wide use buy their guarantees differently:

    Code

    How it works

    Guarantees

    Overhead

    8b/10b

    A table maps each byte to one of two 10-bit code groups; extra code groups are reserved as control symbols

    At most five identical bits in a row; bounded disparity (the encoder chooses the group that restores balance); unique control symbols such as the comma (K28.5) for alignment

    20%

    64b/66b

    A 2-bit sync header (01 = data, 10 = control) in front of 64 scrambled bits

    A transition in every header; balance and transitions in the payload only statistically, through scrambling

    about 3%

    128b/130b

    A 2-bit sync header (10 = data block, 01 = ordered-set block) in front of 128 scrambled bits

    Same idea as 64b/66b, with half the overhead

    about 1.5%

    Where each code spends its extra bits.

    Build it: overhead and payload per lane

    The model computes each code's overhead, then the payload bandwidth per lane for five PCI Express generations, using their published line rates and codes.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    """Line-code overhead and what it does to payload bandwidth per lane.
    
    Line rates for PCI Express generations: Gen1 2.5, Gen2 5.0, Gen3 8.0, Gen4 16.0,
    Gen5 32.0 GT/s per lane. Gen1-2 use 8b/10b; Gen3-5 use 128b/130b.
    """
    codes = {"8b/10b": (8, 10), "64b/66b": (64, 66), "128b/130b": (128, 130)}
    print("code        overhead (share of the line rate)")
    for name, (d, t) in codes.items():
        print(f"{name:11} {100 * (t - d) / t:5.2f}%")
    
    gens = [("Gen1", 2.5, "8b/10b"), ("Gen2", 5.0, "8b/10b"), ("Gen3", 8.0, "128b/130b"),
            ("Gen4", 16.0, "128b/130b"), ("Gen5", 32.0, "128b/130b")]
    print("\ngeneration  line rate  code        payload per lane")
    payload = {}
    for g, rate, code in gens:
        d, t = codes[code]
        payload[g] = rate * d / t
        print(f"{g:10}  {rate:5.1f} GT/s  {code:10}  {payload[g]:6.3f} Gb/s")
    ratio = payload["Gen3"] / payload["Gen2"]
    print(f"\nGen2 -> Gen3: line rate x{8.0 / 5.0:.2f}, payload x{ratio:.2f}")
    assert abs(ratio - 1.97) < 0.01
    print("PASS: dropping 8b/10b's 20% overhead let Gen3 nearly double payload with a 1.6x line rate")

    It prints:

    Diagram
    code        overhead (share of the line rate)
    8b/10b      20.00%
    64b/66b      3.03%
    128b/130b    1.54%
    
    generation  line rate  code        payload per lane
    Gen1          2.5 GT/s  8b/10b       2.000 Gb/s
    Gen2          5.0 GT/s  8b/10b       4.000 Gb/s
    Gen3          8.0 GT/s  128b/130b    7.877 Gb/s
    Gen4         16.0 GT/s  128b/130b   15.754 Gb/s
    Gen5         32.0 GT/s  128b/130b   31.508 Gb/s
    
    Gen2 -> Gen3: line rate x1.60, payload x1.97
    PASS: dropping 8b/10b's 20% overhead let Gen3 nearly double payload with a 1.6x line rate

    That is the opening puzzle solved. Going from Gen2 to Gen3, the line rate rose 1.6 times but the payload rose 1.97 times, because 8b/10b's 20% overhead dropped to about 1.5%. The trade is in the guarantees: 8b/10b's run-length and balance limits are hard, while 128b/130b's depend on scrambling, plus the header's guaranteed transition in every block.

    Why not always use the cheapest code?

    • Hard versus statistical guarantees. 8b/10b bounds run length and disparity for any data. Scrambled codes make bad patterns extremely unlikely but not impossible, so receivers must tolerate more baseline wander and longer runs.

    • Control symbols. 8b/10b has spare code groups that data can never produce, which makes framing and alignment simple and robust. Scrambled codes signal control with the header ("this block is control") and a type field inside, which costs design effort.

    • Latency and granularity. 8b/10b works byte by byte; 128b/130b needs a full block to be assembled, which adds a little latency and forces data into 16-byte units.

    • Error behaviour. One bit error in an 8b/10b code group usually produces an invalid code, which is detected immediately. In a scrambled code an error stays a simple bit error (but self-synchronising scramblers can multiply it, lesson 2.7).

    The design space

    If you need...

    Choose

    Because

    Hard limits on runs and balance, simple control symbols, moderate rates

    8b/10b

    Every guarantee is unconditional; overhead is acceptable below a few Gb/s

    High rates where 20% is too much bandwidth to give away

    64b/66b or 128b/130b

    Low overhead; transitions from the header and scrambling

    Very high rates with PAM4 and FEC

    Fixed-size flits protected by FEC (lesson 2.10)

    The coding and the error correction are designed together

    How real protocols chose

    Protocol

    Code

    PCI Express Gen1–2

    8b/10b

    PCI Express Gen3–5

    128b/130b, with a 2-bit sync header (10 data, 01 ordered set) that is not scrambled

    PCI Express Gen6

    PAM4 signalling with fixed 256-byte flits and FEC

    10 Gb/s Ethernet (10GBASE-R)

    64b/66b, with sync header 01 for data blocks and 10 for control blocks: the opposite assignment from PCIe's 128b/130b

    What breaks

    A bandwidth estimate for a new system uses the line rate as the payload rate (illustrative): a x4 link at 5 GT/s is assumed to carry 20 Gb/s. With 8b/10b it carries 16 Gb/s before any packet overhead, and the design misses its throughput target by 20% at the first measurement. The fix is a habit: always multiply by n/m first, then subtract framing, header and flow-control overheads (lesson 6.9).

    Why this matters

    Senior lens. A line code is a decision about where guarantees come from. 8b/10b buys them with bandwidth; 64b/66b and 128b/130b buy them with probability and careful receiver design. When a link moves from one to the other, the receiver's tolerance for wander and long runs, the alignment and control-symbol scheme, and the error detection model all change, not just the efficiency. Review those, not just the headline percentage.

    Interview

    Asked: "Why did PCIe move from 8b/10b to 128b/130b?"

    Weak answer: To go faster.

    Strong answer: 8b/10b costs 20% of the line rate. Doubling Gen2's payload with 8b/10b would have needed 10 GT/s. Gen3 instead runs at 8 GT/s with 128b/130b, whose overhead is about 1.5%: payload per lane went from 4 to about 7.9 Gb/s, nearly double, with only a 1.6x line rate. The cost is that run length and balance are no longer hard limits: they come from scrambling, plus a 2-bit sync header that always has a transition.

    Follow-ups: (1) What does 8b/10b guarantee that 128b/130b does not? (2) How does a 128b/130b receiver tell a data block from an ordered set?

    Check yourself A x8 link runs at 8 GT/s per lane with 128b/130b. What is its raw payload bandwidth before packet overhead?

    8 × 8 × 128/130 ≈ 63.0 Gb/s, about 7.9 GB/s.

    Check yourself Why is the sync header of a 128b/130b block never scrambled?

    The receiver must find block boundaries by looking for valid headers (01 or 10) before it can descramble anything, and each header must contain a guaranteed transition.

    Check yourself What do 8b/10b's spare code groups give a protocol?

    Control symbols that data can never produce, such as the comma used for word alignment, so framing and alignment markers are unambiguous.

    Key takeaways

    • A block code maps n data bits to m line bits; overhead is (m − n)/m: 20% for 8b/10b, about 3% for 64b/66b, about 1.5% for 128b/130b.

    • 8b/10b guarantees run length, balance and control symbols for any data; 64b/66b and 128b/130b rely on scrambling plus a 2-bit header.

    • Always convert line rate to payload rate with n/m before any bandwidth estimate.

    Keep going

    Next: Lesson 2.7, Scrambling. How a scrambler makes any data look random, and why both ends must stay in step.

    Related topics

    • Part 2 overview: Encoding and Framing

    Previous

    31 / 234

    Next: Scrambling

    Up next

    Up nextScrambling

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Line Codes
    • Framing Basics
    • Packet Anatomy