基于zynq的图像视频数据采集处理项目一

基于zynq的图像视频数据采集处理项目一

1.整体的架构

在这里插入图片描述

2.整体的时钟和复位设计

时钟域分为:
1.图像预处理时钟:它由外部cmos芯片源同步传递过来,作用于传感器解析模块;byer转rgb模块;灰度域白均衡模块(74.25MHz)
2.axi 读写时钟:它由ps端给出的axi时钟200MHz
3.视频输出时钟:它由pll(clkin由ps端给出的100MHz)产生的148.5MHz(1920x1080 @60Hz)
4.给到serdes的管脚时钟:为视频输出时钟的5倍

复位分为:(都通过了异步复位同步释放)
1.图像预处理复位:它由ps通过gpio给出(与axi wr模块启动信号同源)
2.axi wr/rd复位:它由ps给出PS-PL configuration配置给出,通过复位ip核同步于ps端给出的axi时钟200MHz
3.视频输出复位:pll的locked信号

3.详细方案设计

3.1 ps端spi对摄像头的配置,数据的dvp口截断输入

fpga芯片配置imx222寄存器的接口采用spi接口协议,

spi详细解读以及配置请看我的博文
https://blog.youkuaiyun.com/weixin_45284871/article/details/141001874

主要是在vitis端用封装好的spi函数来对摄像头中的寄存器进行配置。这里 SPI 配置时序要求先发 LSB 最后发 MSB,与xilinx的zynq的PS端提供的驱动程序相反,我们再发送数据时需要进行高低位对调操作。

spi配置的是cmos模组12bit的模式,dvp并口数据(CMOS电平信号)的12根线接到FPC软排线然后再接到fpga,数据PIXEL_RGB只用12bit的高8位,PIXEL_RGB就只是绑定了高8位的管脚

3.2 看手册对 IMX2221080P 模式图像解析

图像传感器输出的是图像是那种嵌入式同步字机制(帧头或者帧尾一样的机制),要对输出的嵌入式同步字和有效行场信号进行解析。通过4个字节的无效行开始,4个字节的无效行结束,4个字节的有效行开始,4个字节的有效行结束,然后再根据相机的行场细节来解析出有效的图像1920*1080的模式。
用一个移位寄存器,高位先来,往左推箱子

always @(posedge clk) begin
	shift_reg <= {shift_reg[23:0],bayer};
end

shift_reg来判断当前行是不是有效行

在这里插入图片描述

在这里插入图片描述

主要就是写状态机(因为事件发生有前后顺序),在不同的状态(无效行状态,有效行状态)处理图像数据。注意,为了后续的处理,需要多解析有效图像的的外围一圈像素,然后将有效图像的行场有效信号传递给bayer2rgb模块。
在这里插入图片描述

这里的输入的数据需要打一拍,以和解析出来的有效图像的行场有效信号,可以说是一级流水

3.3 拜耳图像格式转换为 RGB 图像

拜尔图像就是他一个点只有一个颜色通道分量的值,8bit,
主要就是用三个移位寄存器和两个fifo实现一个3X3的滑动矩形窗,矩形窗中心位置就是我们要差值出rgb三个通道的像素点,(怎么插值,需要根据像素的行列索引号来确定——奇行奇列是什么样的插值算法,偶行偶列是什么插值算法这样)
在这里插入图片描述

具体的过程描述
图像的第0行缓冲到fifo0,第1行缓冲到fifo1,第3行第一个有效像素来的时候,开始对fifo0和fifo1进行读出,fifo0的读出dout0送入24位的移位寄存器reg000102,fifo1的读出dout1送入24位的移位寄存器reg101112,pixel的直接送入24位的移位寄存器reg202122,与此同时pixel(第3行第一个有效像素来的时候)作为fifo1的输入,fifo1的输出dout1作为fifo0的输入,fifo0的输出dout0就扔掉不要了,直到整个一帧有效图像结束。
(这里的fifo深度就是能缓存一行图像就行)
fifo0的读写使能,和数据代码

