FPGA纯verilog实现Gzip数据压缩deflate算法,提供工程源码和技术支持

news2024/12/28 4:36:22

目录

  • 1、前言
  • 2、我这儿已有的FPGA压缩算法方案
  • 3、FPGA Gzip数据压缩功能和性能
  • 4、FPGA Gzip数据压缩设计方案
    • 输入输出接口描述
    • 数据处理流程
      • LZ77压缩器
      • 哈夫曼编码
      • 输出缓存
    • 数据输出说明
    • 特殊说明
  • 5、vivado仿真
  • 6、vivado工程
  • 7、上板调试验证
    • FPGA开发板测试
    • 本zip算法对比于评估
  • 8、福利:工程代码的获取

1、前言

说到FPGA的应用,数据压缩算法的硬件加速器无疑是经典应用之一,用FPGA压缩图片、视频、普通数据等都具有并行执行的独特优势,关于FPGA压缩图片和视频,我之前的博客有相关设计,今天讲讲用FPGA实现对普通数据进行Gzip压缩算法的实现;本工程源码的功能就是:基于 FPGA 的流式的 GZIP (deflate 算法) 压缩器,用于通用无损数据压缩:输入原始数据,输出标准的 GZIP 格式,即常见的 .gz / .tar.gz 文件的格式。

2、我这儿已有的FPGA压缩算法方案

我这里有图像的JPEG解压缩、JPEG-LS压缩、H264编解码、H265编解码以及其他方案,后续还会出更多方案,我把他们整合在一个专栏里面,会持续更新,专栏地址:
直接点击前往

3、FPGA Gzip数据压缩功能和性能

3.1:纯 RTL 设计,在各种 FPGA 型号上都可以部署;
3.2:极简流式接口 :AXI-stream 输入接口:
3.2.1:数据位宽 8-bit ,每周期可输入 1 字节的待压缩数据;
3.2.2:输入的长度 ≥32 字节的 AXI-stream 包 (packet) 会被压缩为一个独立的 GZIP 数据流;
3.2.3:输入的长度 <32 字节的 AXI-stream 包会被模块丢弃 (不值得压缩) ,不会产生任何输出;
3.3:AXI-stream 输出接口:
4.3.1:每个输出的 AXI-stream 包是一个独立的 GZIP 数据流 (包括GZIP文件头和文件尾);
3.4:性能:
如果输出接口无反压,也即 o_tready 始终=1,则输入接口也一定无反压,也即 o_tready 始终=1 (即使在最坏情况下) ;
这是我刻意设计的,好处是当外部带宽充足时,本模块可跑在确定且最高的性能下 (输入吞吐率=时钟频率);
在 Xilinx Artix-7 xc7a35ticsg324-1L 上时钟频率跑到 128MHz (输入性能为 128MByte/s);
资源:在 Xilinx FPGA 上约占 8200×LUT 和 25×BRAM36K;
支持几乎完整的 deflate 算法 :
依照 deflate 算法规范 (RFC1951 [1]) 和 GZIP 格式规范 (RFC1952 [2]) 编写;
deflate block:
小于 16384 字节的输入 AXI-stream 包当作一个 deflate block;
大于 16384 字节的输入 AXI-stream 包分为多个 deflate block , 每个不超过 16384;
LZ77 游程压缩:
搜索距离为 16383 , 范围覆盖整个 deflate block;
使用哈希表匹配搜索,哈希表大小=4096;
动态 huffman 编码:
当 deflate block 较大时,建立动态 huffman tree ,包括 literal code tree 和 distance code tree;
当 deflate block 较小时,使用静态 huffman tree 进行编码;
由于支持了以上功能,本设计的压缩率:
接近 7ZIP 软件在“快速压缩”选项下生成的 .gz 文件;
显著大于其它现有的开源 deflate 压缩器。见 对比和评估;
依照 GZIP 的规定,生成原始数据的 CRC32 放在 GZIP 的末尾,用于校验;
不支持的特性:
不构建动态 code length tree , 而是使用固定 code length tree ,因为它的收益代价比不像动态 literal code tree 和 distance code tree 那么高;
不会为了提高压缩率而动态调整 deflate block 大小,目的是降低复杂度;

