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对数据差分信号,如下图:
在这里插入图片描述

免责声明

本工程及其源码即有自己写的一部分,也有网络公开渠道获取的一部分(包括CSDN、Xilinx官网、Altera官网等等),若大佬们觉得有所冒犯,请私信批评教育;基于此,本工程及其源码仅限于读者或粉丝个人学习和研究,禁止用于商业用途,若由于读者或粉丝自身原因用于商业用途所导致的法律问题,与本博客及博主无关,请谨慎使用。。。

2、目前我已有的CameraLink收发工程

我的CameraLink视频专栏有很多FPGA的CaeraLink视频编解码方案,既有CaeraLink接收,也有CaeraLink发送,既有CaeraLink普通输出显示,也有CaeraLink视频拼接输出等等,专栏链接如下:欢迎前往查看:点击直接前往

3、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

4、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

5、福利:工程源码获取

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

  • 8
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

9527华安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值