//r_fifo_en
//第三行数据来临开始读出
always @(*) begin
	if(frame_valid == 1'b1 && vcnt != 'd0 && vcnt != 'd1 && hsync)begin
		r_fifo_en = 1'b1;
	end
	else begin
		r_fifo_en =0;
	end
end

//w_fifo_0_data
//先是缓存一帧图像的首行,后面缓存fifo1的输出dout1
always @(*)begin
	if(frame_valid == 1'b1 && vcnt == 'd0) begin
		w_fifo_0_data <= pixel;
	end
	else begin
		w_fifo_0_data <= dout1;
	end
end

//w_fifo_0_enfifo0在一帧数据pixel的0行和除了最后1行之外的时候保持写入
always @(*) begin
	if(frame_valid == 1'b1 && vcnt != 'd1 && vcnt != VCNTMAX && hsync)begin
		w_fifo_0_en = 1'b1;
	end
	else begin
		w_fifo_0_en = 0;
	end
end

//FIFO深度能缓存1行数据1920即可,这里是2048
sfifo_2048x8 sfifo_2048x8_0_inst (//
  .clk(clk),      // input wire clk
  .din(w_fifo_0_data),      // input wire [7 : 0] din
  .wr_en(w_fifo_0_en),  // input wire wr_en
  .rd_en(r_fifo_en),  // input wire rd_en
  .dout(dout0),    // output wire [7 : 0] dout
  .full(),    // output wire full
  .empty()  // output wire empty
);

fifo1的读写使能,和数据代码

//w_fifo_1_data 一直让它等于输入进来的pixel即可
always @(*)begin
		w_fifo_1_data <= pixel;
end

//w_fifo_1_en fifo1从一帧数据pixel的第1行和除了最后1行之外的时候保持写入
always @(*) begin
	if(frame_valid == 1'b1 && vcnt != 'd0 && vcnt != VCNTMAX && hsync)begin
		w_fifo_1_en = 1'b1;
	end
	else begin
		w_fifo_1_en =0;
	end
end

//rd_en和fifo0的一样

//
sfifo_2048x8 sfifo_2048x8_1_inst (
  .clk(clk),      // input wire clk
  .din(w_fifo_1_data),      // input wire [7 : 0] din
  .wr_en(w_fifo_1_en),  // input wire wr_en
  .rd_en(r_fifo_en),  // input wire rd_en
  .dout(dout1),    // output wire [7 : 0] dout
  .full(),    // output wire full
  .empty()  // output wire empty
);

三个移位寄存器形成矩形窗


always @(posedge clk ) begin
	if (r_fifo_en == 1'b1) begin
		reg000102 <= {reg000102[15:0],dout0};
		reg101112 <= {reg101112[15:0],dout1};
		reg202122 <= {reg202122[15:0],pixel};
	end
end

具体的设计时序如图:
在这里插入图片描述

3.4 灰度域的白平衡算法 white Balance 的 RTL 实现

白平衡算法的实现:是后面加的,因为出来的图像有点偏绿,色温有问题。所以采用灰度域的白平衡算法,一般得现在c语言里面做定点化验证效果(比如写一张图像到sd卡导出来做算法的定点化验证),然后再做的RTL的设计

RTL中的设计为:计算上一帧图像的所有像素的 R, B, G通道的平均值 Ravg, Bavg, Gavg。以及上一帧图像的 R/G/B 平均值的平均值又称作灰度平均值 Kavg。在得到上一帧图像的上述四个参数后,根据这四个参数,用这4个值算出增益,来对当下的这一帧图像进行白平衡处理(所以第一帧是处理不了的)。增益计算如下:
在这里插入图片描述

如果红色分量的平均值大于灰度平均值的话就会使 red 分量变少,反之增大一点,当计算结果大于 255(溢出)时,固定输出为 255,由此得到白平衡处理后的图像输出数据。过程中涉及到的除法器,如果误差不太大的话+除数为固定值,就可以直接截位。这样可以节约资源。

Ravg颜色通道是将进来的8位i_data_r分量全部相加,用ri_data_r_sum来寄存,
ri_data_r_sum的位宽既是19201080255,即29位即可,在一帧信号标志下降沿的时候清零上一帧的sum和并计算上一帧的颜色通道平均值(为了计算本帧的sum和),在有效行信号来的时候开始计算sum
代码如下:

// ri_data_r_sum
always @(posedge i_clk or posedge i_rst) begin
   if (i_rst) begin
       ri_data_r_sum <= 'd0;
   end
   else if(i_fv_flag_fall) begin//在一帧信号标志下降沿的时候清零上一帧的sum
       ri_data_r_sum <= 'd0;
   end
   else if(i_hv_flag) begin//在有效行信号来的时候开始计算sum
       ri_data_r_sum <= i_data_r + ri_data_r_sum;
   end
   else
       ri_data_r_sum <= ri_data_r_sum;
end

// data_ravg
always @(posedge i_clk or posedge i_rst) begin
   if (i_rst) begin
       data_ravg <= 'd0;
   end
   else if(i_fv_flag_fall) begin//在一帧信号标志下降沿的时候计算上一帧的颜色通道平均值
       data_ravg <= ri_data_r_sum[29:21];//这里直接截位计算,相当于除以1920*1080
   end
   else
       data_ravg <= data_ravg;
end

其他的乘除就调用ip核,调用ip核的时候都选择了只使用lut和ff资源的模式,所以最后我们可以看到项目的dsp资源使用为0
在这里插入图片描述

最后数据有效信号传递给下一模块的即复用除法器除出来的valid信号就行
在这里插入图片描述

### Zynq 项目在 Vivado 中的开发流程 #### 设计创建与配置 在启动个新的 Zynq 项目时,需通过 Vivado 创建工程并设置目标器件参数。对于基于 Zynq 的设计而言,核心在于正确配置 ZYNQ7 Processing System IP 模块,该模块代表了 ARM 处理器子系统及其外围接口资源[^3]。 #### 硬件平台构建 完成 PS(Processing System)初始化后,继续添加必要的外设组件以及自定义逻辑电路至 PL(Programmable Logic)。此阶段涉及综合、实现操作,并最终生成用于编程 FPGA 器件的比特流文件(bit stream)[^2]。 #### 软硬件协同工作准备 旦完成了上述步骤并且成功编译出 bit 文件,则可以考虑将整个硬件环境打包导出给 SDK 使用。具体做法是从菜单栏选择 `File -> Export -> Export Hardware` 并勾选项 “Include bitstream”。这步骤确保了后续加载的应用程序能够访问到最新的硬件描述信息,从而支持更高效的软硬件联合仿真与调试过程。 #### 应用层开发 进入 SDK 后可着手编写应用程序代码,利用 Xilinx 提供的各种库函数简化底层驱动控制难度。例如,在个简单的 "Hello World" 实验里,开发者只需调用 printf 函数就能向 UART 输出字符串消息。 ```c #include <stdio.h> int main() { printf("Hello, world!\n"); return 0; } ``` #### 测试验证 最后步是对所开发出来的嵌入式系统进行全面的功能性和性能上的检验。除了常规手段之外,还推荐采用 ChipScope Pro 工具来进行在线监测分析,以便及时发现潜在问题所在并加以修正[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

帅癌晚期的彦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值