4、FPGA Gzip数据压缩设计方案

FPGA Gzip数据压缩设计方案框图如下:
在这里插入图片描述

输入输出接口描述

输入接口是标准的 8-bit 位宽的 AXI-stream slave;
在这里插入图片描述
i_tvalid 和 i_tready 构成握手信号,只有同时=1时才成功输入了1个数据 (如上图);
i_tdata 是1字节的输入数据;
i_tlast 是包 (packet) 的分界标志,i_tlast=1 意味着当前传输的是一个包的末尾字节,而下一个传输的字节就是下一包的首字节。每个包会被压缩为一个独立的 GZIP 数据流;

输出接口是标准的 32-bit (4字节) 位宽的 AXI-stream master;
o_tvalid 和 o_tready 构成握手信号,只有同时=1时才成功输出了1个数据 (类似输入接口) ;
o_tdata 是4字节的输出数据。按照 AXI-stream 的规定,o_tdata 是小端序,o_tdata[7:0] 是最靠前的字节,o_data[31:24] 是最靠后的字节;
o_tlast 是包的分界标志。每个包是一个独立的 GZIP 数据流;
o_tkeep 是字节有效信号,具体如下:
o_tkeep[0]=1 意为 o_tdata[7:0] 有效,否则无效;
o_tkeep[1]=1 意为 o_tdata[15:8] 有效,否则无效;
o_tkeep[2]=1 意为 o_tdata[23:16] 有效,否则无效;
o_tkeep[3]=1 意为 o_tdata[31:24] 有效,否则无效;
当输出包的字节数量不能整除4时,只有在包的末尾 (o_tlast=1 时) ,o_tkeep 才可能为 4’b0001, 4’b0011, 4’b0111;
其余情况下 o_tkeep=4’b1111;

数据处理流程

LZ77压缩器

详见计方案框图;
输入数据首先给到LZ77压缩器进行数据处理;
关于LZ77压缩器原理,推荐参考阅读下面这篇博客:
点击直接阅读LZ77压缩器
LZ77压缩器在代码中的位置如下:可以看到,由纯verilog代码实现;
在这里插入图片描述

哈夫曼编码

输入数据经过LZ77压缩器后,分两路给到哈夫曼树动态构建和哈夫曼编码模块,哈夫曼编码模块内部定义了一个二维数组作为缓存使用,关于哈夫曼编码原理,推荐参考阅读下面这篇博客:
点击直接阅读哈夫曼编码
哈夫曼树动态构建和哈夫曼编码模块在代码中的位置如下:可以看到,由纯verilog代码实现;
在这里插入图片描述
哈夫曼编码模块内部定义的二维数组作为缓存使用代码位置如下:
在这里插入图片描述

输出缓存

输出缓存其实质就是一个AXIS接口的FIFO,将输出数据缓存以作AXIS格式输出,这个很简单,在代码中的位置如下:可以看到,由纯verilog代码实现;
在这里插入图片描述

数据输出说明

AXI-stream 接口输出的是满足 GZIP 格式标准的数据,将每个 AXI-stream 包的数据独立存入一个 .gz 文件后,这个文件就可以被众多压缩软件 (7ZIP, WinRAR 等) 解压。
需要提示的是: .gz 是 GZIP 压缩文件的概念。更为人熟知的是 .tar.gz 。实际上 TAR 是把多个文件打包成一个 .tar 文件,然后再对这一个 .tar 文件进行 GZIP 压缩得到 .tar.gz 文件。如果对单个文件进行压缩,则可以不用 TAR 打包,直接压缩为一个 .gz 。例如 data.txt 压缩为 data.txt.gz;例如,AXI-stream 接口上一共成功握手了 987 次,最后一次握手时 o_tlast=1 ,说明这 987 拍数据是一个独立的 GZIP 流。假设最后一次握手时 o_tkeep=4’b0001 ,则最后一拍只携带1字节的数据,则该 GZIP 流一共包含 986×4+1=3949 字节。如果将这些字节存入 .gz 文件,则应该:

.gz 文件的第1字节 对应 第1拍的 o_tdata[7:0]
.gz 文件的第2字节 对应 第1拍的 o_tdata[15:8]
.gz 文件的第3字节 对应 第1拍的 o_tdata[23:16]
.gz 文件的第4字节 对应 第1拍的 o_tdata[31:24]
.gz 文件的第5字节 对应 第2拍的 o_tdata[7:0]
.gz 文件的第6字节 对应 第2拍的 o_tdata[15:8]
.gz 文件的第7字节 对应 第2拍的 o_tdata[23:16]
.gz 文件的第8字节 对应 第2拍的 o_tdata[31:24]
......
.gz 文件的第3945字节 对应 第986拍的 o_tdata[7:0]
.gz 文件的第3946字节 对应 第986拍的 o_tdata[15:8]
.gz 文件的第3947字节 对应 第986拍的 o_tdata[23:16]
.gz 文件的第3948字节 对应 第986拍的 o_tdata[31:24]
.gz 文件的第3949字节 对应 第987拍的 o_tdata[7:0]

特殊说明

如果输出接口无反压,也即 o_tready 始终=1,则输入接口也一定无反压,也即 o_tready 始终=1 (即使在最坏情况下) ;借助这个特性,如果外部带宽充足稳定,以至于可以保证 o_tready 始终=1 ,则可忽略 i_tready 信号,任何时候都可以让 i_tvalid=1 来输入一个字节。
deflate 算法需要用整个 deflate block 来构建动态 huffman 树,因此本模块的端到端延迟较高:
当输入 AXI-stream 包长度为 32~16384 时,只有在输入完完整的包 (并还需要过一段时间后) ,才能在输出 AXI-stream 接口上拿到对应的压缩包的第一个数据。
当输入 AXI-stream 包长度 >16384 时,每完整地输入完 16384 字节 (并还需要过一段时间后),才能在输出 AXI-stream 接口上拿到对应的有关这部分数据的压缩数据,当输入 AXI-stream 包长度为 <32 时,模块内部会丢弃该包,并且不会针对它产生任何输出数据。
要想获得高压缩率,尽量让包长度 >7000 字节,否则模块很可能不会选择使用动态 huffman ,且 LZ77 的搜索范围也会很受限。如果需要压缩的数据在逻辑上是很多很小的 AXI-stream 包,可以在前面加一个预处理器,把它们合并为一个几千或几万字节的大包来送入gzip_compressor_top;

5、vivado仿真

vivado仿真设计框图如下:
在这里插入图片描述
vivado仿真代码架构如下:
在这里插入图片描述
其中随机数据包生成器 (tb_random_data_source.v) 会4种生成特性不同的数据包 (字节概率均匀分布的随机数据、字节概率非均匀分布的随机数据、随机连续变化的数据、稀疏数据) ,送入待测模块 (helai_gzip_compressor) 进行压缩,然后 tb_save_result_to_file 模块会把压缩结果存入文件,每个独立的数据包存入一个独立的 .gz 文件。

tb_print_crc32 负责计算原始数据的 CRC32 并打印,注意:待测模块内部也会计算 CRC32 并封装入 GZIP 数据流,这两个 CRC32 计算器是独立的 (前者仅用于仿真,用来验证待测模块生成的 CRC32 是否正确)。你可以自行将仿真打印的 CRC32 与 生成的 GZIP 文件中的 CRC32 进行对比。
vivado仿真打印结果如下:
在这里插入图片描述
仿真波形如下:
在这里插入图片描述
仿真后生成的zip压缩文件保存的路径如下:
在这里插入图片描述
然后可以将其解压打开看。。。

