Message on WhatsApp Book a Session
Hardware Design Challenge · #002

Build a Multi-Mode Line Encoder/Decoder

Architecture Context

A line encoder/decoder is a PCS-layer (Physical Coding Sublayer) transformation. It sits between an SoC fabric — which speaks parallel payload words — and a SerDes/PMA — which puts encoded bits on a wire. The encoder shapes the parallel payload into a line-coded bitstream with the run-length, DC-balance, and framing properties the link standard requires (NRZ, NRZI, Manchester-II, 8b/10b, 128b/130b, 4b/5b…). The decoder runs in reverse.

In this system, the block lives on a single clock domain between a 512-bit AXI-Stream payload bus (toward the fabric) and a wide parallel line bus (toward a downstream gearbox + serializer). It is payload-agnostic — no parsing, no framing.

Engineering / Business Context

A single programmable IP that supports six encodings vs. six hardcoded IPs is a deliberate trade-off:

The decision is driven by NRE budget and tape-out schedule, not gate count. Any design that adds gates without paying for itself in reuse is the wrong answer here.

Problem Statement

Design the RTL for a module LINE_ENC_DEC that meets the interface, configuration, and timing contract below.

The expected answer-on-LinkedIn-DM is your interface contract (top-level signals + handshake rules) and a one-paragraph microarchitecture sketch — not full RTL.

The Block Diagram (System Context)

Top-level block diagram of LINE_ENC_DEC showing all input/output ports and dashed internal sub-blocks
Top-level ports of LINE_ENC_DEC with internal sub-blocks hinted (dashed).
The diagram is for your benefit. It anchors the system context, names signals, and disambiguates where the encode and decode paths live. Your solution sits inside LINE_ENC_DEC. The dashed sub-blocks (encode WR buffer + P2S, encode core, decode core, S2P + AXI-S align) are suggestions hinting at the natural decomposition — they are part of what you will design, not something handed to you.

System Parameters

ParameterValue
Clock (clk)Single domain. Target frequency 500 MHz. Both AXI-S and line interfaces run on this clock.
Reset (rst_n)Active-low. Async-asserted, sync-deasserted to clk. All module flops reset on assertion.
ThroughputMust sustain full-rate s_axis and m_axis (one beat per cycle when not backpressured) for any non-reserved enc_sel.
LatencyNot a hard constraint. Justify any pipeline depth > 4 cycles.
LINE_WDesigner-chosen parameter. Pick a value that lets the line side keep up with the AXI-S side under the worst-case encoding.

The Waveform — Worked Example (Manchester-II encode)

Waveform showing one AXI-Stream input beat producing multiple line_out beats under Manchester-II encoding
One 512-bit AXI-S input beat under Manchester-II → n beats on line_out, where n depends on LINE_W.

Interface & Configuration Spec

Interfaces

SideDirInterface
s_axisinAXI-Stream slave, tdata=512b, tkeep[63:0], tlast. Used only in ENCODE.
m_axisoutAXI-Stream master, tdata=512b, tkeep[63:0], tlast. Used only in DECODE.
line_inindata[LINE_W-1:0], valid/ready. Used only in DECODE.
line_outoutdata[LINE_W-1:0], valid/ready. Used only in ENCODE.

Configuration (latched at burst start, held until TLAST)

Behavioral rules

The Questions

  1. Pick LINE_W. What's a sensible value of LINE_W, and why? Sketch the relationship between AXI-S beat throughput, encoding ratio, and LINE_W. Where does throughput backpressure show up first if you pick LINE_W too small?
  2. Gearbox math. For a single 512-bit input beat, how many line_out beats do you emit under each non-reserved scheme? Which schemes leave a "ragged" tail (partial codeword) at TLAST, and how do you flush it cleanly?
  3. Stateful vs combinational. NRZ and NRZI are essentially combinational (NRZI tracks 1 bit of state). Manchester-II is combinational with a 2× doubler. 8b/10b carries running disparity. 128b/130b carries scrambler state and block sync. How do you structure the core so the stateful schemes don't tax area when a stateless one is selected — or do you accept the cost?
  4. Reserved-code policy. When enc_sel ∈ {110, 111} at the start of a burst, should the module: (a) silently drop the input, (b) deassert s_axis_tready and hold until SW reconfigures, or (c) accept and emit a defined error pattern on line_out? Defend your choice on system-integration grounds.
  5. Bidirectional reuse. A reasonable answer shares the codeword LUTs between encode and decode. What's the cost of doing that vs separate encode/decode datapaths?
How to share your answer DM me on LinkedIn with your interface contract (top-level signals + handshake rules) and a one-paragraph microarchitecture sketch. I'll feature the cleanest reasoning in next week's post. DM on LinkedIn →

Going Further (bonus)

What changes if input bursts can be multi-beat (TLAST arrives several beats in), and the encoding is 128b/130b — where the 130-bit codeword can straddle a beat boundary on either the input or the output side? Where does the complexity move to: gearbox, scrambler reset, or burst boundary tracking?

WhatsApp Book a Session