本设计是一种verilog代码实现的低功耗H.264/AVC解码器(baseline ),硬件ASIC设计,不使用任何GPP/DSP等内核,完全有可综合的verilog代码实现,没有任何ip,可在Xilinx、Intel、国产FPGA间任意移植;
本文详细描述了纯verilog实现设计方案,可直接项目移植,适用于在校学生做毕业设计、研究生项目开发,也适用于在职工程师做项目开发,可应用于医疗、军工等行业的视频解码领域;提供完整的、跑通的工程源码和技术支持;
本设计只做到了仿真层面并验证通过,并没有实际应用于真实项目,但理论上讲是可行的,作为研究FPGA实现H.264的学习性参考资料很完美,既有verilog源码又有仿真文件,作为工程应用可能需要自行搭建使用平台,我也可以提供技术支持;
H.264和AVC是两个不同机构定义的不同名称,其实质是同一个东西,也就是视频压缩和解压的算法,由于叫的人多了,也就习惯叫H.264了,不必纠结这些名称性的东西。
关于H.264编解码的理论知识,请看官自行搜索,CSDN也有很多大佬写得很详细,我就不写这部分了,我们详细讲讲用verilog实现的过程和本工程的组成结构。
本工程及其源码即有自己写的一部分,也有网络公开渠道获取的一部分(包括CSDN、Xilinx官网、Altera官网等等),若大佬们觉得有所冒犯,请私信批评教育;基于此,本工程及其源码仅限于读者或粉丝个人学习和研究,禁止用于商业用途,若由于读者或粉丝自身原因用于商业用途所导致的法律问题,与本博客及博主无关,请谨慎使用。。。
本H.264/AVC解码器(baseline)具有以下特点:
一个字:牛逼,表现如下:
1:Verilog-HDL实现,没有任何IP核,学习性和阅读性达到天花板;
2:目前只支持QCI分辨率(176X144)的实时H.264/AVC解码,但可修改代码以适应更高分辨率视频;
3:由于使用verilog代码实现,所以具有流水线操作和并行操作的特点,解码速度直接拉满;
4:帧间和帧内自适应流水线设计;
5:分层内存组织设计,减少外部内存访问;
6:低开销的帧内预测单元;
7:优化的帧间预测单元(运动补偿);
8:最大频率200MHz,可提供高达980kMB/s的吞吐量;
9:QCIF 30fps的实时解码仅需约1.5MHz时钟,只有169k个逻辑门,实测功耗低至293µW;
10:移植性达到天花板,Xilinx、Altera和国产FPGA之间自由移植;
以Virtex-4 xc4vlx200的FPGA实现本解码器的资源消耗如下:
用专用ASIC实现本解码器的资源消耗如下:
vivado工程设计架构如下:
代码运行仿真流程如下:
1:使用10个300帧的QCIF视频序列作为输入源,它们由JM94软件编码产生位TXT文件,生成的模拟视频流文件放在仿真文件夹下,如图:
2:测试视频RAM:负责将读取视频流文件送到H264解码器进行解码,该模块由H264解码器的视频流控制模块控制,只作为仿真应用,在实际使用中并不需要;模块很简单,源码如下:
module Beha_BitStream_ram(
input clk ,
input BitStream_ram_ren ,
input [16:0] BitStream_ram_addr,
output reg [15:0] BitStream_ram_data
);
reg [15:0] BitStream_ram[0:`Beha_Bitstream_ram_size];
initial
begin
$readmemh("akiyo300_1ref.txt",BitStream_ram);
end
always @ (posedge clk)
if (BitStream_ram_ren == 0) BitStream_ram_data <= #2 BitStream_ram[BitStream_ram_addr];
endmodule
3:H264解码器:当测试视频RAM深度填充至一半时,开始发送测试视频流给到H264解码器;H264解码器由视频流控制器和数据重构解析器组成;如下:
其中的4×4/16×16混合流水线机制如下:
关于H264解码器具体代码级详情,请联系我看源码,不是我不愿具体写,而是代码量实在有点大,写不完也装不下,如果具体写的话估计得出5本书。。。
H264解码器顶层接口如下:
module helai_h264_decode (
input clk ,
input reset_n ,
input [15:0] BitStream_buffer_input,
input pin_disable_DF ,
input freq_ctrl0 ,
input freq_ctrl1 ,
output BitStream_ram_ren ,
output [16:0] BitStream_ram_addr ,
output [5:0] pic_num ,
//---ext_frame_RAM0---
output ext_frame_RAM0_cs_n ,
output ext_frame_RAM0_wr ,
output [13:0] ext_frame_RAM0_addr ,
input [31:0] ext_frame_RAM0_data ,
//---ext_frame_RAM1---
output ext_frame_RAM1_cs_n ,
output ext_frame_RAM1_wr ,
output [13:0] ext_frame_RAM1_addr ,
input [31:0] ext_frame_RAM1_data ,
output [31:0] dis_frame_RAM_din ,
output slice_header_s6
);
4:乒乓RAM:设置了两个乒乓RAM,一个用来缓存一帧数据,作为H264解码器解析用,比如帧预测;另一个作为输出显示的缓存;当其中一个RAM完成自己的任务时,H264解码器控制二者角色互换;RAM顶层接口如下:
H264解码器通过片选信号ext_frame_RAM0_cs_n达到控制二者乒乓效果;
module ext_frame_RAM0_wrapper (
input clk ,
input reset_n ,
input ext_frame_RAM0_cs_n,
input ext_frame_RAM0_wr ,
input [13:0] ext_frame_RAM0_addr,
input [31:0] dis_frame_RAM_din ,
input [5:0] pic_num ,
input slice_header_s6 ,
output reg [31:0] ext_frame_RAM0_data
);
5:视频输出
H264解码器解码后的视频颜色空间为YUV4:2:0,需要转换为YUV4:4:4或者RGB8:8:8再输出显示,框图如下:
总体代码架构如下:
下面我们重点看看H264解码器代码级组成:
视频流控制器完整verilog代码组成如下:
数据重构解析器完整verilog代码组成如下:
关于H264解码器具体代码级详情,请联系我看源码,不是我不愿具体写,而是代码量实在有点大,写不完也装不下,如果具体写的话估计得出5本书。。。
仿真后,H264解码器会输出两个文件,文件位置如下:
h264_display.txt:存放H264解码器输出的像素数据,可以将此文件转成图片显示;
h264_MB_output_debug.txt:存放H264解码器输出的debug数据,可清晰看到输出过程,如下:
福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:私,或者文章末尾的V名片。
网盘资料如下: