开源ISP介绍(1)——开源ISP的Vivado框架搭建

开源github链接:bxinquan/zynq_cam_isp_demo: 基于verilog实现了ISP图像处理IP

国内Gitee链接:zynq_cam_isp: 开源ISP项目

基于以上开源链接移植项目到正点原子领航者Zynq7020开发板,并对该项目的Vivddo工程进行架构详解,后续会讲解ISP算法对应源码

Vivado版本(2023.2)

Zynq通用视频处理框架介绍

这个可以参考知乎文章:ZYNQ视频图像处理系统(下) - 知乎

贴出里面的一张图

Vivado工程搭建

创建vivado工程,选择对应的器件

在Vivado中导入开源的IP核目录(开源链接中下载)

创建一个BlockDesign,添加ZYNQ7 Processsing System,并按照以下设置PS端

若需要烧录到QSPI Flash中就勾选以下,注意必须勾选Feedback Clock选项,否则会烧录到Flash Timeout失败。

SD卡也勾选上,稍后可以将程序放在SD卡并使用SD卡启动,在Vitis中也可以挂载SD卡保存相应的RAW/RGB图像。

 UART用于向串口输出相关调试信息

 EMIO和MIO用于映射PL端和PS端的按键以及LED

 PL配置两个时钟系统:低速时钟用于AXI-Lite总线寄存器配置,高速时钟用于ISP等其他IP的基准时钟(经过不同分频/倍频提供给相应IP核)

正点原子DDR使用的型号为MT41J256M16 RE-125

勾选中断相关

另外注意:Bnak0 的电平为3.3V ,bank1的电平为1.8V

添加相关IP并连线,最终的BlcokDesign如下

完整框架图可以在这个链接下载查看:【免费】开源ISPVivado框架PDF资源-CSDN文库

由于使用了正点原子开发板,因此需要修改开源项目中对应的管脚约束XDC文件,修改的XDC文件内容如下:

