LM-LZS-D is a lossless decompression IP core for FPGA and SoC designs.
The engine decompresses LZ4 and Snappy streams in hardware, with a 64 kB history window and a datapath producing up to eight decompressed bytes per clock. It accepts the LZ4 frame format complete, the Snappy raw stream format, and the Snappy framing format with its masked CRC-32C per chunk. Format detection is automatic.
The core is delivered as vendor-neutral SystemVerilog and builds from one source on AMD, Altera and Efinix devices. It includes AMBA AXI interfaces and a register map, and ANSI C drivers are provided for fast integration into the target platform.
Measured FPGA results
Product top, out of context, constrained at the target clock. AMD and Efinix report LUTs, Altera reports ALMs; the two are never combined.
| Device | Configuration | Logic | FF | Memory | DSP | Fmax |
|---|---|---|---|---|---|---|
| Altera Agilex 3A3CW135BM16AE6S · quartus-pro 26.1.1 | DP_W=64, LZ4_EN=1, SNAPPY_EN=1 | 4,527 ALM | 2,905 | 512 Kb M20K | 0 | 165.1 MHztarget 165 |
| AMD Kintex UltraScale+xcku3p-ffva676-1-e · vivado 2026.1 | DP_W=64, LZ4_EN=1, SNAPPY_EN=1 | 6,309 LUT | 2,024 | 16 BRAM | 0 | 254.2 MHztarget 250 |
| AMD Kintex UltraScale+xcku3p-ffva676-1-e · vivado 2026.1 | DP_W=64, LZ4_EN=1, SNAPPY_EN=1, SNAPPY_FRAMING_EN=1 | 7,208 LUT | 2,139 | 16 BRAM | 0 | 250.7 MHztarget 250 |
| Efinix Titanium Ti375Ti375N1156 · efinity 2026.1 | DP_W=64, LZ4_EN=1, SNAPPY_EN=1 | 12,646 LUT | 5,540 | 64 RAM | 1 | 232.1 MHztarget 220 |
Features
Formats
- LZ4 frame format: magic, descriptor, block sizes, optional content size, header and content checksums, EndMark, skippable and legacy frames
- Snappy raw stream: preamble varint, literal and copy elements
- Snappy framing: stream identifier, the full chunk table including all four reserved ranges, and the masked CRC-32C per chunk
- Automatic format detection, or pinned to one format by register
Checksums
- xxHash-32 for LZ4 header, block and content checksums
- CRC-32C, masked, for Snappy framing chunks
Engine
- Configurable datapath of up to 8 decompressed bytes per clock
- History window of up to 64 kB, byte-banked for unaligned copies at full rate
- Optional SECDED error correction on the history window
Error reporting
- Errors carry a class and a code — which check failed, not merely that one did
- The error flag travels on the output stream as well as in a register
- A dictionary frame is refused by name rather than decoded against an absent dictionary
Integration
- AMBA AXI4-Lite control, AXI4-Stream in and out
- Independent input and output widths
- Two delivery tops: complete AXI product, or bare decompressor for a custom fabric
- ANSI C driver, UVM RAL, IP-XACT, SystemRDL register description
Applications
- Storage and filesystem decompression offload
- Network and RPC payload decompression
- Log and telemetry ingestion
- Firmware and configuration image expansion
- Database page and column decompression
Block diagram
Interfaces
| Interface | Type | Width | Carries |
|---|---|---|---|
s_axil | AXI4-Lite slave | 32-bit data, 7-bit address | capability, control, command, status, error pair, counters |
s_axis | AXI4-Stream sink | IN_W, tkeep, tlast | the compressed stream |
m_axis | AXI4-Stream source | OUT_W, tkeep, tlast | the decompressed stream |
m_axis_tuser[0] | source | 1-bit | the error flag, travelling with the data |
irq | level | 1-bit | completion and error events |
The error flag rides on the output stream. A decompressor that detects a bad stream
has usually already emitted part of it, so a consumer reading only a register would have
to poll between beats to know whether the bytes it just took were good. tuser[0] lets a
sink discard a failed stream without a bus access and without a race.
Error reporting
Errors carry a class and a code, so a log line names the check that failed:
| Class | Codes include |
|---|---|
| coding | not a recognised stream, bad version, reserved field set, malformed Snappy preamble, trailing bytes |
| size | declared size impossible, block size disagreement, content size mismatch |
| crc | LZ4 header / block / content checksum, Snappy framing chunk CRC-32C |
| truncation | stream ended mid-element |
| unsupported | dictionary requested |
Throughput
throughput = DP_W bytes x f_clk for copy-dominated streams
DP_W is configurable up to 8 bytes per clock. Achieved rate depends on the stream's mix
of literals and matches; cnt_in, cnt_out and cnt_cycles let a host measure it on its
own traffic rather than trusting a datasheet figure.
Configuration
| Parameter | Type | Effect |
|---|---|---|
DP_W | elaboration | decompressed bytes per clock, up to 8 |
IN_W, OUT_W | elaboration | stream widths, independent of each other |
HIST_KB | elaboration | history window size, up to 64 kB |
LZ4_EN, SNAPPY_EN | elaboration | formats compiled in |
SNAPPY_FRAMING_EN | elaboration | the Snappy framing layer |
CHECKSUM_EN, ECC_EN | elaboration | checksum verification, window SECDED |
| format select | run time | automatic, or pinned |
Resources and performance
Resource utilisation and maximum clock frequency for each target device are measured out of context and published per target in the measured results on this page. AMD and Efinix rows report LUTs; Altera rows report ALMs, and the two are never combined.
Deliverables
| Item | Contents |
|---|---|
| RTL | parameterised SystemVerilog, vendor-neutral |
| Model | bit-accurate C++ model |
| Registers | SystemRDL source plus six generated exports |
| Verification | UVM RAL, formal property wrappers, corpus and vector drivers |
| Software | ANSI C reference driver with generated header and JSON |
| Packaging | IP-XACT, IEEE 1685-2022 |
| Implementation | runnable flow script per FPGA vendor, file list, SDC |
| Documentation | integration guide |