6、vivado工程

开发板FPGA型号:Xilinx–>xc7k325tffg676-2;
输入:python测试数据,串口输入;
输入:zip压缩后的数据,串口输出;
应用:zip数据压缩应用;

vivado工程设计框图如下:
在这里插入图片描述
该 FPGA 工程接收串口数据,将数据送入 GZIP 压缩器,并将得到的 GZIP 压缩数据流用串口发出去 (串口格式: 波特率115200, 无校验位)。
在电脑 (上位机) 上,编写了一个 python 程序,该程序的执行步骤是:
从电脑的磁盘中读入一个文件 (用户通过命令行指定文件名);
列出电脑上的所有串口,用户需要选择 FPGA 对应的串口 (如果只发现一个串口,则直接选择这个串口);
将该文件的所有字节通过串口发给 FPGA;同时接收 FPGA 发来的数据;
将接收到的数据存入一个 .gz 文件,相当于调用 FPGA 进行了文件压缩;
最终,调用 python 的 gzip 库解压该 .gz 文件,并与原始数据相比,看是否相等。如果不相等则报错;
由于串口速度远小于 gzip_compressor_top 能达到的最高性能,因此该工程仅仅用于展示。要想让Gzip数据压缩模块发挥更高性能,需要用其它高速通信接口。
python代码放置目录如下:
在这里插入图片描述
工程代码架构如下:
在这里插入图片描述
FPGA资源消耗如下:
在这里插入图片描述
在其他FPGA上移植后的资源消耗如下:
在这里插入图片描述

7、上板调试验证

FPGA开发板测试

FPGA 工程烧录后,在python 目录下打开命令行,运行以下命令:

python fpga_uart_gz_file.py <需要压缩的文件名>

例如,运行以下命令来压缩 raw.hex :

python fpga_uart_gz_file.py raw.hex

如果压缩成功,会得到 raw.hex.gz 文件,且不会打印报错信息。

本zip算法对比于评估

为了评估本设计的综合表现,我们将本设计与以下 3 种 deflate 压缩方案进行对比:
1:软件压缩:在电脑上运行 7ZIP 压缩软件
配置:压缩格式=gzip,压缩等级=极速压缩,压缩方法=Deflate,字典大小=32KB,单词大小=32;

2:HDL-deflate算法:
一个基于 FPGA 的 deflate 压缩器/解压器,它的压缩器只使用了 LZ77 + 静态 huffman,而没有使用动态 huffman 。在 LZ77 中,它没有使用哈希表来搜索。
在本测试中,使用了它的压缩器的最高配置 (也是默认配置) : LOWLUT=False, COMPRESS=True , DECOMPRESS=False , MATCH10=True ,FAST=True;

3:HT-Deflate-FPGA算法:
一个基于 FPGA 的多核的 deflate 压缩器,它也只使用了 LZ77 + 静态 huffman ,而没有使用动态 huffman 。在 LZ77 中,它使用了哈希表来搜索,这与本设计相同。
这个设计是面向 Xilinx-AWS 云平台的多核并行的 deflate 压缩,性能很高,但占用的资源较多。相比之下,HDL-deflate 和本设计都是单核的压缩,面向嵌入式应用设计。
由于这个设计并没有提供上手仿真的工程,很难快速run起来,因此这里没有让它参与实际测试对比,只对它进行定性对比。

4:对比平台:
软件压缩运行在个人电脑 (Intel Core i7-12700H, 16GB DDR4) 上;
本设计和 HDL-deflate 都部署在Xilinx Artix-7 开发板 上;

5:测试数据
用于对比的待压缩数据是 python 目录下的 raw.hex ,它的大小是 512kB;

6:对比结果
下表展示对比结果:在指标中,↑代表越大越好, ↓代表越小越好;
在这里插入图片描述
HT-Deflate-FPGA 的压缩率应该高于 HDL-deflate ,但低于本设计。这是根据它所支持的算法特性分析出来的。