#----------------------摄像头接口的时钟---------------------------
#96M
create_clock -period 10.416 -name cam_pclk [get_ports cam_pclk]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets cam_pclk_IBUF]
# set_clock_groups -async -group [get_clocks cam_pclk] \
#         -group [get_clocks clk_fpga_0] -group [get_clocks clk_fpga_1] \
#         -group [get_clocks camif_xclk_base_clk_wiz_0_0] \
#         -group [get_clocks isp_pclk_base_clk_wiz_0_0] \
#         -group [get_clocks lcd_clk_base_clk_wiz_0_0] \
#         -group [get_clocks dvi_clk_base_clk_wiz_1_0_1]set_clock_groups -async -group [get_clocks cam_pclk]#----------------------摄像头接口---------------------------
#camera  采用的是DVP接口
set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports cam_rst_n]
set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports cam_pwdn]set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports cam_pclk]
set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports cam_vsync]
set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports cam_active_video]set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports cam_data[0]]
set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports cam_data[1]]
set_property -dict {PACKAGE_PIN V13 IOSTANDARD LVCMOS33} [get_ports cam_data[2]]
set_property -dict {PACKAGE_PIN U15 IOSTANDARD LVCMOS33} [get_ports cam_data[3]]
set_property -dict {PACKAGE_PIN U14 IOSTANDARD LVCMOS33} [get_ports cam_data[4]]
set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports cam_data[5]]
set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports cam_data[6]]
set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports cam_data[7]]#camera xclk  实际中该约束不起作用,OV5640模组已经板载了24M有源晶振
set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports cam_xclk]#iic for camera 
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports iic_scl_io] 
set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports iic_sda_io]   set_property PULLUP true [get_ports iic_scl_io]
set_property PULLUP true [get_ports iic_sda_io]#----------------------GPIO EMIO接口---------------------------
#PL_RESET 
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports {GPIO_EMIO_tri_io[0]}]
#PL_KEY0
set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports {GPIO_EMIO_tri_io[1]}]
#PL_KEY1
set_property -dict {PACKAGE_PIN K16 IOSTANDARD LVCMOS33} [get_ports {GPIO_EMIO_tri_io[2]}]
#PL_LED0
set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports  {GPIO_EMIO_tri_io[3]}]
#PL_LED1
set_property -dict {PACKAGE_PIN L15 IOSTANDARD LVCMOS33} [get_ports {GPIO_EMIO_tri_io[4]}]#----------------------LCD接口---------------------------
set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[0]}]
set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[1]}]
set_property -dict {PACKAGE_PIN R16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[2]}]
set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[3]}]
set_property -dict {PACKAGE_PIN W20 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[4]}]
set_property -dict {PACKAGE_PIN V20 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[5]}]
set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[6]}]
set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[7]}]
set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[8]}]
set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[9]}]
set_property -dict {PACKAGE_PIN T17 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[10]}]
set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[11]}]
set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[12]}]
set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[13]}]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[14]}]
set_property -dict {PACKAGE_PIN P16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[15]}]
set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[16]}]
set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[17]}]
set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[18]}]
set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[19]}]
set_property -dict {PACKAGE_PIN Y17 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[20]}]
set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[21]}]
set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[22]}]
set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[23]}]set_property -dict {PACKAGE_PIN N18 IOSTANDARD LVCMOS33} [get_ports lcd_hs]
set_property -dict {PACKAGE_PIN T20 IOSTANDARD LVCMOS33} [get_ports lcd_vs]
set_property -dict {PACKAGE_PIN U20 IOSTANDARD LVCMOS33} [get_ports lcd_de]
set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports lcd_bl]
set_property -dict {PACKAGE_PIN P19 IOSTANDARD LVCMOS33} [get_ports lcd_clk]#----------------------HDMI接口---------------------------
set_property -dict {PACKAGE_PIN J18  IOSTANDARD TMDS_33 } [get_ports TMDS_tmds_clk_p]
set_property -dict {IOSTANDARD TMDS_33                  } [get_ports TMDS_tmds_clk_n]set_property -dict {IOSTANDARD TMDS_33  PACKAGE_PIN G19} [get_ports {TMDS_tmds_data_p[0]}]
set_property -dict {IOSTANDARD TMDS_33                 } [get_ports {TMDS_tmds_data_n[0]}]
set_property -dict {IOSTANDARD TMDS_33  PACKAGE_PIN K19} [get_ports {TMDS_tmds_data_p[1]}]
set_property -dict {IOSTANDARD TMDS_33                 } [get_ports {TMDS_tmds_data_n[1]}]
set_property -dict {IOSTANDARD TMDS_33  PACKAGE_PIN J20} [get_ports {TMDS_tmds_data_p[2]}]
set_property -dict {IOSTANDARD TMDS_33                 } [get_ports {TMDS_tmds_data_n[2]}]set_property -dict {PACKAGE_PIN L19  IOSTANDARD LVCMOS33} [get_ports tmds_oen]

在正点原子带的ov5640模块中已经有一个24MHz的有源晶振了,因此cam_xclk可以省略。 正点原子ov5640模块中将摄像头的xclk引脚直接接到24Mhz晶振上了,需要不同的pclk直接配置该模块内部的相关寄存器即可。(后面嵌入式vitis端搭建会讲)

摄像头的配置可参考:摄像头配置——OV5640配置输出RAW格式-CSDN博客

Vaivado 工程讲解

数据输入通路

在Vitis中配置Ov5640的输出为DVP格式,OV5640 提供了一个 10 位的 DVP 接口(支持 8 位接发)。ATK-MC5640 模块采用 8 DVP 连接的方式

在配置成RAW格式输出时,RAW格式实际是以RAW10输出的,所以低两位数据会被截断(对于后续ISP的处理确实会有影响,因为低两位的数据直接丢失了)

cam接口为8位宽的RAW数据,cam_pclk为摄像头输出的像素时钟,在例程里,像素时钟配置为了96MHz,对应摄像头输出的帧率(2592x1944的分辨率)大致在17帧左右。OV5640的输出时序如下

