首页 > 其他分享 >mipi数据流处理

mipi数据流处理

时间:2023-04-14 22:34:34浏览次数:55  
标签:lane mipi clk 处理 vld 数据流 input byte data

总体概览

配置摄像头 将摄像头配置为RAW10输出格式
图像数据串转并 将从两个lane通道接收的串行数据转换为byte类型数据
字节对齐 由于应用层原始数据打包后是byte形式,在传输时又转换成bit形式,在进行图像的逆过程时,需要保证一个byte数据的各个bit在是原来的byte数据
通道对齐 lane0和lane1数据到达FPGA的时刻存在偏差,要保证恢复后的数据相邻的两个byte是原始数据的相邻byte
解析出原始图像数据 一个长包包含一行数据,但是还包含包头等非图像数据,需要去掉
字节转像素 将解析好的图像数据转换成能够通过hdmi显示的像素数据

摄像头配置

OV5640寄存器配置

  时钟配置

    

  首先,采用的是720P的图像模式,帧率是30帧,我们知道图像实际传输的时候分辨率会比我们用到的有效分辨率高,比如我们这里720P传输的时候并不是1280720,而是1892740,这样算下来每一帧图像总共有42002400个像素,图像帧率是30帧,这样每秒钟就有42002400*30=42002400个像素需要传输,假如每个像素有两个Byte,也就是16bit,这样每秒钟就是42002400*16=672038400个比特,而我们是两个通道传输,又是DDR模式,所以相应的时钟还要除以通道数目,再除以2(DDR模式),所以最终的时钟速率是168009600, 也就是168MHz。

Register Name Value Description
0x3035 PLL Control1 0x21 System clock divided by 2, MIPI divided by 2
0x3036 PLL Control2 0x54 PLL multiplier by 0x54 = 84
0x3037 PLL Control3 0x13 PLL predivider is 31

  这样我们根据实际参考时钟为24M来计算,首先24M经过3分频变为8M,然后经过84倍的倍频变为672M,在经过系统分频2变为336MHz,之后是MIPI的2分频,最终变为168MHz。

寄存器太复杂,太多了,对寄存器的配置理解的还是不够通透,时钟计算不太准确,自己的理解。根据手册配置能够满足时钟的要求。例如 1024×768×30帧/秒的图像采集,计算疫苗产生的像素点为1024×768×30=23,592,960,采用RGB565的格式 传输图像信息,一共16bit的数据,需要2个时钟周期才能完成一个像素点数据的传输,所以需要传输的数据23,592,960×2=47,185,920‬,约为47MHZ,个人认为大于该时钟就完全可以完成数据的传输

IIC时序

MIPI 串转并

  OV5640配置 1080P 30Fps  MIPI LANE DATA RATE = 420Mhz

  mipi ddr mode mipiclk=210Mhz

  mipi 数据传输 低位优先

  1.数据传入包含MIPI_LANE[1:0] MIPI_CLK

    使用IBUFDS_DPHY原语进行数据接入,并实现差分转单端操作

    使用BUFG将转单端的时钟接入全局时钟,并使用BUFGCE_DIV原语生成串转并需要的4分频时钟信号

    ISERDESE3原语,采用DDR模式,将传入时钟和分频时钟接入,输出并行8bit信号

    

MIPI_PHY数据接收和串转并操作
 module mipi_phy_gen(
	//
	input			resetn			,
	input			mipi_clk_p		,
	input			mipi_clk_n		,
	input	[1:0]	mipi_data_p		,
	input	[1:0]	mipi_data_n		,
	
	//
	output 			mipi_byte_clk	,
	output	[7:0]	lane0_byte_data	,
	output	[7:0]	lane1_byte_data
    );
	
	
//clock

wire			clk_in_int;
wire 			clk_div;