8、福利:工程代码的获取

福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:文章末尾的V名片。
网盘资料如下:
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/835238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JDK版本差异】Optional.requireNonNullElseGet在JAVA8中的替代表述

Objects.requireNonNullElseGet 是 Java 9 引入的方法&#xff0c;不在 Java 8 中可用。但是&#xff0c; 可以使用 Java 8 的一些功能来模拟类似的效果。 快速查阅 JDK9以上表述&#xff1a; this.principalFactory Objects.requireNonNullElseGet(principalFactory, Defau…

如何测出 Scratch 的指令反应时间

相信看了标题&#xff0c;你一定会很吃惊&#xff0c;你会觉得scratch不是没有反应时间吗&#xff1f; 但其实不是&#xff0c;这也是我偶然间发现的&#xff0c;这期的内容较少&#xff0c;对你的技术涨幅很小&#xff0c;但可以当作娱乐来看 其实就7个代码&#xff0c;但看着…

(自控原理)线性系统的时域分析法

目录 一、系统时间响应的性能指标 1、典型输入信号 2、动态性能与稳态性能 二、一阶系统的时域分析 1、一阶系统的数学模型 2、一阶系统的单位阶跃响应 三、二阶系统的时域分析 1、二阶系统的数学模型 2、二阶系统的单位阶跃响应 3、欠阻尼二阶系统的动态过程分析 4…

redis原理 5:同舟共济 —— 事务

为了确保连续多个操作的原子性&#xff0c;一个成熟的数据库通常都会有事务支持&#xff0c;Redis 也不例外。Redis 的事务使用非常简单&#xff0c;不同于关系数据库&#xff0c;我们无须理解那么多复杂的事务模型&#xff0c;就可以直接使用。不过也正是因为这种简单性&#…

国内版ChatGPT平替

想体验的朋友可以去微信搜索小程序 “ robot buddy ”

2024年杭州电子科技大学MEM项目招生信息全面了解

2024年全国管理类硕士联考备考已经到了最火热的阶段&#xff0c;不少考生开始持续将注意力集中在备考的规划中&#xff01;杭州达立易考教育整合浙江省内的MEM目信息&#xff0c;为大家详细梳理了相关报考参考内容&#xff0c;方便大家更好完成择校以及针对性的备考工作。本期为…

【Spring Boot】Thymeleaf模板引擎 — Thymeleaf表达式

Thymeleaf表达式 本节介绍Thymeleaf的各种表达式&#xff0c;通过一些简单的例子来演示Thymeleaf的表达式及用法。 1.变量表达式 变量表达式即获取后台变量的表达式。使用${}获取变量的值&#xff0c;例如&#xff1a; <p th:text"${name}">hello</p>…

Windows Server 2012 R2 安装 Oracle RAC 11g R2

Windows Server 2012 R2 安装 Oracle RAC 11g R2 环境准备安装系统设置虚拟网络配置虚拟机网卡开机进行系统配置关闭防火墙设置网络系统高级设置修改注册表修改计算机名称设置账户控制RAC1 和 RAC2 的磁盘共享修改 hosts同步时间在 RAC1 RAC2 DATA 中安装 .net3.5在 DATA 中搭建…

windows下redis的下载和安装

文章目录 1 下载2 打开解压文件&#xff0c;可以看到以下内容3 使用命令进行安装和注册redis到window服务4 查看服务 1 下载 https://github.com/MicrosoftArchive/redis/releases 2 打开解压文件&#xff0c;可以看到以下内容 3 使用命令进行安装和注册redis到window服务 …

一文学透设计模式——抽象工厂模式

创建者模式 抽象工厂模式 概念 抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这是很多地方对于抽象工厂模式的描述&#xff0c;说实话感觉不是特别好懂。…

ResNet-残差网络一