Ov5640图像传感器的数据输出(通过 D[9:0]),是在 PCLKVSYNCHREFHSYNV

的控制下进行的。,图像数据在 HREF 为高的时候输出,当 HREF 变高后,每一个 PCLK

时钟,输出一个 8 位或 10 位的数据,ATK-MC5640 模块采用 8 位,所以每个 PCLK 输出 1 个字节图像数据,且在 RGB/YUV 输出格式下(565格式),每个像素数据需要两个 PCLK 时钟,在 RAW输出格式下,每个像素数据需要一个 PCLK 时钟。

xil_camif这个IP是一个接收并传递RAW数据的IP核,通过配置该IP可以选择后续数据是来自于摄像头还是该IP生成的彩条。(后续会讲解这个IP的源码仿真以及打包封装)

RAW数据VDMA暂存通路

在进入ISP前,先将RAW帧通过VDMA缓存到DDR中,ISP随后通过VDMA再读取数据进行处理,例程中isp_pclk设置为了120MHz,稍微大于摄像头输入的像素时钟频率,但是由于VDMA的存在,可以保证时序同步。VDMA使用了多缓冲机制(例程配置了3帧),将写入和读取解耦,写端写完会将该缓冲帧标记为可读,读端读完会将对应的帧标记为可写,读写之间不会冲突。由于输入的帧率低于ISP处理的帧率,因此可以想象一段时间后,ISP读帧会拿到与上一帧相同位置的帧进行处理输出。

ISP处理与后处理通路

ISP通过VDMA从DDR中取出一帧数据开始处理(例程中分辨率设置为了2592x1944),处理完后分为了两路数据,一路用于后续处理输出到HDMI,另一路用于输出到LCD。由于两者输出的分辨率是不同的,DVI输出为1280x720@60FPS,而LCD输出为800x480@60FPS,所以Xil_vip_v1.0这个IP会对视频进行相应的缩放裁剪以达到输出的尺寸(在嵌入式Vitis中对该IP进行配置以裁剪成两种输出尺寸),由于显示输出帧率快于ISP和xil_vip处理输出的帧率,因此在输出到显示器之前都需要先将帧缓冲到VDMA中,将输入与输出解耦。以下对VDMA的同步机制进行解释。

以1280×720 @ 60 FPS的输出情况进行解释:

写缓冲器:输入路径(120MHz 的isp_pclk时钟)将1280x720的帧数据写入一个缓冲器。

读缓冲器:输出路径(基于 1280×720 @ 60 FPS 的时钟)从缓冲器中读取帧数据。

假设使用 3 个缓冲区(A、B、C):

1、初始状态:

缓冲区 A:写缓冲区(输入通路正在写)。

缓冲区 B:可供读取(已写入完成)。

缓冲区 C:空闲。

2、输入路径完成写入 A,切换到 C。

3、输出路径读取 B,完成后切换到 A。

4、循环以上过程,确保输入和输出互不干扰。

总之,写入和读取操作不会发生在同一个缓冲区上。但是由于输出帧率大于输入帧率,因此输出过程有时候会重复读取上一帧已经读取过的帧。VDMA中每帧的平均被显示的次数:约为 60/17 ≈ 3.5 次。

HDMI输出通路

在HDMI输出端中,通过VDMA从DDR中获取对应尺寸的输出通过DVI_Transmitter输出到HDMI中。因为DDR中对于该输出保存的帧尺寸为1280x720,因此对axs_to_video这个IP的配置也要相应改成如下:

LCD输出通路

同理LCD端输出也需要配置axis_to_video为相应的参数(LCD参数的配置参考正点原子对于LCD屏的描述),IP配置如下:

其他注意

开启LCD的背光lcd_bl、cam_pwdn为掉电使能(高有效),正常工作情况下需要保持该引脚一直为低电平。cam_rst_n保持为高电平,一直工作。

实际效果

在正点原子的领航者zynq7020实际效果如下:

该开源项目的Vivado工程讲解结束!敬请期待后续关于该开源项目的嵌入式vitis讲解、IP核代码讲解、ISP算法讲解.....

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/483333.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Redis#13] cpp-redis接口 | set | hash |zset

