建设项目环境影响登记表备案系统网站百度优化插件
目录
- 1、前言
- 2、硬件电路解析
- SDI摄像头
- Gv8601a单端转差
- GTX解串
- SDI解码
- VGA时序恢复
- YUV转RGB
- 图像输出
- FDMA图像缓存
- HDMI输出
- 3、工程1详解:无缓存输出
- 4、工程2详解:缓存3帧输出
- 5、上板调试验证并演示
- 6、福利:工程代码的获取
1、前言
FPGA实现SDI视频编解码目前有两种方案:
一是使用专用编解码芯片,比如典型的接收器GS2971,发送器GS2972,优点是简单,比如GS2971直接将SDI解码为并行的YCRCB,缺点是成本较高,可以百度一下GS2971的价格;
另一种方案是使用FPGA实现编解码,利用FPGA的GTP/GTX资源实现解串,优点是合理利用了FPGA资源,GTP/GTX资源不用白不用,缺点是操作难度大一些,对FPGA水平要求较高。
本文详细描述了FPGA纯verilog解码SDI视频的实现设计方案,工程代码编译通过后上板调试验证,文章末尾有演示视频,可直接项目移植,适用于在校学生做毕业设计、研究生项目开发,也适用于在职工程师做项目开发,可应用于医疗、军工等行业的数字成像和图像传输领域;
提供完整的、跑通的工程源码和技术支持;
工程源码和技术支持的获取方式放在了文章末尾,请耐心看到最后;
本设计提供两套vivado工程;
一是SDI 1080P@30Hz帧视频输入解码后,无缓存直接HDMI 1080P@30Hz帧输出;
二是SDI 1080P@30Hz帧视频输入解码后,缓存3帧后HDMI 1080P@60Hz帧输出;
关于SDI的理论知识部分,可自行搜索一下,很多大佬讲得很详细,也可以参考我之前写的文章:点击查看:SDI解码详解
2、硬件电路解析
硬件电路连接如下:
SDI摄像头
我用到的SDI摄像头输出视频分辨率1080P@30Hz;根据不同相机有所区别;
Gv8601a单端转差
Gv8601a起到均衡 EQ 功能,这里选用Gv8601a是因为抄袭了Xilinx官方的板子,当然也可以用其他型号器件。
GTX解串
GTX负责解串,将原始SDI视频解为20位的并行数据,我的板子是K7,所以用GTX,如果是A7的板子则用GTP,这里使用GTX并没有调用IP,而是直接调用GTXE2_CHANNEL和GTXE2_COMMON源语,这一点可谓将Xilinx的GTX资源用到了极致水平,值得好好品读,其实调用IP无非也就是把调用源语变得界面化而已,直接调用源语或许理解更为深刻,这一点,在市面上的所谓FPGA教程里都学不到。
SDI解码
调用SMPTE-SDI IP核实现,GTX只是将高速串行数据解为了并行,但并没有解析SDI协议,SMPTE-SDI IP核则完成了SDI协议的解码,去掉了SDI协议中的数据包信息和控制信息,解析出有效的视频数据,详细的SMPTE-SDI IP核接口定义请参考官方的使用手册;
VGA时序恢复
此模块的作用就是解码恢复出hs、vs以及de信号,即恢复正常的VGA视频时序;
要恢复正常的VGA视频时序,首先得看懂下面这张图:
根据这张表即可恢复出图像时序,具体看代码,这里一两句话实在讲不清楚,如果要完全讲明白,写5本书都搓搓有余;
YUV转RGB
这里就简单了,YUV4:4:4转RGB8:8:8,几条公式和几行代码的事儿,属于低端操作;
至此,SDI解码过程就完成了,接下来就是图像输出过程;
图像输出
图像输出有两种通路
一种是无缓存直接输出,这种方式的优点是没有延迟,适用于做图传的项目,缺点是不能对图像进行其他处理了;
另一种是缓存输出,这种方式的优点是可以平衡和同步后端的接收,比如后端接收不过来时就可以缓存几帧再输出;另外,如果还需要对图像进行其他处理时也需要缓存,适用于做图像处理的项目,缺点是输出有延迟,根据设置可以延迟多帧,本设计是延迟3帧;
既然需求是多样的,所以我们直接做两个工程。
FDMA图像缓存
我常用的FDMA数据缓存架构,详情请参考我之前的文章:点击查看:FDMA图像缓存
HDMI输出
纯verilog代码实现HDMI发送,输出时序1920x1080P,输出帧率由输入HDMI时钟决定;
HDMI输出顶层接口如下:
module helai_hdmi_out(input clk_hdmi ,input clk_hdmix5 ,input reset_n ,input i_vga_hs ,input i_vga_vs ,input i_vga_de , input [23:0] i_vga_rgb , output o_hdmi_clk_p ,output o_hdmi_clk_n ,output [2: 0] o_hdmi_data_p,output [2: 0] o_hdmi_data_n
);
3、工程1详解:无缓存输出
开发板:Xilinx Kintex7开发板;
开发环境:Vivado2019.1;
输入:SDI摄像头,分辨率1080p@30帧;
输出:HDMI,分辨率1080p@30帧;
工程代码架构如下:
顶层源码如下:
module helai_sdi_decode_2023(input I_SDI_2_N ,input I_SDI_2_P , input SDI_GTX_CLK_148_5_N , // MGT REFCLKs 148.5 MHz clockinput SDI_GTX_CLK_148_5_P , input SDI_GTX_CLK_148_35_P, // MGT REFCLKs 148.35 MHz clockinput SDI_GTX_CLK_148_35_N,output HDMI_CLK_P ,output HDMI_CLK_N ,output [2:0] HDMI_DATA_P ,output [2:0] HDMI_DATA_N );wire o_vout_clk ;
wire o_vout_hs ;
wire o_vout_vs ;
wire o_vout_de ;
wire [23:0] o_vout_rgb ; wire clk_hdmi ;
wire clk_hdmix5;
wire hdmi_rstn ;helai_sdi_driver u_helai_sdi_driver(.I_SDI_2_N (I_SDI_2_N ),.I_SDI_2_P (I_SDI_2_P ), .O_SDI_2_N (),.O_SDI_2_P (), .SDI_GTX_CLK_148_5_N (SDI_GTX_CLK_148_5_N ), // MGT REFCLKs 148.5 MHz clock.SDI_GTX_CLK_148_5_P (SDI_GTX_CLK_148_5_P ), .SDI_GTX_CLK_148_35_P(SDI_GTX_CLK_148_35_P), // MGT REFCLKs 148.35 MHz clock.SDI_GTX_CLK_148_35_N(SDI_GTX_CLK_148_35_N),.o_vout_clk (o_vout_clk ),.o_vout_hs (o_vout_hs ),.o_vout_vs (o_vout_vs ),.o_vout_de (o_vout_de ),.o_vout_rgb (o_vout_rgb )
);clk_wiz_1 clk_hdmi (.clk_hdmi(clk_hdmi), // output clk_hdmi.clk_hdmi_clkx5(clk_hdmix5), // output clk_hdmi_clkx5.locked(hdmi_rstn), // output locked.clk_in1(o_vout_clk) // input clk_in1
); helai_hdmi_out(.clk_hdmi (clk_hdmi ),.clk_hdmix5 (clk_hdmix5 ),.reset_n (hdmi_rstn ),.i_vga_hs (o_vout_hs ),.i_vga_vs (o_vout_vs ),.i_vga_de (o_vout_de ), .i_vga_rgb (o_vout_rgb ), .o_hdmi_clk_p (HDMI_CLK_P ),.o_hdmi_clk_n (HDMI_CLK_N ),.o_hdmi_data_p(HDMI_DATA_P),.o_hdmi_data_n(HDMI_DATA_N)
);
endmodule
资源消耗和功耗预估如下:
4、工程2详解:缓存3帧输出
开发板:Xilinx Kintex7开发板;
开发环境:Vivado2019.1;
输入:SDI摄像头,分辨率1080p@30帧;
输出:HDMI,分辨率1080p@60帧;
工程BD如下:
工程代码架构如下:
顶层源码如下:
module helai_sdi_decode_2023(input clk_27m ,input I_SDI_2_N ,input I_SDI_2_P , input SDI_GTX_CLK_148_5_N , // MGT REFCLKs 148.5 MHz clockinput SDI_GTX_CLK_148_5_P , input SDI_GTX_CLK_148_35_P, // MGT REFCLKs 148.35 MHz clockinput SDI_GTX_CLK_148_35_N,input i_uart_rx , output o_uart_tx ,
// DDR3 output [12:0]DDR3_0_addr ,output [2:0] DDR3_0_ba ,output DDR3_0_cas_n ,output [0:0] DDR3_0_ck_n ,output [0:0] DDR3_0_ck_p ,output [0:0] DDR3_0_cke ,output [3:0] DDR3_0_dm ,inout [31:0] DDR3_0_dq ,inout [3:0] DDR3_0_dqs_n ,inout [3:0] DDR3_0_dqs_p ,output [0:0] DDR3_0_odt ,output DDR3_0_ras_n ,output DDR3_0_reset_n ,output DDR3_0_we_n ,output ddr3_ok ,
// HDMI_OUT output HDMI_CLK_P ,output HDMI_CLK_N ,output [2:0] HDMI_DATA_P ,output [2:0] HDMI_DATA_N );wire ui_clk_200m;
wire rst_n ;wire ud_r_0_ud_rclk ;
wire [31:0] ud_r_0_ud_rdata ;
wire ud_r_0_ud_rde ;
wire ud_r_0_ud_rvs ;
wire ud_w_0_ud_wclk ;
wire [31:0] ud_w_0_ud_wdata ;
wire ud_w_0_ud_wde ;
wire ud_w_0_ud_wvs ;wire o_vout_clk ;
wire o_vout_hs ;
wire o_vout_vs ;
wire o_vout_de ;
wire [23:0] o_vout_rgb ; wire o_vga_hs ;
wire o_vga_vs ;
wire o_vga_de ;
wire [23:0] o_vga_rgb;
wire [23:0] i_vga_rgb; wire clk_hdmi ;
wire clk_hdmix5;
wire hdmi_rstn ;assign ud_r_0_ud_rclk =clk_hdmi ;
assign ud_r_0_ud_rde = o_vga_de ;
assign ud_r_0_ud_rvs = o_vga_vs ;
assign i_vga_rgb =ud_r_0_ud_rdata[23:0];assign ud_w_0_ud_wclk =o_vout_clk;
assign ud_w_0_ud_wdata =o_vout_rgb;
assign ud_w_0_ud_wde =o_vout_de ;
assign ud_w_0_ud_wvs =o_vout_vs ; design_1 u_design_1 (.DDR3_0_addr (DDR3_0_addr ),.DDR3_0_ba (DDR3_0_ba ),.DDR3_0_cas_n (DDR3_0_cas_n ),.DDR3_0_ck_n (DDR3_0_ck_n ),.DDR3_0_ck_p (DDR3_0_ck_p ),.DDR3_0_cke (DDR3_0_cke ),.DDR3_0_dm (DDR3_0_dm ),.DDR3_0_dq (DDR3_0_dq ),.DDR3_0_dqs_n (DDR3_0_dqs_n ),.DDR3_0_dqs_p (DDR3_0_dqs_p ),.DDR3_0_odt (DDR3_0_odt ),.DDR3_0_ras_n (DDR3_0_ras_n ),.DDR3_0_reset_n (DDR3_0_reset_n ),.DDR3_0_we_n (DDR3_0_we_n ),.ddr3_ok (ddr3_ok ), .clk_in1_0 (clk_27m ),.ui_clk_0 (ui_clk_200m ),.rst_n (rst_n ),.ud_r_0_ud_rclk (ud_r_0_ud_rclk ),.ud_r_0_ud_rdata(ud_r_0_ud_rdata),.ud_r_0_ud_rde (ud_r_0_ud_rde ),.ud_r_0_ud_rvs (ud_r_0_ud_rvs ),.ud_w_0_ud_wclk (ud_w_0_ud_wclk ),.ud_w_0_ud_wdata(ud_w_0_ud_wdata),.ud_w_0_ud_wde (ud_w_0_ud_wde ),.ud_w_0_ud_wvs (ud_w_0_ud_wvs )
); helai_sdi_driver u_helai_sdi_driver(.I_SDI_2_N (I_SDI_2_N ),.I_SDI_2_P (I_SDI_2_P ), .O_SDI_2_N (),.O_SDI_2_P (), .SDI_GTX_CLK_148_5_N (SDI_GTX_CLK_148_5_N ), // MGT REFCLKs 148.5 MHz clock.SDI_GTX_CLK_148_5_P (SDI_GTX_CLK_148_5_P ), .SDI_GTX_CLK_148_35_P(SDI_GTX_CLK_148_35_P), // MGT REFCLKs 148.35 MHz clock.SDI_GTX_CLK_148_35_N(SDI_GTX_CLK_148_35_N),.o_vout_clk (o_vout_clk ),.o_vout_hs (o_vout_hs ),.o_vout_vs (o_vout_vs ),.o_vout_de (o_vout_de ),.o_vout_rgb (o_vout_rgb )
);clk_wiz_1 clk_hdmi (.clk_hdmi(clk_hdmi), // output clk_hdmi.clk_hdmi_clkx5(clk_hdmix5), // output clk_hdmi_clkx5.locked(hdmi_rstn), // output locked.clk_in1(o_vout_clk) // input clk_in1
); video_timing_control vga(.i_clk (clk_hdmi ), .i_rst_n(hdmi_rstn), .i_rgb (i_vga_rgb),.o_hs (o_vga_hs ),.o_vs (o_vga_vs ),.o_de (o_vga_de ),.o_rgb (o_vga_rgb)
);helai_hdmi_out(.clk_hdmi (clk_hdmi ),.clk_hdmix5 (clk_hdmix5 ),.reset_n (hdmi_rstn ),.i_vga_hs (o_vga_hs ),.i_vga_vs (o_vga_vs ),.i_vga_de (o_vga_de ), .i_vga_rgb (o_vga_rgb ), .o_hdmi_clk_p (HDMI_CLK_P ),.o_hdmi_clk_n (HDMI_CLK_N ),.o_hdmi_data_p(HDMI_DATA_P),.o_hdmi_data_n(HDMI_DATA_N)
);
endmodule
FPGA逻辑资源消耗和功耗如下:
5、上板调试验证并演示
输出演示视频如下:
FPGA纯verilog解码SDI视频
6、福利:工程代码的获取
福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:私,或者文章末尾的V名片。
网盘资料如下: