FPGA纯verilog代码解码CameraLink视频,附带工程源码和技术支持

Posted 9527华安

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FPGA纯verilog代码解码CameraLink视频,附带工程源码和技术支持相关的知识,希望对你有一定的参考价值。

目录

1、CameraLink视频协议简介

CameraLink的详细不必深究,作为FPGA数据采集者而言,我们只需关心他的传输时序和传输协议。
CameraLink相机输出分三种模式:
Base模式:称之为基本模式或初级模式,通常配置为一个CameraLink芯片和一根电源线;有1个标准CameraLink接口,对应的是1对时钟差分信号和4对数据差分信号;解码后的数据位宽为281=28位;分为ABC三个Port;
Medium模式:中级模式,配置为两个CameraLink芯片和一根电源线;有2个标准CameraLink接口,对应的是2对时钟差分信号和8对数据差分信号;解码后的数据位宽为28
2=56位;分为ABCDEF六个Port;
Full模式:高级模式,配置为3个CameraLink芯片,两根电源线;有2个标准CameraLink接口,对应的是3对时钟差分信号和12对数据差分信号;解码后的数据位宽为28*3=84位;分为ABCDEFGH八个Port;

CameraLink差分串行输入转单端并行:以Base模式为例
以Base模式下,CameraLink输出1对时钟差分信号和4对数据差分信号,如下图:

2、FPGA实现CameraLink视频解码

解串的过程可以参考Xilinx给的参考设计,使用Xilinx的ISERDESE2和IDELAYE2实现,由于代码过于复杂,在这里实在说不清楚,只给出解串顶层的端口部分,具体代码“关注并私信我”要源码。

解串部分实现了差分穿行到单端并行的转换,输出像素时钟pixel_clk和数据data_out;
同样,解码部分也只给出解串顶层的端口部分,具体代码“关注并私信我”要源码。

这部分实现了解码CameraLink的功能,输出行、场、de、像素数据;
最后给出整个CameraLink解码代码的顶层如下:
后面还细节地给出了解码后的时序图。

`timescale 1ps/1ps
module helai_CameraLink_rx #(
	// Parameters
	parameter integer	CAMERALINK_MODE = 3,	// Set the CameraLink mode. Base-->1  Medium-->2  Full-->3
	parameter integer	CAMERALINK_CHAL = 4		// Set the number of data lines per channel=4
)
(
	input				                            delay_clk_200m,	    // Clock for input delay control: 200MHz or 300Hz clk is needed
	input				                            reset_n       ,		// Active low reset

	input	[CAMERALINK_MODE-1:0]		            i_clk_in_p    ,		// Input from LVDS clock receiver pin
	input	[CAMERALINK_MODE-1:0]		            i_clk_in_n    ,		// Input from LVDS clock receiver pin
	input	[CAMERALINK_MODE*CAMERALINK_CHAL-1:0]	i_data_in_p   ,		// Input from LVDS data pins
	input	[CAMERALINK_MODE*CAMERALINK_CHAL-1:0]	i_data_in_n   ,		// Input from LVDS data pins
//decode video_clk and video_data output
	output				                            o_pixel_clk   ,		// Pixel clock output
	// Chip X signals
	output			                                o_xLVAL       ,		// Line Valid, active high
	output			                                o_xFVAL       ,		// Frame Valid, active high
	output			                                o_xDVAL       ,		// Data Valid, active high. Maybe always zero.
	output	[7:0]	                                o_PortA       ,		// Camera Link interface Port A , total 8 ports
	output	[7:0]	                                o_PortB       ,		// Camera Link interface Port B , total 8 ports
	output	[7:0]	                                o_PortC       ,		// Camera Link interface Port C , total 8 ports
	// Chip Y signals
	output			                                o_yLVAL       ,		// Line Valid, active high
	output			                                o_yFVAL       ,		// Frame Valid, active high
	output			                                o_yDVAL       ,		// Data Valid, active high. Maybe always zero.
	output	[7:0]	                                o_PortD       ,		// Camera Link interface Port D , total 8 ports
	output	[7:0]	                                o_PortE       ,		// Camera Link interface Port E , total 8 ports
	output	[7:0]	                                o_PortF       ,		// Camera Link interface Port F , total 8 ports
	// Chip Z signals
	output			                                o_zLVAL       ,		// Line Valid, active high
	output			                                o_zFVAL       ,		// Frame Valid, active high
	output			                                o_zDVAL       ,		// Data Valid, active high. Maybe always zero.
	output	 [7:0]	                                o_PortG       ,		// Camera Link interface Port G , total 8 ports
	output	 [7:0]	                                o_PortH       		// Camera Link interface Port H , total 8 ports	
);
 
wire [CAMERALINK_MODE*CAMERALINK_CHAL*7-1:0]	data_out;			// Serial to parallel data output
//**********差分转单端,然后串并转换,由Xilinx IDELAYE2 和 ISERDESE2 原语实现**********//
lvds_n_x_1to7_sdr_rx #(
	// Parameters
	.N (CAMERALINK_MODE),				// Set the number of channels
	.X (CAMERALINK_CHAL)				// Set the number of data lines per channel
)
CameraLink_sdr(
	.delay_refclk_in(delay_clk_200m),	// Clock for input delay control: 200MHz or 300Hz clk is needed
	.reset_n        (reset_n       ),	// Active low reset
	.clk_in_p       (i_clk_in_p    ),	// Input from LVDS clock receiver pin
	.clk_in_n       (i_clk_in_n    ),	// Input from LVDS clock receiver pin
	.data_in_p      (i_data_in_p   ),	// Input from LVDS data pins
	.data_in_n      (i_data_in_n   ),	// Input from LVDS data pins
	.data_out       (data_out      ),	// Serial to parallel data output
	.pixel_clk      (o_pixel_clk   )	// Pixel clock output
);
//**********差分转单端,然后串并转换,由Xilinx IDELAYE2 和 ISERDESE2 原语实现**********//


//*****************根据CameraLink的数据格式,解码出行、场、de、数据*****************//
cameralink_bit_allocation_rx #(
	// Parameters
	.N (CAMERALINK_MODE),				// Set the number of channels
	.X (CAMERALINK_CHAL)				// Set the number of data lines per channel
)
CameraLink_decode(
	.data_in             (data_out),		// Parallel data input
	// Chip X signals
	.xLVAL  (o_xLVAL),		// Line Valid, active high
	.xFVAL  (o_xFVAL),		// Frame Valid, active high
	.xDVAL  (o_xDVAL),		// Data Valid, active high. Maybe always zero.
	.PortA  (o_PortA),		// Camera Link interface Port A , total 8 ports
	.PortB  (o_PortB),		// Camera Link interface Port B , total 8 ports
	.PortC  (o_PortC),		// Camera Link interface Port C , total 8 ports
	// Chip Y signals
	.yLVAL  (o_yLVAL),		// Line Valid, active high
	.yFVAL  (o_yFVAL),		// Frame Valid, active high
	.yDVAL  (o_yDVAL),		// Data Valid, active high. Maybe always zero.
	.PortD  (o_PortD),		// Camera Link interface Port D , total 8 ports
	.PortE  (o_PortE),		// Camera Link interface Port E , total 8 ports
	.PortF  (o_PortF),		// Camera Link interface Port F , total 8 ports
	// Chip Z signals
	.zLVAL  (o_zLVAL),		// Line Valid, active high
	.zFVAL  (o_zFVAL),		// Frame Valid, active high
	.zDVAL  (o_zDVAL),		// Data Valid, active high. Maybe always zero.
	.PortG  (o_PortG),		// Camera Link interface Port G , total 8 ports
	.PortH  (o_PortH)		// Camera Link interface Port H , total 8 ports
);
//*****************根据CameraLink的数据格式,解码出行、场、de、数据*****************//
//解码后的时许如下:

//              __    __    __    __    __    __    __    __    __    __    __    __    __    __    __
//o_pixel_clk__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\__/  \\ 
//                 ____________________________________________________________________________________
//o_xFVAL_________/
//                         _______________________                   _______________________
//o_xLVAL_________________/                       \\_________________/                       \\__________
//                         _______________________                   _______________________
//o_xDVAL_________________/                       \\_________________/                       \\__________
//       _________________ _______________________ _________________ _______________________                
//o_PortA___invalid_data__\\_______valid_data______\\___invalid_data__\\_______valid_data______\\_invalid_data_
//       _________________ _______________________ _________________ _______________________               
//o_PortB___invalid_data__\\_______valid_data______\\___invalid_data__\\_______valid_data______\\_invalid_data_
//       _________________ _______________________ _________________ _______________________               
//o_PortC___invalid_data__\\_______valid_data______\\___invalid_data__\\_______valid_data______\\_invalid_data_

endmodule

3、vivado工程介绍

下面提供一个CameraLink base模式的工程
开发板:Kintex7开发板;
开发环境:vivado2019.1;
输入:CameraLink摄像头,1280X1024@60Hz分辨率;
输出:HDMI,1920X1080@60Hz分辨率;
BD工程如下图:经典的FDMA三帧缓存架构,关于FDMA三帧缓存,请参考我之前写的文章点击查看:FDMA三帧缓存方案

工程代码架构如下:

最后给出工程的顶层代码如下:

module CameraLink_rx_hdmi_out(

    input        i_27m_clk     ,  // Y2 125MHz
	input        i_clk_in_p    ,
	input        i_clk_in_n    ,
	input [3:0]  i_data_in_p   ,
	input [3:0]  i_data_in_n   ,
// HDMI    
    output       HDMI_CLK_P    ,
    output       HDMI_CLK_N    ,
    output       HDMI_D2_P     ,
    output       HDMI_D2_N     ,
    output       HDMI_D1_P     ,
    output       HDMI_D1_N     ,
    output       HDMI_D0_P     ,
    output       HDMI_D0_N     ,
// 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 [0:0] DDR3_0_cs_n   ,
	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
);

helai_CameraLink_rx #(
	// Parameters
	.CAMERALINK_MODE (1),	// Set the CameraLink mode. Base-->1  Medium-->2  Full-->3
	.CAMERALINK_CHAL (4)		// Set the number of data lines per channel=4
)
CameraLink_decode(
	.delay_clk_200m(ui_clk_200m    ),	    // Clock for input delay control: 200MHz or 300Hz clk is needed
	.reset_n       (rst_n          ),		// Active low reset
	.i_clk_in_p    (i_clk_in_p     ),		// Input from LVDS clock receiver pin
	.i_clk_in_n    (i_clk_in_n     ),		// Input from LVDS clock receiver pin
	.i_data_in_p   (i_data_in_p    ),		// Input from LVDS data pins
	.i_data_in_n   (i_data_in_n    ),		// Input from LVDS data pins
	.o_pixel_clk   (vid_clk        ),		// Pixel clock output
	.o_xFVAL       (vid_vs         ),		// Frame Valid, active high
	.o_xDVAL       (vid_de         ),		// Data Valid, active high. Maybe always zero.
	.o_PortA       (vid_data[23:16]),		// Camera Link interface Port A , total 8 ports
	.o_PortB       (vid_data[15: 8]),		// Camera Link interface Port B , total 8 ports
	.o_PortC       (vid_data[ 7: 0])		// Camera Link interface Port C , total 8 ports
);
    
wire [31:0]  fdma_raddr_0 ;
wire         fdma_rareq_0 ;
wire         fdma_rbusy_0 ;
wire  [127:0]fdma_rdata_0 ;
wire         fdma_rready_0;
wire [15:0]  fdma_rsize_0 ;
wire         fdma_rvalid_0;
wire [31:0]  fdma_waddr_0 ;
wire         fdma_wareq_0 ;
wire         fdma_wbusy_0 ;
wire [127:0] fdma_wdata_0 ;
wire         fdma_wready_0;
wire [15:0]  fdma_wsize_0 ;
wire         fdma_wvalid_0;
wire         ui_clk_200m  ; 
wire         rst_n        ;
 
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   ),
    .clk_in1_0     (i_27m_clk     ),
    .ddr3_ok       (ddr3_ok       ),
    .fdma_raddr_0  (fdma_raddr_0  ),
    .fdma_rareq_0  (fdma_rareq_0  ),
    .fdma_rbusy_0  (fdma_rbusy_0  ),
    .fdma_rdata_0  (fdma_rdata_0  ),
    .fdma_rready_0 (fdma_rready_0 ),
    .fdma_rsize_0  (fdma_rsize_0  ),
    .fdma_rvalid_0 (fdma_rvalid_0 ),
    .fdma_waddr_0  (fdma_waddr_0  ),
    .fdma_wareq_0  (fdma_wareq_0  ),
    .fdma_wbusy_0  (fdma_wbusy_0  ),
    .fdma_wdata_0  (fdma_wdata_0  ),
    .fdma_wready_0 (fdma_wready_0 ),
    .fdma_wsize_0  (fdma_wsize_0  ),
    .fdma_wvalid_0 (fdma_wvalid_0 ),
    .ui_clk_0      (ui_clk_200m   ),
	.rst_n         (rst_n         )
	);

wire vid_clk        ;
wire vid_vs         ;
wire vid_de         ;
wire [23:0] vid_data;
wire vga_clk;
wire vga_hs;
wire vga_vs;
wire vga_de;
wire [23:0] vga_data;

fdma_contrl #(
	.VIDEO_H_SRTI_W   (1920        ),
	.VIDEO_H_SIZE_W   (1280        ), 	//输入图像行分辨率
	.VIDEO_V_SIZE_W   (1024        ),	//输入图像场分辨率
	.VIDEO_H_SRTI_R   (1920        ),	
	.VIDEO_H_SIZE_R   (1920        ), 	//输入图像行分辨率
	.VIDEO_V_SIZE_R   (1080        ),	//输入图像场分辨率			
	.VIDEO_DAAR_0     (32'h80000000),	//第1帧图像缓存基地址
	.VIDEO_DAAR_1     (32'h81000000),	//第2帧图像缓存基地址
	.VIDEO_DAAR_2     (32'h82000000),	//第3帧图像缓存基地址
	.FDMA_TRANS_DIV   (2           ),	//一行图像分2次FDMA突发写传输
	.FDMA_FRAME_NUM   (3           )		//缓存3帧
)
helai_fdma_contrl(
	.ui_clk_200m  (ui_clk_200m  ),            
	.rst_n        (rst_n        ),       
	.cmos_pclk    (vid_clk      ),
	.senser_vs    (~vid_vs      ),      
	.senser_de    (vid_de       ),      
	.senser_rgb   (vid_data     ),       
	.vga_clk      (vga_clk      ),
	.vga_vs       (vga_vs       ),
	.vga_de       (vga_de       ),
	.o_vga_rgb    (vga_data     ),
	.fdma_waddr_0 (fdma_waddr_0 ),
	.fdma_wareq_0 (fdma_wareq_0 ),
	.fdma_wbusy_0 (fdma_wbusy_0 ),
	.fdma_wdata_0 (fdma_wdata_0 ),
	.fdma_wready_0(fdma_wready_0),
	.fdma_wsize_0 (fdma_wsize_0 ),
	.fdma_wvalid_0(fdma_wvalid_0),
	.fdma_raddr_0 (fdma_raddr_0 ),
	.fdma_rareq_0 (fdma_rareq_0 ),
	.fdma_rbusy_0 (fdma_rbusy_0 ),
	.fdma_rdata_0 (fdma_rdata_0 ),
	.fdma_rready_0(fdma_rready_0),
	.fdma_rsize_0 (fdma_rsize_0 ),
	.fdma_rvalid_0(fdma_rvalid_0)   
    );
  
dvi_transmitter_top helai_hdmi_out(
    .ref_clk      (ui_clk_200m),
    .i_vga_hs     (vga_hs     ),
    .i_vga_vs     (vga_vs     ),
    .i_vga_de     (vga_de     ),
	.i_vga_rgb    (vga_data   ),   
    .tmds_clk_p   (HDMI_CLK_P ),
    .tmds_clk_n   (HDMI_CLK_N ),
    .tmds_data0b_p(HDMI_D0_P  ),
	.tmds_data0b_n(HDMI_D0_N  ),
	.tmds_data1g_p(HDMI_D1_P  ),
	.tmds_data1g_n(HDMI_D1_N  ),
	.tmds_data2r_p(HDMI_D2_P  ),
	.tmds_data2r_n(HDMI_D2_N  ),
	.o_vga_rclk   (vga_clk    ),
	.o_vga_hs     (vga_hs     ),	
	.o_vga_vs     (vga_vs     ),
	.o_vga_de     (vga_de     ),
	.o_x_pos      (),
	.o_y_pos      ()	
    );   

endmodule

4、福利:工程源码获取

代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:文章末尾的V名片。
网盘资料如下:

以上是关于FPGA纯verilog代码解码CameraLink视频,附带工程源码和技术支持的主要内容,如果未能解决你的问题,请参考以下文章

FPGA纯verilog代码实现jpg解码rgb并输出显示,私我提供工程源码

FPGA/数字IC手撕代码3——通过纯verilog实现简单的ROM

FPGA纯verilog代码实现4路视频缩放拼接 提供工程源码和技术支持

FPGA纯verilog代码实现图像缩放,两种插值算法任意尺寸缩放,提供3套工程源码

FPGA纯verilog实现任意分辨率视频输出显示,高度贴近真实项目,提供工程源码和技术支持

FPGA纯verilog代码实现sobel 边缘检测,提供2套工程源码和技术支持