目录 Set 1. Sadd 和 Smembers 2. Sismember 3. Scard 4. Spop 5. Sinter 6. Sinter store Hash 1. Hset 和 Hget 2. Hexists 3. Hdel 4. Hkeys 和 Hvals 5. Hmget 和 Hmset Zset 1. Zadd 和 Zrange 2. Zcard 3. Zrem 4. Zscore cpp-redis 的学习 主要关注于…

GEOBench-VLM:专为地理空间任务设计的视觉-语言模型基准测试数据集

2024-11-29 ,由穆罕默德本扎耶德人工智能大学等机构创建了GEOBench-VLM数据集,目的评估视觉-语言模型(VLM)在地理空间任务中的表现。该数据集的推出填补了现有基准测试在地理空间应用中的空白,提供了超过10,000个经过人工验证的指…

设计模式 更新ing

设计模式 1、六大原则1.1 单一设计原则 SRP1.2 开闭原则1.3 里氏替换原则1.4 迪米特法则1.5 接口隔离原则1.6 依赖倒置原则 2、工厂模式 1、六大原则 1.1 单一设计原则 SRP 一个类应该只有一个变化的原因 比如一个视频软件,区分不同的用户级别 包括访客&#xff0…

nlp培训重点

1. SGD梯度下降公式 当梯度大于0时,变小,往左边找梯度接近0的值。 当梯度小于0时,减去一个负数会变大,往右边找梯度接近0的值,此时梯度从负数到0上升 2.Adam优化器实现原理 #coding:utf8import torch import torch.n…

电脑关机的趣味小游戏——system函数、strcmp函数、goto语句的使用

文章目录 前言一. system函数1.1 system函数清理屏幕1.2 system函数暂停运行1.3 system函数电脑关机、重启 二、strcmp函数三、goto语句四、电脑关机小游戏4.1. 程序要求4.2. 游戏代码 总结 前言 今天我们写一点稍微有趣的代码,比如写一个小程序使电脑关机&#xf…

基础入门-Web应用OSS存储负载均衡CDN加速反向代理WAF防护部署影响

知识点: 1、基础入门-Web应用-防护产品-WAF保护 2、基础入门-Web应用-加速服务-CDN节点 3、基础入门-Web应用-文件托管-OSS存储 4、基础入门-Web应用-通讯服务-反向代理 5、基础入门-Web应用-运维安全-负载均衡 一、演示案例-Web-拓展架构-WAF保护-拦截攻击 原理&a…

Milvus×OPPO:如何构建更懂你的大模型助手

01. 背景 AI业务快速增长下传统关系型数据库无法满足需求。 2024年恰逢OPPO品牌20周年,OPPO也宣布正式进入AI手机的时代。超千万用户开始通过例如通话摘要、新小布助手、小布照相馆等搭载在OPPO手机上的应用体验AI能力。 与传统的应用不同的是,在AI驱动的…

002-日志增强版

日志增强版 一、需求二、引入依赖三、配置日志处理切面四、配置RequestWrapper五、效果展示 一、需求 需要打印请求参数和返回参数 二、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop<…

Spire.PDF for .NET【页面设置】演示:旋放大 PDF 边距而不改变页面大小

PDF 页边距是正文内容和页面边缘之间的空白。与 Word 不同&#xff0c;PDF 文档中的页边距不易修改&#xff0c;因为 Adobe 不提供任何功能供用户自由操作页边距。但是&#xff0c;您可以更改页面缩放比例&#xff08;放大/压缩内容&#xff09;或裁剪页面以获得合适的页边距。…

服务器数据恢复—EVA存储硬盘磁头和盘片损坏离线的数据恢复案例

服务器存储数据恢复环境&故障&#xff1a; 一台HP EVA存储中有23块硬盘&#xff0c;挂接到一台windows server操作系统的服务器。 EVA存储上有三个硬盘指示灯亮黄灯&#xff0c;此刻存储还能正常使用。管理员在更换硬盘的过程中&#xff0c;又出现一块硬盘对应的指示灯亮黄…

探索仓颉编程语言:官网上线,在线体验与版本下载全面启航

文章目录 每日一句正能量前言什么是仓颉编程语言仓颉编程语言的来历如何使用仓颉编程语言在线版本版本下载后记 每日一句正能量 当你被孤独感驱使着去寻找远离孤独的方法时&#xff0c;会处于一种非常可怕的状态。因为无法和自己相处的人也很难和别人相处&#xff0c;无法和别人…

idea 自动导包,并且禁止自动导 *(java.io.*)

自动导包配置 进入 idea 设置&#xff0c;可以按下图所示寻找位置&#xff0c;也可以直接输入 auto import 快速定位到配置。 Add unambiguous imports on the fly&#xff1a;自动帮我们优化导入的包Optimize imports on the fly&#xff1a;自动去掉一些没有用到的包 禁止导…

【时时三省】(C语言基础)结构体的自引用

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 结构体的自引用 在结构中包含一个类型为该结构体本身的成员是否可以呢&#xff1f; 在struct B里面包含了一个结构体struct A叫sa 结构体类型里面是可以包含另一个结构体类型变量作为它的成…

GoReplay开源工具使用教程

目录 一、GoReplay环境搭建 1、Mac、Linux安装GoReplay环境 二、GoReplay录制与重播 1、搭建练习接口 2、录制命令 3、重播命令 三、GoReplay单个命令 1、常用命令 2、其他命令 3、命令示例 4、性能测试 5、正则表达式 四、gorepaly组合命令 1、组合命令实例 2、…

宏海科技募资额有所缩减,最大销售和采购都重度依赖美的集团

《港湾商业观察》施子夫 11月29日&#xff0c;北交所上市审核委员会将召开2024年第24次上市委审议会议&#xff0c;届时将审议武汉宏海科技股份有限公司&#xff08;以下简称&#xff0c;宏海科技&#xff09;的首发上会事项。 在上会之前&#xff0c;宏海科技共收到北交所下…

驱动篇的开端

准备 在做之后的动作前&#xff0c;因为win7及其以上的版本默认是不支持DbgPrint&#xff08;大家暂时理解为内核版的printf&#xff09;的打印&#xff0c;所以&#xff0c;为了方便我们的调试&#xff0c;我们先要修改一下注册表 创建一个reg文件然后运行 Windows Registr…

渗透测试--Windows凭证收集

在渗透测试过程中&#xff0c;我们终究会遇到攻陷了某台加域Windows主机的情况。而这种情况下&#xff0c;我们很需要搜集当前主机的凭证信息。为进一步利用这些相互信任的凭证来进行横向打下基础。 在凭证收集中&#xff0c;我们主要有以下场景&#xff1a; 1.lsass.exe的DMP文…

PH热榜 | 2024-12-03

1. Vela OS 标语&#xff1a;利用人工智能&#xff0c;创业投资精准度提升十倍。 介绍&#xff1a;Vela操作系统是一个原生AI操作系统&#xff0c;它能让创业投资者的预测准确率比传统风投公司高出十倍。借助一群AI智能体&#xff0c;投资者可以发现蓬勃发展的市场、公司和人…

微信小程序 运行出错 弹出提示框(获取token失败,请重试 或者 请求失败)

原因是&#xff1a;需要登陆微信公众平台在开发管理 中设置 相应的 服务器域名 中的 request合法域名 // index.jsPage({data: {products:[],cardLayout: grid, // 默认卡片布局为网格模式isGrid: true, // 默认为网格布局page: 0, // 当前页码size: 10, // 每页大小hasMore…

Google Cloud 混合云部署连接方式最佳实践案例讲解

混合云部署连接方式 GCP 的混合云部署连接方式提供了多种选择&#xff0c;企业可以根据自身需求选择合适的解决方案。实施最佳实践&#xff0c;将有助于提高混合云架构的性能、安全性和可用性。通过合理的规划和管理&#xff0c;企业可以充分利用混合云的优势&#xff0c;实现…