wire			clk_in_int_bufg;

 IBUFDS_DPHY #(
      .DIFF_TERM("TRUE"),             // Differential termination
      .IOSTANDARD("MIPI_DPHY_DCI"),         // I/O standard
      .SIM_DEVICE("ULTRASCALE_PLUS")  // Set the device version (ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1,
                                      // ULTRASCALE_PLUS_ES2)
   )
   IBUFDS_DPHY_inst_uclk (
      .HSRX_O(clk_in_int_bufg),             // 1-bit output: HS RX output
      .LPRX_O_N(),         // 1-bit output: LP RX output (Slave)
      .LPRX_O_P(),         // 1-bit output: LP RX output (Master)
      .HSRX_DISABLE(1'b0), // 1-bit input: Disable control for HS mode
      .I(mipi_clk_p),                       // 1-bit input: Data input0 PAD
      .IB(mipi_clk_n),                     // 1-bit input: Data input1 PAD
      .LPRX_DISABLE(1'b1)  // 1-bit input: Disable control for LP mode
   );

BUFG BUFG_inst (
        .O                              (clk_in_int                      ),  // 1-bit output: Clock output
        .I                              (clk_in_int_bufg                          )   // 1-bit input: Clock input
    );


	 
 BUFGCE_DIV #(
      .BUFGCE_DIVIDE(4),      // 1-8
      // Programmable Inversion Attributes: Specifies built-in programmable inversion on specific pins
      .IS_CE_INVERTED(1'b0),  // Optional inversion for CE
      .IS_CLR_INVERTED(1'b0), // Optional inversion for CLR
      .IS_I_INVERTED(1'b0)    // Optional inversion for I
   )
   BUFGCE_DIV_inst (
      .O(clk_div),     // 1-bit output: Buffer
      .CE(1'b1),   // 1-bit input: Buffer enable
      .CLR(1'b0), // 1-bit input: Asynchronous clear
      .I(clk_in_int_bufg)      // 1-bit input: Buffer
   );
	 
assign mipi_byte_clk = clk_div;

//data
wire	[1:0]	data_in_from_pins_int;
wire	[7:0]	lane_byte_data[0:1];
assign lane0_byte_data = lane_byte_data[0];
assign lane1_byte_data = lane_byte_data[1];
genvar i;
generate
	for(i=0;i<2;i=i+1)begin:gen
		IBUFDS_DPHY #(
			.DIFF_TERM("TRUE"),             // Differential termination
			.IOSTANDARD("MIPI_DPHY_DCI"),         // I/O standard
			.SIM_DEVICE("ULTRASCALE_PLUS")  // Set the device version (ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1,
											// ULTRASCALE_PLUS_ES2)
		)
		IBUFDS_DPHY_inst_u0 (
			.HSRX_O(data_in_from_pins_int[i]),             // 1-bit output: HS RX output
			.LPRX_O_N(),         // 1-bit output: LP RX output (Slave)
			.LPRX_O_P(),         // 1-bit output: LP RX output (Master)
			.HSRX_DISABLE(1'b0), // 1-bit input: Disable control for HS mode
			.I(mipi_data_p[i]),                       // 1-bit input: Data input0 PAD
			.IB(mipi_data_n[i]),                     // 1-bit input: Data input1 PAD
			.LPRX_DISABLE(1'b1)  // 1-bit input: Disable control for LP mode
		);
		
		
		ISERDESE3 #(
			.DATA_WIDTH(8),                 // Parallel data width (4,8)
			.FIFO_ENABLE("FALSE"),          // Enables the use of the FIFO
			.FIFO_SYNC_MODE("FALSE"),       // Always set to FALSE. TRUE is reserved for later use.
			.IS_CLK_B_INVERTED(1'b1),       // Optional inversion for CLK_B
			.IS_CLK_INVERTED(1'b0),         // Optional inversion for CLK
			.IS_RST_INVERTED(1'b0),         // Optional inversion for RST
			.SIM_DEVICE("ULTRASCALE_PLUS")  // Set the device version for simulation functionality (ULTRASCALE,
											// ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1, ULTRASCALE_PLUS_ES2)
		)
		ISERDESE3_u0 (
			.FIFO_EMPTY(),           // 1-bit output: FIFO empty flag
			.INTERNAL_DIVCLK(), // 1-bit output: Internally divided down clock used when FIFO is
												// disabled (do not connect)
		
			.Q(lane_byte_data[i]),                             // 8-bit registered output
			.CLK(clk_in_int),                         // 1-bit input: High-speed clock
			.CLKDIV(clk_div),                   // 1-bit input: Divided Clock
			.CLK_B(clk_in_int),                     // 1-bit input: Inversion of High-speed clock CLK
			.D(data_in_from_pins_int[i]),                             // 1-bit input: Serial Data Input
			.FIFO_RD_CLK(),         // 1-bit input: FIFO read clock
			.FIFO_RD_EN(),           // 1-bit input: Enables reading the FIFO when asserted
			.RST(1'b0)                          // 1-bit input: Asynchronous Reset
		);//set_property DATA_RATE SDR|DDR [get_ports port_name]
	end	

endgenerate
endmodule

MIPI 通道对齐

  SOT = 8'hB8; 帧头也是同步头

  

DI SOT(B8)

LPS(low power state)

8bit 10111000 0000 0000

 

 {byte_data,byte_data_r1};  16bit data,在其中寻找B8,确定数据偏移量;但是B8不一定是SOT,因为数据中也可能存在B8;所以,找到B8之后,计算ECC结果是否等于接收到的ECC,就能确定B8是否代表SOT;如果是SOT,利用偏移位置将拼接的16bit数据对应的数据进行输出;通道对齐模块只是进行寻找B8,验证是否是SOT在数据包解析模块进行

 

数据对齐
 module byte_align(
	input			clk				,
	input			resetn			,
	input	[7:0]	lane_data		,
	output reg[7:0]	mipi_byte_data	,
	output reg		mipi_byte_vld  	,
	input			re_find
);  

//================define==========
localparam SYNC  = 8'hb8;
reg [2:0]	offset;

reg [7:0]	lane_data_r1;


wire [15:0]	data_16bit;
reg [15:0]	data_16bit_r1;

//===================main code=====
always@(posedge clk)begin
	lane_data_r1 <= lane_data;
	data_16bit_r1<= data_16bit;
end

assign data_16bit = {lane_data,lane_data_r1};

always@(posedge clk or negedge resetn)begin
	if(!resetn)begin
		offset <= 'd0;
		mipi_byte_vld <= 1'b0;
	end
	else if(re_find)begin
		offset <= 'd0;
		mipi_byte_vld <= 1'b0;
	end
	else if(mipi_byte_vld == 1'b0)begin
		if(data_16bit[7:0] == SYNC)begin
			offset <= 'd0;
			mipi_byte_vld <= 1'b1;
		end
		else if(data_16bit[8:1] == SYNC)begin
			offset <= 'd1;
			mipi_byte_vld <= 1'b1;
		end
		else if(data_16bit[9:2] == SYNC)begin
			offset <= 'd2;
			mipi_byte_vld <= 1'b1;
		end
		else if(data_16bit[10:3] == SYNC)begin
			offset <= 'd3;
			mipi_byte_vld <= 1'b1;
		end
		else if(data_16bit[11:4] == SYNC)begin
			offset <= 'd4;
			mipi_byte_vld <= 1'b1;
		end
		else if(data_16bit[12:5] == SYNC)begin
			offset <= 'd5;
			mipi_byte_vld <= 1'b1;
		end
		else if(data_16bit[13:6] == SYNC)begin
			offset <= 'd6;
			mipi_byte_vld <= 1'b1;
		end
		else if(data_16bit[14:7] == SYNC)begin
			offset <= 'd7;
			mipi_byte_vld <= 1'b1;
		end
	end
end

//assign mipi_byte_data data_16bit_r1[offset+7:offset];]
always@(*)begin
	case(offset)
		0:	mipi_byte_data = data_16bit_r1[7:0];
		1:	mipi_byte_data = data_16bit_r1[8:1];
		2:	mipi_byte_data = data_16bit_r1[9:2];
		3:	mipi_byte_data = data_16bit_r1[10:3];
		4:	mipi_byte_data = data_16bit_r1[11:4];
		5:	mipi_byte_data = data_16bit_r1[12:5];
		6:	mipi_byte_data = data_16bit_r1[13:6];
		7:	mipi_byte_data = data_16bit_r1[14:7];
		default:	mipi_byte_data = data_16bit_r1[7:0];
	endcase
end

endmodule

 通道对齐

 SOT在摄像头MIPI端是同时传输的,如果两个lane的同步头在FPGA内部传输相差超过1个时钟周期,就意味着源端发送2进制数据超过8bit,也就是超过MIPI传输数据的4个时钟周期(20ns),两个同步头的传输时不会发生这种情景,所以这种情况对应的一定是数据部分,不是同步头。

   两个lane的byte_vld相差不超过一个时钟周期,谁快谁打拍,需做同步处理,谁快谁打拍,同时进入就同时输出。

   如果在两个时钟周期以上,就一定不是SOT,反馈给byte_align,模块重新查找同步头。

 

通道对齐
 module lane_align(
	//sys
	input				clk			,
	input				rst_n		,
	//input
	input		[7:0]	lane0_byte_data	,
	input		[7:0]	lane1_byte_data,
	input				lane0_byte_vld	,
	input				lane1_byte_vld	,
	//output
	output	reg 		word_vld,
	output	reg [15:0]	word_data,
	input				invalid_start
);
//=========================================
//================define===================
//=========================================
localparam LANE0_FIRST = 2'b01;
localparam LANE1_FIRST = 2'b10;
localparam NONE_FIRST  = 2'b11;

wire 			lane_vld_or;
reg 			lane_vld_or_r1;
wire 			lane_vld_or_pos;
reg 			lane_vld_or_pos_r1;
reg 	[7:0]	lane0_byte_data_r1;
reg		[7:0]	lane1_byte_data_r1;
reg 			lane0_byte_vld_r1;
reg 			lane1_byte_vld_r1;

reg 	[1:0]	tap;

wire 			lane_vld_and;

//-----------------------------------------
assign lane_vld_or = lane0_byte_vld || lane1_byte_vld;
assign lane_vld_or_pos = lane_vld_or && !lane_vld_or_r1;
assign lane_vld_and = lane0_byte_vld && lane1_byte_vld;

always@(posedge clk)begin
	lane0_byte_data_r1 	<= lane0_byte_data;
	lane1_byte_data_r1 	<= lane1_byte_data;
	lane_vld_or_r1		<= lane_vld_or;
	lane_vld_or_pos_r1	<= lane_vld_or_pos;
	lane0_byte_vld_r1   <= lane0_byte_vld;
	lane1_byte_vld_r1   <= lane1_byte_vld;
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		tap <= NONE_FIRST;
	else if(lane_vld_or_pos)
		tap <= {lane1_byte_vld,lane0_byte_vld};
end
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		invalid_start <= 1'b0;
	else if(lane_vld_or_pos_r1 && lane_vld_and == 1'b0)
		invalid_start <= 1'b1;
	else
		invalid_start <= 1'b0;
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		word_data <= 'd0;
		word_vld <= 1'b0;
	end
	else begin
		case(tap)
			LANE0_FIRST:begin
				word_data <= {lane1_byte_data,lane0_byte_data_r1};
				word_vld <= lane1_byte_vld;
			end
			LANE1_FIRST:begin
				word_data <= {lane1_byte_data_r1,lane0_byte_data};
				word_vld <= lane0_byte_vld;
			end
			NONE_FIRST:begin
				word_data <= {lane1_byte_data_r1,lane0_byte_data_r1};
				word_vld <= lane1_byte_vld_r1;
			end
			default:begin
				word_data <= {lane1_byte_data_r1,lane0_byte_data_r1};
				word_vld <= lane1_byte_vld_r1;
			end
		endcase
	end
		
end
endmodule

标签:lane,mipi,clk,处理,vld,数据流,input,byte,data
From: https://www.cnblogs.com/VicentZJ/p/17318492.html

相关文章

  • 基于L2-RLS算法的目标跟踪算法matlab仿真,可处理小范围遮挡问题
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要目标表观模型是跟踪器的重要组成部分,用来描述目标表观的特征.基于判别式模型的表观模型用来区分目标和背景;基于生成式模型的表观模型用来描述目标本身,提取出目标的特征.本文合理地融合了判别式模型和生成式模型......
  • 基于L2-RLS算法的目标跟踪算法matlab仿真,可处理小范围遮挡问题
    1.算法仿真效果matlab2022a仿真结果如下:            2.算法涉及理论知识概要       目标表观模型是跟踪器的重要组成部分,用来描述目标表观的特征.基于判别式模型的表观模型用来区分目标和背景;基于生成式模型的表观模型用来描述目标本身,提取......
  • 使用cups + ipp 协议client 进行网络打印处理
    实际上日常中我们已经使用了网络打印了(比如公司内部使用的共享打印机),现在大家会有使用基于部分厂商开发的的网络打印进行资料打印从技术实现上基本都是基于网络打印技术,然后通过控制程序对于打印机进行操作,然后平台会按照不同的打印模式收取不同的费用,用户可以自己去固定网点去取......
  • GIS For CAD插件:高效便捷的地理信息处理辅助工具
    GISForCAD插件是一款基于AutoCAD的功能套件,它提供了一系列GIS功能。通过该插件,您可以轻松地在AutoCAD中导入和导出SHP、MDB、Kml、Kmz、Gpx、GeoJson、EXCEL、TXT、CSV等多种格式的矢量文件,并支持SQLServer、MySQL、PostgreSQL等多种数据库的导入和导出。 同时,GISForCA......
  • 物联网前沿实践【2】-信号处理基础
    参考:https://iot-book.github.io/2_%E4%BF%A1%E5%8F%B7%E5%A4%84%E7%90%86%E5%9F%BA%E7%A1%80/S1_%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%8F%91%E9%80%81%E5%92%8C%E6%8E%A5%E6%94%B6/ 我们首先可以尝试一下用声音信号模拟,简单生成声音信号、录音以及播放录音文件的代码如下;%%制造......
  • 解密 parquet 文件,以及如何用 Python 去处理它
    楔子随着大数据时代的发展,每天都要产生大量的数据,而存储这些数据不仅需要更多的机器,怎么存也是一个问题。因为数据不是存起来就完事了,我们还要对数据进行分析、统计,所以一个合理的数据格式也是非常重要的。而随着数据种类的不同,我们也会选择不同的格式去存储。数据种类数据一......
  • python 正则处理字符串,使用函数
    """在正则截取的字符子串基础上,处理字符串Python的re模块提供了re.sub用于替换字符串中的匹配项。语法:re.sub(pattern,repl,string,count=0,flags=0)参数:pattern:正则中的模式字符串。repl:替换的字符串,也可为一个函数。string:要被查找替换的原始字符串。cou......
  • python 之 session鉴权的处理
    一、session鉴权的处理1.requests的会话对象就像一个浏览器一样,它会在同一个会话中自动处理cookie信息,不需要写任何额外的代码。importrequests  session=requests.Session()#理解为就是一个浏览器  type(session)  requests.sessions.Sess......
  • 29-springcloud-config-5-配置信息的加解密安全处理
    前面是在Git仓库中明文存储配置信息值,很多场景下,对于某些敏感的配置内容(例如数据库账号、密码等),应该加密存储,configserver为我们考虑到了这一点,对配置内容提供了加密与解密支持;安装JCEconfigserver的加解密功能依赖JavaCryptographyExtension(JCE)Java8JCE下载地址:http://......
  • 关于 css 伪元素 content属性值 为中文字符时出现乱码问题的处理
    更多关于csscontent属性的介绍点我 场景:需要在右箭头(点击该箭头是可以跳转到详情页)的左侧补充一个“更多”的文字描述 在一些场景下,使用CSS去做改动会是最优的,比如无源码等 易出现乱码的代码示例i.common-right-arrow-icon{position:relative;}i.comm......