文章目录 残差网络深度网络退化残差结构残差网络对比测试plain net VS residual net不同的shrotcut connection残差网络增加层数 著名的残差网络主要是在两片论文里提出&#xff1a; Deep Residual Learning for Image RecognitionIdentity Mappings in Deep Residual Networks…

yolov8在rknn(rv1109/1126)模型转换、量化移植过程

续&#xff1a;rv1109/1126 rknn 模型量化过程_CodingInCV的博客-CSDN博客 Yolov8简介 yolov8是比较新的目标检测模型&#xff0c;根据论文和开源项目的报告&#xff0c;相对使用比较广泛的yolov5提升还比较明显。 yolov8与yolov5相比&#xff0c;结构上的主要区别是将C3结构…

hutool Sm2加解密-自定义公钥私钥

代码 首先说结论&#xff0c;hutool 的SM2对象的公钥私钥是不关联的&#xff0c;你可以存自己的私钥和别人的公钥&#xff0c;这样解密的时候只要协商好就能用了&#xff0c;以下是调换公钥私钥的加解密案例 公钥格式 04公钥x公钥y //使用自定义的公钥私钥生成sm2Testpubli…

android资深工程师如何分析system_server异常

Android系统中的System Server负责管理许多关键功能&#xff0c;例如进程管理、电源管理等。如果System Server出现异常&#xff0c;可能会导致系统重启或部份功能失效。作为Android资深工程师&#xff0c;分析System Server的异常状况时&#xff0c;考虑以下步骤&#xff1a;查…

晶澳转债上市价格预测

晶澳转债 基本信息 转债名称&#xff1a;晶澳转债&#xff0c;评级&#xff1a;AA&#xff0c;发行规模&#xff1a;89.603077亿元。 正股名称&#xff1a;晶澳科技&#xff0c;今日收盘价&#xff1a;31.71元&#xff0c;转股价格&#xff1a;38.78元。 当前转股价值 转债面值…

我做了一个JPA Specification的优化

目录 一、参考二、概述流程效果感受 三、实现原理AST树结构AstNode主要结构 把表达式解析成AstAst 解析成 JPA Specification 三、项目地址四、目前阶段的总结 一、参考 如何搞一个支持自定义函数和变量的四则运算的抽象语法树出来 二、概述 这是一个可以优化生成Specificati…

Android SystemServer中Service的创建和启动方式(基于Android13)

Android SystemServer创建和启动方式(基于Android13) SystemServer 简介 Android System Server是Android框架的核心组件&#xff0c;运行在system_server进程中&#xff0c;拥有system权限。它在Android系统中扮演重要角色&#xff0c;提供服务管理和通信。 system …

Pycharm中修改注释文本的颜色(详细设置步骤)

下面是在Pycharm中设置注释文本颜色的详细步骤&#xff1a; 下面是修改前后对比&#xff1a; 修改前注释行的颜色&#xff1a; 修改后注释行的颜色&#xff1a; 以上就是Pycharm中修改注释文本颜色的详细步骤&#xff0c;希望能帮到你&#xff01;

pve安装dsm7.2,并启用照片同步

目录 1.文件准备 2. 创建虚拟机 3. 编译引导文件 4. 群晖安装 5. 安装Photos和mmfpeg 6. 安装手机APP 之前安装了pve版本的dsm6.2了&#xff0c;近期换硬盘&#xff0c;加上对dsm6.2的moments性能实在不满意&#xff0c;就产生尝鲜的想法&#xff0c;因为dsm7.0发布很久了…

2024年浙财MBA项目招生信息全面了解

2024年全国管理类硕士联考备考已经到了最火热的阶段&#xff0c;不少考生开始持续将注意力集中在备考的规划中&#xff01;杭州达立易考教育整合浙江省内的MBA项目信息&#xff0c;为大家详细梳理了相关报考参考内容&#xff0c;方便大家更好完成择校以及针对性的备考工作。本期…