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:
- Cost: more area (LUTs + state for all schemes coexist) and more DV cycles (mode-cross coverage).
- Benefit: one design serves PCIe, USB, Ethernet, and MIPI variants — collapsing several product SKUs into one base IP and pushing differentiation into fuses/straps instead of separate tape-outs.
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.
- Deliverable: the module. Every port shown in the block diagram is a contract you owe.
- In scope: encode core, decode core, encode write buffer + P2S/shift, decode S2P/pack, AXI-S handshakes, line-side handshakes, reserved-code handling.
- Out of scope: the SerDes/PMA, any clock-crossing FIFO, any framing or error-correction layer.
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)
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
| Parameter | Value |
|---|---|
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. |
| Throughput | Must sustain full-rate s_axis and m_axis (one beat per cycle when not backpressured) for any non-reserved enc_sel. |
| Latency | Not a hard constraint. Justify any pipeline depth > 4 cycles. |
LINE_W | Designer-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)
line_out, where n depends on LINE_W.Interface & Configuration Spec
Interfaces
| Side | Dir | Interface |
|---|---|---|
s_axis | in | AXI-Stream slave, tdata=512b, tkeep[63:0], tlast. Used only in ENCODE. |
m_axis | out | AXI-Stream master, tdata=512b, tkeep[63:0], tlast. Used only in DECODE. |
line_in | in | data[LINE_W-1:0], valid/ready. Used only in DECODE. |
line_out | out | data[LINE_W-1:0], valid/ready. Used only in ENCODE. |
Configuration (latched at burst start, held until TLAST)
mode— 0 = encode, 1 = decodeenc_sel[2:0]— line-encoding scheme:000NRZ ·001NRZI ·010Manchester-II ·0118b/10b100128b/130b ·1014b/5b ·110/111Reserved →err_reserved
Behavioral rules
- Payload-agnostic. No framing, no parsing — just bit-level transformation defined by the selected scheme.
- Reserved codes → assert
err_reservedand refuse the burst (your call: NACK vs hold).
The Questions
- Pick LINE_W. What's a sensible value of
LINE_W, and why? Sketch the relationship between AXI-S beat throughput, encoding ratio, andLINE_W. Where does throughput backpressure show up first if you pickLINE_Wtoo small? - Gearbox math. For a single 512-bit input beat, how many
line_outbeats 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? - 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?
- Reserved-code policy. When
enc_sel ∈ {110, 111}at the start of a burst, should the module: (a) silently drop the input, (b) deasserts_axis_treadyand hold until SW reconfigures, or (c) accept and emit a defined error pattern online_out? Defend your choice on system-integration grounds. - 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?
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?