LM-LZS-E is a lossless compression IP core for FPGA and SoC designs.
The engine compresses data to LZ4 or Snappy in hardware, emitting standards-compliant framing directly from the core — an LZ4 frame with its checksums, a Snappy raw stream, or the Snappy framing format with a masked CRC-32C per chunk. The search window is configurable across the range the formats allow, and a block that does not compress is emitted uncompressed rather than expanded.
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 | HIST_B=128, LZ4_EN=1, SNAPPY_EN=1, STORED_EN=1 | 1,327 ALM | 1,534 | 392 Kb M20K | 2 | 208.5 MHztarget 205 |
| AMD Kintex UltraScale+xcku3p-ffva676-1-e · vivado 2026.1 | HIST_B=128, LZ4_EN=1, SNAPPY_EN=1, STORED_EN=1 | 1,829 LUT | 1,088 | 13 BRAM | 3 | 311.4 MHztarget 300 |
| AMD Kintex UltraScale+xcku3p-ffva676-1-e · vivado 2026.1 | HIST_B=128, LZ4_EN=1, SNAPPY_EN=1, SNAPPY_FRAMING_EN=1, STORED_EN=1 | 2,059 LUT | 1,221 | 13 BRAM | 3 | 316.7 MHztarget 300 |
| Efinix Titanium Ti375Ti375N1156 · efinity 2026.1 | HIST_B=128, LZ4_EN=1, SNAPPY_EN=1, STORED_EN=1 | 9,840 LUT | 6,727 | 49 RAM | 3 | 216.1 MHztarget 205 |
Features
Formats
- LZ4 frame format, complete: magic, descriptor, block headers, EndMark
- Snappy raw stream format
- Snappy framing format: stream identifier, one chunk per block, masked CRC-32C
- Format selected at run time
Compression
- Configurable search window from 128 bytes to 32 kB
- Configurable maximum block size
- Stored-block fallback — a block that does not compress is emitted uncompressed, so output never exceeds input by more than framing
- xxHash-32 checksums for the LZ4 frame: header, per block and content
Reliability
- Optional SECDED error correction on the search memory
- A non-correctable error abandons the stream rather than emitting corrupt output
Integration
- AMBA AXI4-Lite control, AXI4-Stream in and out
- Independent input and output widths
- Two delivery tops: complete AXI product, or bare compressor for a custom fabric
- ANSI C driver, UVM RAL, IP-XACT, SystemRDL register description
Applications
- Storage and filesystem compression offload
- Network and RPC payload compression
- Log and telemetry reduction at the source
- Database page and column compression
- Firmware and configuration image packing
Block diagram
Interfaces
| Interface | Type | Width | Carries |
|---|---|---|---|
s_axil | AXI4-Lite slave | 32-bit | capability, control, command, status, error pair, counters, stream_len |
s_axis | AXI4-Stream sink | IN_W, tkeep, tlast | the uncompressed stream |
m_axis | AXI4-Stream source | OUT_W, tkeep, tlast | the compressed stream |
irq | level | 1-bit | completion and error events |
Snappy requires the uncompressed length before the first byte. That format's preamble
is a varint carrying the length and is emitted ahead of any compressed data, so
stream_len is written before the stream starts. LZ4 does not need it — its frame
carries sizes after the fact.
Throughput
This core has one block engine, and its measured steady-state rate is published with the measured results on this page. The architecture's ceiling is below one input byte per clock and the reason is structural rather than a tuning matter: a scan position and a verified byte each cost a clock and they are different clocks, so a byte that is scanned and then extended through is paid for twice.
An integrator whose budget needs more throughput instantiates more than one engine, with an input scheduler and in-order output reassembly above them. The measured clock census behind the figure — the proportion of cycles spent in extension, scan, sequence handover and bank refusal — is published alongside it, so the ceiling can be checked rather than taken on trust.
cnt_in, cnt_out and cnt_cycles let a host measure the achieved rate on its own
traffic.
Compression ratio
The ratio is not a register. It is cnt_in divided by cnt_out, computed by the
driver over whatever window matters. A ratio reported by hardware is a number rounded at
a moment the hardware chose.
Ratios measured against the reference software encoders at their default settings, on named corpora, are published with the measured results with the corpus, the window and the block size stated.
Configuration
| Parameter | Type | Effect |
|---|---|---|
HIST_B | elaboration | search window in bytes, 128 to 32768 — the parameter that moves area most |
MAX_BLOCK | elaboration | maximum block size |
IN_W, OUT_W | elaboration | stream widths, independent |
LZ4_EN, SNAPPY_EN, STORED_EN | elaboration | formats and the stored-block path |
SNAPPY_FRAMING_EN | elaboration | the Snappy framing layer |
CHECKSUM_EN, ECC_EN | elaboration | xxHash-32 checksums, search-memory SECDED |
| format select | run time | LZ4 or Snappy |
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, across the window ladder so the area cost of a larger window is visible. 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 — and the specification of the encoding |
| 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 |