明德扬FPGA网络班:http://www.mdy-edu.com/product/670.html
明德扬FPGA就业班:http://www.mdy-edu.com/product/672.html
在本实验中,我们在FPGA上实现了JPEG压缩和UDP以太网传输。我们的想法是从摄像机的输入端获取一个灰度帧,使用JPEG标准对其进行编码,然后通过以太网将其传输到另一台设备(如计算机),所有这些都在硬件中。该项目利用专用硬件对软件的速度,为严格模块化的设计提供严格的调度和控制逻辑。
背景
JPEG图像压缩标准是一种有损压缩标准,它使用DCT变换及其相关属性来显着减少用于表示图像的位数。编码过程涉及许多步骤,这些步骤在我们的设计中被分解为可分离的模块。此外,我们在系统中引入了以太网和UDP通信实现。
离散余弦变换
离散余弦变换(DCT)可以将有限长度的数字序列表示为不同频率的余弦项的总和,类似于傅立叶变换如何将周期函数表示为不同频率的正弦之和。DCT,更具体地DCT-II,由于其高能量压缩特性而用于图像压缩。简而言之,大多数能量(或原始信息)可以压缩成较小数量的比特。
要执行JPEG压缩的第一步,首先将所讨论的图像分割为8x8像素块。然后将二维DCT应用于每个8×8块。2-D DCT的结果表示在与矩阵的索引相对应的离散频率处的原始块的空间频率信息。在变换之后,左上角系数给出空间DC信息,而右下角系数给出最高空间频率(在水平和垂直方向上)信息。空间频率表示如下图所示。
注意,左上角元素在水平和垂直方向上具有较低的空间频率,而右下角元素具有较高的频率。利用DCT,大部分原始信息可以从较低频率系数(靠近左上角的系数)重建,因为这些系数中的高能量压缩。另外,人类视觉系统对高频空间内容中的错误不太敏感。这两个事实一起意味着低频系数中的误差对于人类而言将比高频元素中的误差更明显。
2-D DCT操作是可分离的,这意味着它可以通过在被分析的块上应用1-D DCT两次来获得。首先在块的每一行上执行1-D变换,然后在行方向变换的结果的列上执行1-D变换。可以使用以下等式获得1-D DCT系数:
其中k是系数的索引。对于JPEG变换的情况,N总是等于8,因为变换被应用于图像的8×8块。
量化
一旦将DCT应用于8×8块,就将量化因子应用于系数。简而言之,该步骤将系数与具有与能量密度相关的步长离散化。低频系数采用较小的步长进行量化,因此与使用较大步长量化的系数相比,误差较小。如此量化低频系数以减少量化误差的可能性。较高的频率被赋予较大的步长,从而降低了不太重要的元件的精度。这是压缩过程中的有损步骤。
虽然JPEG压缩标准没有指定要使用的量化矩阵,但这是建议的矩阵之一。为了量化2-D DCT的结果,将每个系数除以上述矩阵的适当值并舍入为最接近的整数。
Zig-Zag测序
在量化之后,2-D矩阵被重新排列成1-D阵列。以一种方式读取元件,首先给出具有高能量密度的系数。测序以Z字形方法完成,使得系数以增加的空间频率顺序排列。使用这种方法,更重要的系数出现在系列的前面,而不太重要的系数出现在后面。
可变大小的游程编码
假设使用较大的步长量化高频系数,那些系数为零的可能性远高于低频系数。这将零值系数的候选者分组,允许我们假设一系列零的可能性。
JPEG标准的主要压缩源是可变大小和行程长度编码。压缩中的该步骤使用霍夫曼编码和可变长度编码的组合。每个非零系数被转换为可变长度的位串或代码。代码包含其编号和长度的信息(即0与00不同)。
如前所述,之字形组织增加了连续零的可能性,特别是在阵列末尾附近。为了避免发送连续的零,将前一个零的游程长度编码到每个非零系数的平移中。每个非零系数被编码为可变长度代码,以及指示前一个零运行的“标题”霍夫曼代码,以及VL代码的长度。像素转换表和Huffman表显示 在这里。这些转换表仅适用于图像的亮度值。由于我们的系统完全处理灰度图像。对于用于彩色图像的色度值存在不同的转换方案。
由于无论长度如何,霍夫曼码都是唯一可识别的,因此可以在不知道长度的情况下始终识别新的非零值的零游程和大小。然后,使用由霍夫曼给出的大小,可以提取以下VL比特并将其转换回适当的非零系数。除非先前已知代码的长度,否则VL代码不是唯一可识别的。
DC与AC
DC系数的编码与AC系数略有不同。由于DC系数永远不会具有前面的零(零不在块之间延续),因此霍夫曼码仅反映VL码的长度。
DC系数也以差分编码方法编码。由于DC值基本上是8×8块中所有像素的平均值,因此连续块之间的DC系数将具有相似(或相同)的高可能性。不是编码绝对像素值,而是将该值编码为与前一个块的DC系数的差值。例如,如果图像的前三个连续块分别具有127,127和128的DC系数,则代码将分别编码为127,0,1(图像中第一个块的DC系数为与0区分,意味着给出其实际值)。
零运行和块结束指示
请注意,上面链接的转换表没有容纳零运行时间超过15的代码。这是因为在遇到15个零后,会插入15个运行的指示符,而不是跟踪更长的流。前面零运行超过15的任何非零值都将转换为此指标,然后是正常代码,其中零运行是原始15 之后的零数。指标显示在下表中零运行15的情况,VL大小为零。
由霍夫曼代码1010指示的每个块的结尾。该代码不用于任何其他转换可能性,因此它用于向解码器指示已到达块的结尾。
以太网络
在开放系统互连参考模型(OSI模型)中,以太网位于链路层和物理层。在物理层,以太网描述了电线应如何互连。在链路层,以太网指定应如何格式化以太网帧以及应如何传送帧。以太网上的交付仅是最佳尝试,这意味着以太网尝试尽可能地传递消息,但不能保证交付。
由于以太网本质上是一种广播协议,可能有许多设备连接到同一物理线路,因此一次只能广播一个设备。如果线路发生冲突,以太网控制器能够检测到冲突并执行随机退避。随机退回仅意味着在碰撞检测时,在尝试另一次发送之前等待随机的时间量。以太网帧由前导码,帧起始分隔符,MAC目的地,MAC源,以太网类型,有效载荷和校验和组成。
前导码和帧起始分隔符用于指定以太网帧正在启动。可以使用其媒体访问控制(MAC)地址寻址每个以太网控制器。因此,每个以太网帧还包含MAC目的地和源地址。Ethertype指定解码有效负载时使用的协议。有效载荷是实际数据,最后的校验和是确保以太网帧头是正确的。
用户数据报协议/ Internet协议
用户数据报协议(UDP)和因特网协议(IP)分别驻留在传输层和网络层的OSI模型的下两层。UDP / IP协议与以太网一样,不保证可靠的数据包接收,只保证尽力传输。IP协议的主要目的是在链路层之上提供一个抽象层。这样,如果底层链路层不是以太网,则不需要更改应用级软件。IP协议通过具有另一对源和目标地址,分段偏移,报头校验和以及有效载荷中使用的协议来提供此抽象。
IP校验和计算为所有16位报头值的一个补码和的一个补码。驻留在IP帧中的UDP协议实际上告诉网络堆栈数据有多大以及目标端口是什么。UDP是应用程序级别之前的最后一个抽象层。
设计
代码大量模块化,输出馈入连续模块的输入。编码的步骤分为以下步骤,每个步骤在单独的模块中实现:1-D DCT,2-D DCT /量化,Z形组织,VL转换,霍夫曼转换和比特流构造。该系统考虑256x256图像,但可以扩展以分析更多像素。数据流图如下所示:
通过仅考虑灰度成像,我们使用了彩色系统所需的内存量和处理能力的三分之一。对于处理彩色图像的系统,需要将上述整个压缩处理单独地应用于每个颜色通道。我们最初通过仅选择每个像素的绿色值来获得灰度图像,而不是执行从RGB到YUV的转换。这种简化并不完全正确,但项目的重点不在于图像,而在于压缩,因此我们不需要在转换操作上浪费额外的计算。
1-D DCT
使用快速算法实现一维DCT,该算法需要八个周期才能完成。该算法主要需要连续添加输入和得到的和,在三个中间步骤期间发生五次乘法。该算法产生DCT结果,该结果根据实际DCT结果的某些因子进行缩放。然而,可以在量化步骤中考虑比例,从而产生正确量化的变换矩阵。系数的比例因子如下:
算法数据流如下图所示。
该模块是完全流水线的,这意味着每个周期都可以输入新的输入,8个周期后输出新的输出。这允许模块更快速地处理块。
二维DCT
2-D DCT是可分离的操作,这意味着它可以通过在8x8块的每一行上应用1-D DCT,然后将其应用于8x8块的列来获得。这允许我们使用流水线1-D DCT非常快速地执行2-D DCT,方法是将块的行馈送到1-D模块中8个周期,然后获得结果并将这些列反馈到同一模块中。
在将结果写回存储器之前,还在该2-D模块中执行量化。由于算法的缩放与量化相结合的方式,整个操作仅需要对2-D算法结果进行移位。
锯齿形
通过简单地以适当的顺序读取内存中的值来执行之字形组织。块的元素存储在直接从图像中的像素坐标获得的地址中。来自存储器的该输出以每周期一个像素的速率直接馈送到转换器中。
VL和RL翻译
使用查找表完成从像素的量化值到可变长度代码的转换。该表包含代码的值和长度(以位为单位)。然后将这两个值发送给霍夫曼翻译器。霍夫曼转换器采用前面的零个数和系数代码的大小。这两个数字被馈送到另一个查找表,该表格将霍夫曼代码作为非零系数的“标题”。
DC和AC系数的VL码转换完全相同。DC和AC转换的差异在于Huffman代码,因此只有Huffman查找表需要区分DC和AC像素。
比特流建设
VL和RL转换器的输出被馈送到比特流构造器,该构造器连接适当的比特以形成JPEG比特流。该模块基本上需要跟踪进入的霍夫曼和VL代码的大小,并将它们适当地转发到以太网发送器的16位FIFO。
硬件以太网控制器
硬件以太网控制器用于初始化DM9000A控制器芯片,将数据包推送到DM9000A,从DM9000A获取接收数据,以及从DM9000A接收中断。Controller主要由Adam Shapiro编写,但由我们调试。
Controller分为两个独立的状态机,一个处理来往DM9000A的命令(包括中断),另一个处理发送和接收序列。
发送序列包括:
1)等待输入FIFO不为空。将第一个值存储为有效负载中的字节数。
2)告诉硬件控制器将存储多少字节,包括以太网报头。
3)将以太网帧作为数据发送到DM9000A。
4)将有效载荷发送到DM9000A。
5)等待传输通过中断完成。返回空闲状态。
因为我们不使用接收函数,所以我们不会在这里描述接收序列。
UDP包装器
UDP Wrapper利用Adam Shapiro的硬件DM9000A以太网控制器生成有效的UDP / IP报头,然后发送有效载荷数据。使用先进先出数据结构(FIFO),UDP包装器首先获得有效载荷中的总字节数,然后一次获得16位的有效载荷。Wrapper使用状态机执行以下步骤以发送单个UDP数据包:
1)等待输入FIFO不为空。将第一个值存储为有效负载中的字节数。
2)告诉硬件控制器将存储多少字节,包括UDP / IP报头。
3)将以太网帧作为数据发送到硬件控制器。
4)将IP头作为数据发送到硬件控制器。在校验头发送之前计算IP校验和。
5)将UDP头作为数据发送到硬件控制器。
6)将所有数据发送到硬件控制器。
因为UDP包装器的目的是允许DE2与通过以太网直接连接的单个计算机通信,所以许多值被硬编码到Verilog中。硬编码值包括目标和源MAC地址,目标和源IP地址以及目标端口。这四个硬编码值都设置为广播地址,FF:FF:FF:FF:FF:FF用于MAC地址,255.255.255.255用于IP地址。目标端口被硬编码为任意31373.其他值(例如IP头校验和)是动态计算的,因为标头值不一定每次都相同。完成后,控制寄存器复位并返回等待状态。
内存使用情况
此项目中仅使用M4K块。使用M4K块是因为它们的速度和易用性,因为它的想法是拥有一个实时JPEG压缩器。第一个存储器模块保存直接从摄像机馈送的值,最多可容纳16行256个像素(每个1个字节)。16行用于始终具有8行缓冲区,我们在其上执行DCT,8行准备好被摄像机覆盖。
在DCT的输出端是另一个256x16元件M4K模块。该存储器模块的写入端馈送到Z字形单元,该Zig-zag单元通过随时间适当地设置地址来简单地读出Z字形图案中的值。
最后,在比特流构造函数的末尾,有第三个FIFO作为以太网发送器的传输FIFO。理想情况下,这个内存模块应该尽可能大,并且由于JPEG压缩应该显着减少图像的位数,我们可以将整个图像存储在M4K块中(我们无法对原始像素进行处理)流)。
文档
作为注释,存储器的地址通常是这样的格式,即高位代表y坐标,低位代表所讨论像素的x坐标。这些地址的长度可能因模块而异,因为某些存储器模块具有不同大小的输入/输出,具体取决于应用。
dct_algorithm
输入:clk,reset,in0,...,in7
输出:out0,...,out7
该模块运行快速算法来计算1-D DCT。该模块完全流水线化,在读取输入后8个周期输出长度为8的DCT结果。该模块具有22位固定点(8位十进制位)输入和输出。虽然存储器中的像素存储为8位值,但是数字扩展到22以避免溢出并且在变换的中间步骤中保持一些精度与小数值。
要从算法结果中获得实际DCT,必须将相应的输出乘以设计部分中给出的s值。然而,在我们的系统中跳过该步骤,因为它与量化操作中所需的乘法相结合。
问题:这个模块实现相当简单,因为它实际上只有五次乘法和一系列的增加。流水线操作也很简单,但原始模块尝试使用移位和求和作为乘法的替代,这有时会产生输出值的问题(但并非总是如此)。一旦我们意识到没有其他模块需要乘数,我们决定废弃尝试的优化。
dct2d
输入:clk,reset,q,currentX,currentY
输出:wren,rdaddress,wraddress
该模块调度正在馈送到流水线1-D DCT算法的输入和输出。输出rdaddress确定应从内存中读取的值以获取适当的行。要读取的块的时间表取决于相机将哪个X和Y值写入存储器(由currentX和currentY指定)。
输入q是64位值,表示来自存储器的8个像素的行。该输入被分割并馈送到dct_algorithm模块的适当的8个输入中。中间矩阵(在对行执行1-D DCT之后)存储在寄存器中,以便保持更多位以获得更高的精度。然后,这些寄存器作为列反馈到1-D DCT,以完成2-D DCT。然后适当地缩放这些输出以考虑算法的比例因子,并量化系数。然后将量化值存储回单独的M4K块。
问题:调度何时锁存寄存器值和分配新输入是该模块的最大问题。M4K模块对数据可用时有特定的时序要求。此外,存储到寄存器和存储到存储器也需要一些调整。
蜿蜒
输入:clk,启用
输出:rden,latch_dc,rdaddress
该模块简单地控制馈送到存储器模块的读取地址,以Z字形图案读出矩阵,如背景技术部分所述。latch_dc输出告诉顶级模块从内存中锁存输出值,因为它是该特定8x8块的DC值。如背景技术部分所述,需要对DC系数进行差分编码方案。
translate_to_vl
输入:clk,enable,value
outputs:size,code
该模块将量化的像素值转换为适当的可变长度代码。两个输出是代码(必须作为固定长度值输出)和一个大小组件,它告诉下一个转换模块从代码输出中取出哪些位。这只是一个实现为查找表。对于DC和AC系数,该转换是相同的。
translate_to_huffman
输入:clk,enable,dc,size,zero_run
输出:huffman_length ,huffman
该模块是另一个查找表,并给出霍夫曼代码,该代码充当每个非零像素的前缀。所述直流输入告诉该模块是否是编码的DC值,否则它假定它编码的AC值。如前所述,这两种类型的系数具有不同的转换方法(特别是因为DC不考虑零运行)。
霍夫曼代码简单地描述了前面的零的数量,以及值的VL代码的大小。霍夫曼本身也是可变长度的,因此长度也必须是输出,因此比特流模块可以提取适当的比特。注意:该模块的huffman_length输出实际上比实际长度小1,因此该信号实际上表示16位霍夫曼信号中的最高有效位(从0开始计数时)。该模块嵌入在比特流缓冲器中,如下所述。
bitstream_buffer
输入:clk,enable,size,code
outputs:next_transmit,new_stream
缓冲器从霍夫曼转换器和可变长度转换器获取输出,并将适当的位馈送到最终将要发送的比特流缓冲器。VL转换器提供大小和代码,它们被馈送到Huffman转换器(嵌入在该模块中)。该模块具有64位的位缓冲区,适当数量的可变长度转换位流入其中。该模块记录64位寄存器的实际有效位数并需要传输。
该模块还处理写入传输FIFO。一旦比特流缓冲器具有至少16位,则写入线被断言并且16位被适当地存储到FIFO中。该模块还处理零运行跟踪,并在发现数组中没有更多非零系数时附加块结束(EOB)代码。
问题:该模块在翻译过程中遇到的问题最多。首先,为超过15个元素的运行附加零运行信息的过程被证明有点困难,因为需要考虑字节结束。我们不能盲目地插入一个15运行指示器,因为零串可能完全运行到块的末尾,在这种情况下,需要附加EOB代码而没有任何15运行指示器。另外,来自翻译模块的输入和输出的调度以及任何条件信号在某种程度上难以协调。
udp_wrapper
输入:clk,reset,enet_int,enet_data,udp_clk,udp_wr,udp_data,halt
outputs:enet_clk,enet_rst_n,enet_cs_n,enet_cmd,enet_wr_n,enet_rd_n,udp_full
该模块被馈送到其FIFO中,并围绕输入的数据构建UDP / IP报头,并使用状态机将其发送到硬件以太网控制器。
要使用您必须:
1)将有效负载的字节数作为第一个数据。
2)推送有效载荷的字节。
在有效负载中拥有正确的字节数非常重要,因为Wrapper使用此数字来保持其状态机与驱动Wrapper的外部状态机同步。
大多数MAC地址和IP值也是硬编码的。虽然更改MAC地址很容易,但更改IP值还包括更改添加到IP层校验和的数量。
目前,如果仍然需要从FIFO读取但FIFO为空,则包装器存在问题。它将继续从空FIFO读取并将垃圾数据提供给硬件控制器。
完全爆发后,UDP包装器每秒最多可传输8兆字节。
结果
该项目的结果证明了概念,但整个实施无法在示范截止日期前完成。
JPEG压缩器模块化为几个交互部分,在模拟中工作(在一定程度上)。对于可变数据(即从摄像机接收帧时),未完全验证准确度。压缩器出自执行动态JPEG视频编码的最初想法。因此,硬件能够以大致等于Terasic相机馈送原始像素的速率编码成JPEG比特流。我们对可以执行压缩的速度感到满意,但是当我们尝试在FPGA上将所有模块组合在一起时,我们无法通过以太网获得任何结果。
通过完成两个较小的系统,我们能够证明设计的中间部分几乎正确运行:
1。从M4K块读取16x8像素块(灰度),在每个8x8块上应用2-D DCT,并发送通过以太网使用UDP的结果。
2.从M4K块读取8x8字节块(表示2-D DCT的结果),对块应用VL / RL编码,生成转换的比特流,并使用UDP通过以太网传输结果。
这两个实验证明我们的压缩机部件工作,但将所有模块组合在一起的控制逻辑是错误的。由于在实验中从存储器读取的块是预加载的,因此结果是先前已知的并且与通过以太网传输的字节进行比较。这些实验中的第二个显示了我们的霍夫曼翻译代码中的一个错误。运行时间超过15的零计数不能正常运行,但非零值的转换是正确的(对于特定的测试流)。此外,由于实验是使用已知输入(数据流开始时的静态存储器)执行的,因此完全删除了项目的相机方面。
系统问题
为流程创建的模块非常严格且严格定时。此外,模块之间的通信很少,即使在一个时钟周期内,也几乎没有空间容易出现控制信号时序差异。虽然这使得处理速度非常快,但这意味着控制逻辑必须非常具体并且没有松弛。模块之间的控制信号依赖于预先知道定时的模块,而不是通信以确定控制。从一开始就应该更仔细地规划整个系统的架构。允许模块之间的通信可能已经解决了一些控制逻辑问题。由于严格的要求,我们无法使控制逻辑正确,这意味着我们无法使系统(从原始图像到传输的比特流)正常运行。
以太网替代品
在我们让以太网控制器完全工作之前,考虑进行通信的硬件以太网控制器有两种替代方案:
1。使用NiosII在软件中实现以太网,NiosII是一种嵌入式处理器,可以使用c代码对软件进行编程。事实证明这种方法太慢了,在我们还在考虑实时压缩的时候被抛弃了。如果不需要实时,则可以使用Nios,因为帧(压缩,未压缩或两者)可以存储到某种形式的存储器中并通过软件缓慢传输。
2.通过RS-232传输比特流。在我们决定取消对项目的实时约束之后考虑这一点,并且完全被视为以太网的替代方案。然而,一旦我们发现我们能够完成足够的以太网控制器和UDP包装器,这个想法就被抛弃了。
结论
虽然我们无法运行最终所需的系统,但我们确实创建了可用于各种其他应用程序的可用功能模块。UDP包装器和硬件以太网控制器在任何网络通信项目中都非常有用。流水线1-D DCT算法可用于信号和图像处理项目,因为DCT-II是一种广泛用于其他应用的变换。该项目虽未按预期完成,但仍被认为是成功的。我们对成品设计的结果和功能感到满意。