ove学习使我快乐

  • 2020-09-18
  • 发表了主题帖: DONT_TOUCH约束

             对设计中的信号施加DONT_TOUCH约束,可以避免这些信号在综合编译过程中被优化掉。例如,有些信号节点在综合或布局布线编译过程中可能会被优化掉,但是我们希望在后期调试过程中能够监控到这些信号,此时就可以使用DONT_TOUCH约束达到保留这些信号的目的。又如,有时在设计中会对一些高扇出的信号进行手动的逻辑复制,也可以使用DONT_TOUCH约束避免它们被优化掉。   实例:          下面有一个简单的例子,看看DONT_TOUCH约束如何使用。原始代码如下,目前只有一个寄存器vga_valid,它对应了adv7123_blank_n、vga_r、vga_g、vga_b等信号的输出。 reg vga_valid;   always @(posedge clk or negedge rst_n)          vga_valid <= vga_origin_vld;     assign adv7123_blank_n = vga_valid; assign vga_r = vga_valid ? vga_rdb:5'd0; assign vga_g = vga_valid ? vga_gdb:6'd0;       assign vga_b = vga_valid ? vga_bdb:5'd0; 编译工程后,点击Run Implementation,打开实现界面。          点击菜单Reports --> Report High Fanout Nets。          如图,设定From cells为[get_cells -hierarchical "*vga_valid*"],即查看所有带vga_valid字符的信号。          此时,可以看到当前vga_valid信号的扇出为17。          这个例子中,vga_valid的扇出为,其实并不多。但是在实际工程中,我们可以通过类似的方式查看到设计中高扇出的关键信号节点。然后,我们会如下在代码中,对这样的信号做逻辑复制。意图减少单个信号的扇出。 reg vga_valid1; reg vga_valid2;   always @(posedge clk or negedge rst_n)          vga_valid1 <= vga_origin_vld;          always @(posedge clk or negedge rst_n)          vga_valid2 <= vga_origin_vld;   assign adv7123_blank_n = vga_valid1; assign vga_r = vga_valid2 ? vga_rdb:5'd0; assign vga_g = vga_valid1 ? vga_gdb:6'd0;    assign vga_b = vga_valid2 ? vga_bdb:5'd0;             如图,可惜我们做过逻辑复制的代码,最终综合实现下来,并没有减少扇出,和原始代码实现的效果完全一样。怎么回事?综合工具太聪明了,识别了你这个小伎俩,为了减少设计资源消耗,综合工具默认优化掉了代码中新增加的vga_valid2。          但是,工具并不懂我们真正的心思,怎么办?此时DONT_TOUCH约束就派上用场了。如下,在不希望被综合优化的2个寄存器前面,加上(*dont_touch = "true"*)的语法。 (*dont_touch = "true"*) reg vga_valid1; (*dont_touch = "true"*) reg vga_valid2;            重新编译后,我们看到,代码生效了。vga_valid1和vga_valid2分担了原本vga_valid的扇出。  

  • 2020-09-15
  • 发表了主题帖: CLOCK_DEDICATED_ROUTE约束应用

             Vivado工具在编译时通常会自动识别设计中的时钟网络,并将其分配到专用的时钟布局布线资源中。通过对某些时钟网络设置CLOCK_DEDICATED_ROUTE值为FALSE,可以将被识别为时钟网络并按照时钟网络进行布局布线的时钟信号安排到通用的布线资源中。比如,某些时钟信号由于设计疏忽或其它原因,没有被安排到FPGA器件的时钟专用引脚上,在编译的时候就会报错,此时就可以使用CLOCK_DEDICATED_ROUTE约束来忽略这个错误。   实例1:忽略关于时钟布线的编译ERROR          我们有一个设计,输入到FPGA的图像数据同步时钟image_sensor_pclk信号,由于没有分配到FPGA内部的MRCC或SRCC引脚上,在编译时,Vivado通常可能会报错。          此时,我们可以通过在工程的.xdc约束文件中添加如下CLOCK_DEDICATED_ROUTE命令,来忽略这个报错,让编译继续进行。          当然,这个约束通常不建议乱用,被施加了CLOCK_DEDICATED_ROUTE FALSE的时钟网络,它将被分配到通用布局布线资源中,若这是一个时序关键路径上时钟,这样的行为很可能会带来一些不期望的设计问题。   实例2:查看时钟资源          对于一个已经编译过的工程,点击Run Implementation,打开实现界面。          此时,Reports菜单出现了很多可视报告项,点击Report Clock Utilization。          此时,在Clock Utilization界面下可以查看到当前工程所有占用到时钟布局布线资源的网络。

  • 2020-08-20
  • 发表了主题帖: 跨时钟域为什么要双寄存器同步

             随着设计规模的不断攀升,各种接口外设琳琅满目,时钟“满天飞”就不可避免(注意这里的“满天飞”不是滥用,意指时钟频率多、时钟扇出多)。而一个设计中,不同时钟频率之间你来我往更是在所难免。那么,这就出现了题目中的跨时钟域的同步问题?怎么办?十年不变的老难题。为了获取稳定可靠的异步时钟域送来的信号,一种经典的处理方式就是双寄存器同步处理(double synchronizer)。那为啥要双寄存器呢,一个不就够了吗?          先来看看,这张老得掉牙,经典得不能再经典的示意图。Aclk和bclk是两个不同的时钟域,bclk比aclk要稍微慢一点(哦,我的天哪,要用慢时钟采集快时钟的数据,又是一个难),与aclk同步的数据adat某个时钟周期拉高了(注意,只保持了1个时钟周期)。接下来,要用bclk时钟去采集只保持了一个aclk时钟周期的adat数据。理论上,这不符合奈奎斯特定律,很难成功,但是大家不要较真,这里重点不在这里。我们要关注的其实是那个不偏不倚bclk采样时(bclk时钟上升沿)正好对准了adat的下降沿(上升沿也类似),好开心,奈奎斯特老爷爷的定律被打破了。 数据采是采到了,但是不稳定,从模拟信号的角度看,bclk采集到的数据就是一个中间电平,到低最终判定是1还是0,很抱歉,看上去好像都不是。数字电路终归还是一个模拟电路搭起来的,真实世界都是骨感的(模拟的)。所以,你就看到,bclk时钟域的第一级采样时钟bq1_dat的输出波形起起伏伏,好在最终还是稳在了数字电平1或接近1的位置。如果bq1_dat直接在bclk时钟域被正常使用,后端就一个驱动扇出或许还好,可能就和示意图里第二级锁存bq1_dat的寄存器bq2_dat一样稳定了。但是,实际情况,可能我们要用这个bq1_dat去驱动多个扇出,那就十有八九要出问题,这个bq1_dat上的亚稳态恐怕还要继续传播给某些后级的寄存器,而这不是我们希望看到的。 那怎么办?解决方案有一个,用专门的寄存器bq2_dat对bq1_dat再锁存一拍,这么一来,就基本是稳定的了。还有一个问题,为啥就这么容易稳定了?前面提到了,bq1_dat的输出波形虽然起起伏伏,但最终一般还是会稳在要么接近0要么接近1的位置(在下一个时钟周期bq2_dat去锁存它的时候,更容易满足bq2_dat寄存器对建立和保持时间的要求),所以如果它本身的扇出路径单一的情况下,后级采样寄存器基本就能正常输出了。            另外,不得不再提一下MTBF(mean time between failures)的概念,一个基本的思想,就是同步寄存器级别越多,MTBF的概率越低,越不容易出问题。关于这个部分,大家可以去搜一下特权同学早期的文章,作为补充阅读。 https://www.eefocus.com/ilove314/blog/11-09/231565_715ed.html            最后,再来看看类似的跨时钟域的亚稳态在这2级寄存器同步后的个各种可能状况。          bq1_dat采样到adat的上升沿,最终bq1_dat稳定在0,bq2_dat也输出稳定的0。          bq1_dat采样到adat的上升沿,最终bq1_dat稳定在1,bq2_dat也输出稳定的1。          bq1_dat采样到adat的下降沿,最终bq1_dat稳定在0,bq2_dat也输出稳定的0。 bq1_dat采样到adat的下降沿,最终bq1_dat稳定在1,bq2_dat也输出稳定的1。          最后,从特权同学的经验和实践的角度聊一下。 跨时钟域的信号同步到底需要1级还是2级,完全取决于具体的应用。如果设计中这类跨时钟域信号特别多,增加1级寄存器就等于增加逻辑资源,增加money。如果设计中的跨时钟域信号并非像前面的例子那样快速或实时变化,或者采样时钟频率远高于采样数据,并且我们也并不在意采样数据第1拍的取值,1级寄存器足矣。而对于控制信号,要特别谨慎,通常是比较建议采用2级寄存器同步。 另一个问题,按照判断应该采取2级寄存器的同步设计,设计中就用1级去实现,会怎样?一天、两天、一年、两年,或许都没有问题出现,如何解释?这本身是一个概率的问题,也和跨时钟域信号的故障敏感性有关(所谓故障敏感性,就是它真的出了问题,对系统的影响有多大,设计中是否有机制去检测)。但是,俗话说“常在河边走哪有不湿脚”,问题终究还是要暴露的,有时就像幽灵般转瞬即逝。 “鲁棒性”和“不过设计”都是一个优秀设计不可或缺的因素,我们还是建议认真审查设计,允许1级同步的就绝不堆料(浪费资源),需要2级同步的就不吝啬。

  • 2020-08-17
  • 发表了主题帖: Vivado工程源码大瘦身

      特权同学原创,转载请保留署名 Vivado的工程文件包含了源码、IP、设置和各种编译的中间文件,动辄上百MB甚至上GB,非常占硬盘。可以通过以下步骤对编译过的工程进行瘦身,只预留必要的设置、IP和源码,减少硬盘空间占用。   打开Vivado工程,在Tcl Console中输入reset_project命令(Type a Tcl command here处输入reset_project后回车),删除所有工程编译的中间文件。可以减少30%~70%左右的size,原有工程的“垃圾文件”越多,瘦身得越明显。            左侧显示瘦身前工程文件234MB,右侧显示瘦身后工程文件只有78.8MB。            对于下一步要保留的.srcs工程子文件夹,瘦身更是明显,从124MB直接减少到14.4MB。   点击Vivado菜单File à Project à Write Tcl…。(不同Vivado版本可能Write Tcl菜单位置会有不同,但是都在File菜单中) 弹出的Write Project to Tcl文件夹,在Output File中设置当前工程路径,并输入.tcl为后缀的文件名。Options下勾选Write all properties和Copy sources to new project。点击OK。这个tcl文件中将存储着工程的源码和属性设置信息。将来还原工程时,有这些信息就可以轻松实现。            在工程路径下,产生了一个新创建的at7.tcl文件,这时只需要保留.srcs文件夹和.tcl文件,其它文件或文件夹可以删除。          此时,最后剩下的备份工程源码只有14.5MB。虽然还是不小,但是好歹我们是从234MB的大基数裁剪下来的。这个代码量可以在git上备份了。   最后,来看看基于备份源码,如何还原工程? 在Tcl Console中使用cd命令打开.srcs和.tcl文件的备份路径(如cd D:/Xilinx_prj/at7_project),然后使用source命令(如source at7.tcl)进行工程恢复。            原工程的源码、IP、约束和设置等,完整恢复。

  • 2020-07-02
  • 发表了主题帖: 特权同学2020视频教程《Verilog边码边学(FPGA工具与语法篇)》

    B站视频合集: https://www.bilibili.com/video/BV1Ve411x75W?from=search&seid=71364886936769315      无论是数字IC设计,还是FPGA开发,Verilog都是最基本、最重要的必备技能。而任何一门编程语言的掌握,都不是啃啃语法书,动动脑门儿这么简单的,更何况Verilog这么一门基于硬件的独特语言。由于它最终所实现的数字电路,具备着硬件与生俱来的并行性,所以Verilog的设计思想与思维方式和绝大多数基于软件的编程语言截然不同。而Verilog的设计和验证,也具备一套独特的开发方式,没有哪个复杂的Verilog设计可以写写代码就直接在板子上调试起来了。​“种的是什么,收的也是什么”,一开始输入的每一行Verilog代码,已经决定了最终所实现电路的功能和性能水平;仿真是Verilog开发中非常重要而有效的验证手段,各种代码本身的bug都可以在仿真过程中逐一暴露、定位然后解决。     Verilog的学习没有什么捷径,什么“速成班”都是假的,Gladwell前辈的1万小时定律才是真的,没有大量时间和精力堆砌的空中楼阁迟早是要破灭的。因此,特权同学带着过去10余年1万小时的积累和总结,希望能带着大家一步一个脚印,脚踏实地的在Vivado和Modelsim两个主流的工具中完成Verilog的设计和验证。     FPGA或Verilog的视频教程有很多了,但是能下功夫“陪着”初学者一行一行敲代码的却“踏破铁鞋无觅处”,而这样一门实操性非常强的技能的掌握,绝对离不开动手练习。在这个教程中,会尽可能从无到有输入每一行代码、执行每一个操作,不错过每一个设计的细节;在看完每一个视频,希望好学的您也能动手如法炮制一遍,并且利用课后练习题再做一遍巩固。整个视频课程的安排有一定的随意性,很多语法都是现学现用,以练代讲,也谈不上非常系统,但是只要您按着课程的设定逐个的往下学,相信您一定会慢慢的爱上Verilog,着迷于Modelsim的仿真验证!如果真的是这样,那么这个课程的目的也就达到了。   B站视频合集: https://www.bilibili.com/video/BV1Ve411x75W?from=search&seid=71364886936769315

  • 2020-04-22
  • 发表了主题帖: 特权同学 Verilog边码边学 Lesson01 Vivado下载与安装

    特权同学 Verilog边码边学 Lesson01 Vivado下载与安装 “工欲善其事,必先利其器”,Verilog的学习亦是如此,Vivado、Modelsim和Notepad++就是我们的“利器”。本节视频课程介绍Xilinx官网账户的注册、Vivado软件的下载、并演示Vivado软件的详细安装过程。   前言 无论是数字IC设计,还是FPGA开发,Verilog都是最基本、最重要的必备技能。而任何一门编程语言的掌握,都不是啃啃语法书,动动脑门儿这么简单的,更何况Verilog这么一门基于硬件的独特语言。由于它最终所实现的数字电路,具备着硬件与生俱来的并行性,所以Verilog的设计思想与思维方式和绝大多数基于软件的编程语言截然不同。而Verilog的设计和验证,也具备一套独特的开发方式,没有哪个复杂的Verilog设计可以写写代码就直接在板子上调试起来了。​“种的是什么,收的也是什么”,一开始输入的每一行Verilog代码,已经决定了最终所实现电路的功能和性能水平;仿真是Verilog开发中非常重要而有效的验证手段,各种代码本身的bug都可以在仿真过程中逐一暴露、定位然后解决。 Verilog的学习没有什么捷径,什么“速成班”都是假的,Gladwell前辈的1万小时定律才是真的,没有大量时间和精力堆砌的空中楼阁迟早是要破灭的。因此,特权同学带着过去10余年1万小时的积累和总结,希望能带着大家一步一个脚印,脚踏实地的在Vivado和Modelsim两个主流的工具中完成Verilog的设计和验证。 FPGA或Verilog的视频教程有很多了,但是能下功夫“陪着”初学者一行一行敲代码的却“踏破铁鞋无觅处”,而这样一门实操性非常强的技能的掌握,绝对离不开动手练习。在这个教程中,会尽可能从无到有输入每一行代码、执行每一个操作,不错过每一个设计的细节;在看完每一个视频,希望好学的您也能动手如法炮制一遍,并且利用课后练习题再做一遍巩固。整个视频课程的安排有一定的随意性,很多语法都是现学现用,以练代讲,也谈不上非常系统,但是只要您按着课程的设定逐个的往下学,相信您一定会慢慢的爱上Verilog,着迷于Modelsim的仿真验证!如果真的是这样,那么这个课程的目的也就达到了。

  • 2020-03-04
  • 发表了主题帖: 玩转Zynq连载51——[ex70] RGB2YUV、图像增强、YUV2RGB IP仿真实例

    本帖最后由 ove学习使我快乐 于 2020-3-4 08:35 编辑   1 图像增强IP简介          Xilinx的Vivado中集成的图像增强(Image Enhancement)IP可以有效降低图像噪声并增强图像边缘。该IP使用了2D滤波方式,可以在达到更好的图像噪声抑制同时,保留并增强图像边缘。          如图所示,对于一个比较经典的图像前端处理,图像增强常常也是一个必不可少的步骤。在我们这个实例中,我们需要设计一个右侧图示红圈内的图像流处理。即RGB toYCbCr模块、图像增强模块、YCbCrto RGB模块,这3个模块都有可用的IP核。          图像增强IP的功能框图如下所示。该IP输入和输出的图像数据必须为YUV444或YUV422模式;待处理图像进入IP后,首先需要多行缓存,然后分别通过降噪(Noise Reduction)模块和边缘检测与增强(Edge Map Morphology和Edge Enhance)模块。完成处理后的图像再拟合在一块,最后会通过可选的光环抑制(Anti-halo)和锯齿消除(Anti-alias)模块,完成最终图像输出。边缘增强和噪声抑制实际上是两个完全相反的图像处理方式,为了保证两个模块能够更好的实现增强图像的效果,在这个IP中,第一步做的是图像的形态检测(Edge Map Morphology),然后再根据这个结果,对图像中需要降噪的部分和边缘增强的部分分别处理。   1.1 图像形态检测          图像形态学检测是整个图像增强的第一步,它用于指示后续需要对图像进行降噪或边缘增强操作。图像形态学检测主要包括下面两步:          ①经过二维的FIR滤波器,从水平、垂直以及两个对角共4个维度提取边缘信息。          ②使用拉长、正交的结构单元和形态学处理,用于提供清晰的各个方向边缘信息。   1.2 降噪处理          降噪处理是基于中心像素点以及特定的临近像素点的滤波实现的。算法实现类似高斯的定向低通滤波。噪声门限由IP核的设置决定。图像形态检测信息标定出的边缘不会做任何的降噪处理。   1.3 边缘增强          IP核设定的边缘增强参数决定了边缘增强的幅度。根据边缘检测形态信息,边缘增强模块对标记处的边缘做拉普拉斯滤波,实现边缘增强效果。   1.4 光环抑制与锯齿消除 光环抑制(Anti-halo)和锯齿消除(Anti-alias)模块是可选的功能块。前面进行噪声抑制和边缘增强后的图像,可能存在图像边缘被放大或抑制的情况。光环抑制和锯齿消除,是通过判断每个新的像素值与原图像的像素值以及邻近8个像素值的比较,以判断其是否需要进行相应的处理并实现图像的优化。 如图所示,原图(左侧)在图像增强后可能出现光环现象(中间),那么经过光环抑制后图像(右侧)就能够实现最优化。   2 测试激励说明        使用project\zstar_ex70\matlab文件夹下的Matlab源码image_txt_generation.m产生作为FPGA仿真输入的测试图像数据,存储在image_in_hex.txt中。FPGA仿真测试后,产生图像增强数据存储在FPGA_Enhenchment_Image.txt中,使用Matlab的draw_image_from_FPGA_result.m脚本则可以比对图像增强前后的效果。          3 IP添加与配置          Vivado的IP Catalog中,Video & Image Processing分类下,可以看到有很多可用的图像处理IP核。我们需要用到的RGB toYCbCr、Image Enhancement和YCbCrto RGB这3个IP核,都在该分类下可以找到。   3.1 RGB toYCbCr IP配置 Feature配置页面中,设置图像位宽8bit,分辨率为640*480,YUV格式,输出图像取值范围0~255即可。          Custom配置页面中,可以看到RGB toYCbCr转换的基本公式参数。   3.2 Image Enhancement IP配置          配置页面很简单,设定好图像位宽8bit,图像分辨率640*480,图像噪声抑制(Image Noise Reduction)水平(取值0~255),图像边缘增强(Image Edge Enhancement)水平(取值0~1.0),以及可选的光环抑制(Halo Suppression)和锯齿消除(Anti-Alias Filtering)。   3.3 YCbCrto RGB IP配置 Feature配置页面中,设置图像位宽8bit,分辨率为640*480,YUV格式,输出图像取值范围0~255即可。          Custom配置页面中,可以看到YCbCr to RGB转换的基本公式参数。   4 FPGA仿真          Vivado打开zstar_ex70工程,在Sources面板中,展开Simulation Sources à sim_1,将zstar_image_enhance_sim.v文件设置为top module。点击Flow Navigator面板的Simulation -> Run Simulation打开仿真页面,matlab产生的原始图像数据image_in_hex.txt需要放置在zstar.sim文件夹下,仿真测试结果位于project\zstar_ex70\zstar.sim\sim_1\behav文件夹下。          在设定Noise Threshold = 192,Enhancement Strength = 0.0,Halo Suppression= 0.125时,比对图像如下。          在设定Noise Threshold = 192,Enhancement Strength = 0.125,Halo Suppression =0.75时,比对图像如下。 在设定Noise Threshold = 192,Enhancement Strength = 1.0,Halo Suppression = 0.75时,比对图像如下。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-03-03
  • 发表了主题帖: 玩转Zynq连载50——[ex69] FIR滤波器IP仿真实例

    本帖最后由 ove学习使我快乐 于 2020-3-3 09:13 编辑               1 FIR滤波器简介         FIR(Finite Impulse Response)滤波器,即有限脉冲响应滤波器,又称为非递归型滤波器,是数字信号处理系统中最基本的元件,它可以在保证任意幅频特性的同时具有严格的线性相频特性,同时其单位抽样响应是有限长的,因而滤波器是稳定的系统。因此,FIR滤波器在通信、图像处理、模式识别等领域都有着广泛的应用。                  Vivado集成的FIR IP核可以实现如下公式所示的N级卷积运算。                          FIR IP核可以根据配置实现复用的乘累加单元,以实现面积最优化的设计;当然了,在速度性能要求极高的应用中,也可以配置并行的乘累加单元,以达到最大的FIR数据吞吐量。                           2 FIR IP核配置                  FIRIP配置主页面如图所示。此页面可以配置基本的滤波参数。                          通道配置页面如下。                          输入输出的数据位宽可在Implementation页面配置。                          实现的资源利用情况,如优化选项、存储器选项和DSP Slice选项等,可以在Detailed Implementation页面配置。                          额外的控制接口,可以在Interface页面配置。                          左侧的Freq.Response页面可以参考所使用的FIR滤波参数最终实现的滤波特性(低通、高通、低阻、高阻或带通、带阻等),这里我们使用的是一组IP默认的参数,低通滤波器。                          而左侧的Implementation Details页面,则可以自由利用以及接口等信息。如图所示的ufix16_0表示输入数据为16位的无符号整数,而fix25_0则表示输出结果是25位的有符号整数。                          详细配置可参看pg149-fir-compiler.pdf(/project/zstar_ex69/matlab文件夹下)。                   3 FIR IP核接口时序                  我们例化的FIR IP核,有如下的接口,其功能和端口方向定义如下。         inputaclk;          //时钟信号                   input [15 : 0] s_axis_data_tdata;    //unsigned(16.0),输入数据         inputs_axis_data_tvalid;                   //输入数据有效信号,高电平有效         outputs_axis_data_tready;              //准备好接收输入数据,高电平有效                   output [24 : 0] m_axis_data_tdata;         //signed(25.0),FIR滤波结果输出         outputm_axis_data_tvalid;                        //FIR滤波结果输出有效,高电平有效                  接口时序控制如图所示。图中很多信号本实例不涉及,可以忽略。s_axis_data_tvalid和s_axis_data_tready信号同时拉高时,s_axis_data_tdata被FIR IP核接收,进行处理。当m_axis_data_tvalid拉高时,表示输出FIR滤波结果m_axis_data_tdata有效。                           4 FIR IP仿真                  使用/project/zstar_ex69/matlab文件夹下的test_data_generate_for_fir.m脚本,可以产生一组1000个点的余弦数据,存放在time_domain_cos.txt文件中,这组数据将作为FPGA的仿真输入激励,经过FIR滤波器进行滤波处理。         clc;clear `all;close all;                   format long g                   Fs = 1000;                    % Sampling frequency         T = 1/Fs;                     % Sampling period         L = 1000;                     % Length of signal         t = (0:L-1)*T;                % Time vector                   x1 = cos(2*pi*50*t)*(2^13);          % First row wave                   %output time domain data         x1_fix = round(x1,0);    %convert to fixed signed(3.13)         x1_fix(find(x1_fix<0)) = x1_fix(find(x1_fix<0))+(2^16);         fid0 = fopen('time_domain_cos.txt', 'wt');         fprintf(fid0, '%16x\n', x1_fix);         fid0 = fclose(fid0);                  FPGA工程zstar_ex69的顶层是一个测试脚本,zstar_fir_sim.v文件。该测试脚本将time_domain_cos.txt文件的1000个数据读入,然后依次送入FIR滤波器IP核进行处理,输出结果写入fir_result.txt文本中。         `timescale 1ns/1ps         module zstar_fir_sim(             );                          reg clk;                       reg [15 : 0] s_axis_data_tdata;       //unsigned(16.0)         reg s_axis_data_tvalid;         wire s_axis_data_tready;                   wire [31 : 25] null;         wire [24 : 0] m_axis_data_tdata;    //signed(25.0)         wire m_axis_data_tvalid;                   parameter DATA_NUM = 1000;                          ////////////////////////////////////////////////////         //FIR IP Core                      fir_compiler_0  uut_fir_compiler_0 (         .aclk(clk),                              // input wire aclk         .s_axis_data_tvalid(s_axis_data_tvalid),  // input wire s_axis_data_tvalid         .s_axis_data_tready(s_axis_data_tready),  // output wire s_axis_data_tready         .s_axis_data_tdata(s_axis_data_tdata),    // input wire [15 : 0] s_axis_data_tdata           .m_axis_data_tvalid(m_axis_data_tvalid),  // output wire m_axis_data_tvalid           .m_axis_data_tdata({null,m_axis_data_tdata})    // output wire [31 : 0] m_axis_data_tdata         );                          ////////////////////////////////////////////////////               integer i;                   reg[15:0] data_mem [DATA_NUM-1:0];                   initial #500 $readmemh("../../time_domain_cos.txt",  data_mem);                                        initial begin                  clk = 0;                                   s_axis_data_tdata<= 16'd0;                  s_axis_data_tvalid<= 1'b0;                                                    #1000;                  @(posedgeclk);                            i<= 1;                  #10000;                            @(posedgeclk);                                                   #100_000;                                   $fclose(w1_file);                  #1000;                  $stop;         end                    always @(*) begin                  if((i>0) && (i<DATA_NUM+1)) s_axis_data_tdata<= data_mem[i-1];                  else s_axis_data_tdata<= 16'd0;         end                    always @(posedgeclk) begin                  if(i == 0) i<= 0;                  else if(i<= DATA_NUM) begin                             if(s_axis_data_tready&&s_axis_data_tvalid) i<= i+1;                            else ;                  end                  else if(i< DATA_NUM+26) i<= i+1;                  else ;         end                   always @(posedgeclk) begin                  if((i>=1) && (i<=DATA_NUM-1)) s_axis_data_tvalid<= 1'b1;                   else s_axis_data_tvalid<= 1'b0;         end                             always #10 clk = ~clk;                                            integer w1_file;                   initial w1_file = $fopen("./fir_result.txt","w");                                          always @(posedgeclk) begin                  if(m_axis_data_tvalid) begin                            $fwrite(w1_file, "%x\n", m_axis_data_tdata);                        end          end                           endmodule                  如图所示,Vivado中打开zstar_ex69工程,在Project Manager à Simulation Sources à sim_1下,看到top module为高亮的zstar_fir_sim.v模块,点击Flow Navigator à Simulation à Run Simulation可以启动仿真。                          运行仿真如图。                 仿真的结果将写入生成的fir_result.txt文本(位于zstar_ex69\zstar.sim文件夹的子文件夹中),将该文本放置到matlab文件夹中,运行matlab脚本draw_wave_from_txt.m,可以查看正弦数据FIR滤波前后的波形比对。在时域看来,峰或谷的位置是高频,因此都被FIR滤波处理了。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处    

  • 2020-03-02
  • 发表了主题帖: 玩转Zynq连载49——[ex68] MT9V034摄像头的图像FFT滤波处理

    本帖最后由 ove学习使我快乐 于 2020-3-2 09:40 编辑   1 关于傅里叶变换          关于傅里叶变换,这么一个神奇的变换,其基本原理和应用在教科书、网络上漫天飞舞,这里就不赘述了,以免有凑字数的嫌疑。前面的例子我们已经使用Matlab和Vivado的FFT IP核进行了初步的验证,掌握的FFT/IFFT IP核的脾气,那么接下来我们要玩点真的了,基于我们Zstar板采集到的MT9V034图像,我们要进行每个行的FFT和IFFT变换,当然,生成的FFT结果我们可以进行必要的滤波,然后再进行IFFT查看滤波效果。   2 基于Matlab的FFT滤波          使用project\zstar_ex68\matlab文件夹下的Matlab源码image_1D_fft_ifft.m或L1024_of_image_1D_fft_ifft.m(将640个点扩展为1024个点进行FFT变换,扩展的点以0填充,模拟FPGA的FFT IP核实际工作状况),对测试图像test进行FFT变换,进行必要的滤波,然后IFFT逆变换。          测试图像为彩色图像,原始图像如下。          首先进行彩色转灰度的变换,灰度图像如下。          提取出其中1行进行FFT变换后的图像频谱如下。很明显,大部分高频分量集中在前面几个点,而后面的点几乎频率都很小。          放大频谱图,看到细节如下。这里绘制了一条取值为300的直线,有将近50%的频谱集中在这条线以下。若是做图像压缩,其实我们可以把这些低频分量忽略了,那么数据量可能会大大降低,当然了,副作用是图像可能会有一定程度的失真,有失必有得嘛。滤除这些低频分量,也会使图像更锐一些。话说做FFT变换的目的可远不止这些,在一些特殊的应用场景中,我们总是希望从原始图像中提取出一些和应用直接相关的特征信息,那么做了FFT后的图像常常非常有益于这些操作。为了演示,这里我们的代码里面就将这些低于300的点都滤除,即取0。          从频谱图上看,如图所示,右侧的滤波后明显图像偏黑(很多值取0了)了。          我们重新把原图放到这里,和FFT滤波并IFFT以后的图像做比对,图像整体仍然保持不变,但是查看细节,可以发现处理后的图像明显锐了一些。          Matlab源码如下: clc;clear `all;close all;   IMAGE_WIDTH = 640; IMAGE_HIGHT = 480;   %load origin image %I = imread('Lena_gray_niose.bmp');  I = imread('test.bmp');    I = rgb2gray(I);   %fclose(fid1);     %% output image data in hex file raw_image = reshape(I, IMAGE_HIGHT, IMAGE_WIDTH); raw_image = raw_image'; fid2 = fopen('image_in_hex.txt', 'wt');   fprintf(fid2, '%04x\n', raw_image); fid2 = fclose(fid2);     %show origin image figure,imshow(I); title('Original image');   %1D fft base on every image line II = zeros(IMAGE_HIGHT,1024); J = zeros(IMAGE_HIGHT,1024); for i = 1:IMAGE_HIGHT     for j = 1:IMAGE_WIDTH         II(i,j) = I(i,j);     end         J(i,:  ) = fft(II(i, :  ));%fft(I(i, :  )); end   %show 1 line fft result t1 = (0:IMAGE_WIDTH);                % Time vector line = ones(IMAGE_WIDTH) * 200;   figure; plot(t1(1:IMAGE_WIDTH),abs(J(50,1:IMAGE_WIDTH)),t1(1:IMAGE_WIDTH),line(1:IMAGE_WIDTH)) title(['1 line image in the Frequency Domain'])   %show fft of origin image figure,imshow(log(abs(J)),[]);  title('1D fft image base on every image line'); %colormap(jet(64)),colorbar;   %fft fiter J(abs(J) < 300) = 0;                 %J(abs(J) > 1000) = 1000;     %show fft of fft filter image figure,imshow(log(abs(J)),[]);  title('1D fft image after filter');   %1D ifft base on every image line K = zeros(IMAGE_HIGHT,1024); for i = 1:IMAGE_HIGHT     K(i,:  ) = real(ifft(J(i,:  ))); end   KK = zeros(IMAGE_HIGHT,IMAGE_WIDTH);   for i = 1:IMAGE_HIGHT     for j = 1:IMAGE_WIDTH         KK(i,j) = K(i,j);     end end   %show ifft image figure,imshow(KK,[])                      title('1D ifft image');   3 FPGA仿真          在Sources面板中,展开Simulation Sources à sim_1,将sim_fft.v文件设置为top module。同样是对前面的测试图像,经过FFT和IFFT变换后存储在image_view0.txt文本中(仿真测试结果位于project\zstar_ex68\zstar.sim\sim_1\behav文件夹下)。为了确认FFT和IFFT IP核运算的精度和效果,这里没有做任何的滤波处理。          使用draw_image_from_FPGA_result.m脚本(project\zstar_ex68\ matlab文件夹下)导入image_view0.txt文本的图像,和原始图像比对如下所示。看到图像几乎没有任何失真。   4 基于FPGA的图像平滑处理        工程文件夹project\zstar_ex688\zstar.srcs\sources_1\new下的image_fft_filter.v模块以及3个子模块image_fft_controller.v、image_filter.v和image_ifft_controller.v实现了图像的FFT变换、滤波和IFFT变换处理。FPGA设计的功能框图如下。          image_fft_controller.v模块例化FFT IP核,将采集的图像留以行为单位输入到FFT IP核,输出FFT频域数据。 image_filter.v模块对FFT频域数据计算绝对值并进行必要的滤波处理,假设FFT结果的实部值为a,虚部值为b,那么其绝对值abs =sqrt(a^2+b^2)。如下代码,注释部分可以滤除低频分量,当前例程中为了验证FFT和IFFT变换后精度没有损失,未作滤波。 always @(posedge clk or negedge rst_n)                          if(!rst_n) begin                    o_image_filter_data_image <= 20'd0;                    o_image_filter_data_real <= 20'd0;          end          /*else if(sqrt_fft[19:0] < 20'd300) begin //此处可以做必要的高频或低频滤波处理                    o_image_filter_data_image <= 20'd0;                    o_image_filter_data_real <= 20'd0;          end*/          else begin                    o_image_filter_data_image <= r_image_fft_data_image[TOTAL_LATENCY-1];                    o_image_filter_data_real <= r_image_fft_data_real[TOTAL_LATENCY-1];          end image_ifft_controller.v模块将滤波处理后的FFT结果进行IFFT变换,图像转回时域值,供后续模块缓存DDR3并显示。   5 装配说明          MT9V034摄像头模块通过Zstar ISB底板(P3)与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图所示。 6 板级调试          本实例对应ex68实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex68\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电,可以看到VGA显示器同时显示左右两个图像,左侧图像为原始图像,右侧图像为经过FFT和IFFT后还原的图像。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-28
  • 发表了主题帖: 玩转Zynq连载48——[ex67] Vivado FFT和IFFT IP核应用实例

      1 关于傅里叶变换          关于傅里叶变换,这么一个神奇的变换,其基本原理和应用在教科书、网络上漫天飞舞,这里就不赘述了,以免有凑字数的嫌疑。下面我们就Matlab和FPGA两个工具双管齐下,比对Vivado的FFT IP核生成的数据。   2 Matlab产生测试数据,绘制cos时域和频域波形          使用project\zstar_ex67\matlab文件夹下的Matlab源码fft_1line.m,运行产生1组cos波形的1000个采样点数据,存储为time_domain_cos.txt文件,该文件中每个数据位宽16bit,定点signed(1.15),即最高位符号位,15位小数。同时,绘制出matlab中cos时域和频域的波形如下。   3 Vivado中添加配置FFT IP核          Vivado中,打开IP Catalog,搜索FFT或者找到分类Core à Digital Signal Processing àTransform à FFTs,即可找到免费的IP核Fast Fourier Transform。双击这个IP。          第一个Configuration页面如图,可以设定IP通道数(Number of Channels)、FFT转换长度(Transform Length)、目标时钟频率(Target Clock Frequency)和FFT实现架构(Architecture Choice)等。          如图所示,第二个Implementation页面,可以配置数据格式(Data Format)、缩放模式(Scaling Options)、数据末尾处理方式(Rounding Modes)、输入数据和相位的位宽(Input Data Width)和数据输出顺序(Output Ordering)等。          第三个Detailed Implement页面中,可以对FPGA存储器或乘法器相关的资源进行选择配置。          在配置页面左侧,可以查看IP接口(IP Symbol)、实现信号位宽细节(Implementation Details)和输出时延(Latency)等信息。   4 使用FPGA的IP进行FFT运算          使用Vivado 16.2打开project\zstar_ex67下的工程,在Sources面板中,展开Simulation Sources à sim_1,确认zstar_fft_sim文件为top module(粗体显示文件名),若不是top module,可以右键单击该文件,点击Set as Top菜单项。如图,若Set as Top菜单项为灰暗不可点击状态,表示当前该模块已经是top module。zstar_fft_sim文件中用测试脚本的形式,将matlab生成的1000个点cos数据time_domain_cos.txt文本导入,送给FFT IP核进行运算,输出FFT结果的实部和虚部分别存储在fft_result_real.txt和fft_result_image.txt文本中(仿真测试结果位于project\zstar_ex67\zstar.sim\sim_1\behav文件夹下)。          在Flow Navigator面板中,展开Simulation,点击Run Simulation,弹出菜单中点击Run Behavioral Simulation进行仿真。          弹出仿真界面后,如图所示点击Run All图标运行仿真。          仿真运行完毕,可以看到FFT的输入数据波形和结果输出波形如图所示。          可以打开project\zstar_ex67\zstar.sim\sim_1\behav文件夹下fft_result_real.txt和fft_result_image.txt文本,分别存储FFT结果的实部和虚部。这里需要注意定点的小数位问题。在IP核页面左侧,点击Implementation Details可以看到定点的小数位标定。所有1024个输入点的位宽定义是一样的,所以如图所示,只需要查看第0点的定点标定信息。          详细的FFT IP核配置说明,可以参考Xilinx官方文档pg109-xfft.pdf。          对于仿真产生的fft_result_real.txt和fft_result_image.txt文本,可以使用Matlab脚本draw_wave_from_txt.m(project\zstar_ex67\matlab文件夹下)进行加载并绘制波形。FPGA实现的FFT运算结果,绘制波形如下。可以比对Matlab的波形,几乎是一致的。当然了,因为FPGA输入数据的精度有限(从浮点到定点的精度损失),不可能完全一致。   5 使用FPGA的IP进行IFFT运算          在Sources面板中,展开Simulation Sources à sim_1,将zstar_ifft_sim.v文件设置为top module。zstar_ifft_sim文件中用测试脚本的形式,在zstar_fft_sim.v测试脚本产生的FFT结果的基础上,继续将此结果进入IFFT IP核进行IFFT运算,最终上传IFFT的结果。输出IFFT结果的实部存储在ifft_result.txt文本中(仿真测试结果位于project\zstar_ex67\zstar.sim\sim_1\behav文件夹下)。可以比对这个文本和time_domain_cos.txt文本的数据,几乎是一致的。          xfft_0输出的FFT结果是定点signed(12.15),要获得最终的FFT结果,需要将IP核输出的结果再除以FFT数据个数(即1024),所以我们可以认为实际的FFT结果是定点signed(2.25)。 而进入xfft_1做IFFT的输入接口是定点signed(1.26),二者并不匹配,则我们认为输入数据做了1位的右移,在IFFT输出结果时要对应的左移1位。IFFT的输出是signed(12.26),那么左移1位后,就是signed(13.25)。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-27
  • 发表了主题帖: 玩转Zynq连载47——[ex66] MT9V034摄像头的图像直方图均衡处理

      1 系统概述 如图所示,这是整个视频采集系统的原理框图。 上电初始,FPGA需要通过IIC接口对CMOS Sensor进行寄存器初始化配置。这些初始化的基本参数,即初始化地址对应的初始化数据都存储在一个预先配置好的FPGA片内ROM中。在初始化配置完成后,CMOS Sensor就能够持续输出标准RGB的视频数据流,FPGA通过对其同步信号,如时钟、行频和场频进行检测,从而从数据总线上实时的采集图像数据。MT9V034摄像头默认初始化数据就能输出正常的视频流,因此FPGA中实际上未作任何IIC初始化配置。 在FPGA内部,采集到的视频数据先通过一个FIFO,将原本25MHz频率下同步的数据流转换到50MHz的频率下。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会通过AXI HP0总线写入DDR3中。与此同时,AXI HP0总线也会读取DDR3中缓存的图像数据,缓存到FIFO中,并最终送往LCD驱动模块进行显示。LCD驱动模块不断的发出读图像数据的请求,并驱动液晶显示器显示视频图像。 本实例除了前面提到对原始图像做DDR3缓存和显示,还会在原始图像缓存到DDR3之前,会对当前图像做直方图统计(以帧为单位做统计),统计后的直方图结果进行均衡运算,获得新的图像映射数据,然后用于紧随着的下一帧图像,这样,后续的每一帧图像都会基于前一帧图像的直方图均衡运算结果计算出新的图像流,这个图像流通过AXI HP1总线写入到DDR3中。AXI HP1总线也会根据LCD显示模块的请求,读取处理后的图像进行显示。最终在VGA液晶显示器上,可以看到左侧图像是原始的图像,右侧图像是经过直方图均衡运算处理后的图像。 2图像直方图均衡处理 2.1 基本概念、原理与方法 直方图增强是调整图像直方图到一个预定的形状。例如,一些图像由于其灰度分布集中在较窄的取件,对比度很弱,图像细节看不清楚。此时,可采用图像灰度直方图均衡化处理,使得图像的对比度增大。加大图像动态范围,扩展图像对比度,使图像清晰,特征明显。 2.1.1 直方图的基本概念 图像直方图是用来表达一幅图像灰度级分布情况的统计表。它反映图像整体灰度值的分布情况,即图像的明暗情况和图像灰度级动态范围。 (1)直方图 直方图的全称为灰度统计直方图,是对图像每一灰度间隔内像素个数的统计,一般的间隔取为1。通常可用一个一维的离散函数来表示: h(k)= nk , k = 0 , 1 , ... , L-1 其中,k表示图像中第k级灰度值;nk表示图像中第k级灰度值的像素个数。 如图所示为原始Lena灰度图像及其直方图。 (2)归一化直方图 用图像中像素的总个数N去除nk的每一个值,得到归一化直方图: p(k)= nk/N    k = 0 , 1 , ... , L-1 其中,p(k)表示一幅图像中灰度级k出现的频率。注意∑p(k)= 1。 图像的灰度直方图p(k)是一个一维离散函数,它给出了灰度取值k发生概率的一个估计,反应图像的灰度分布情况,是从总体上描述图像的一种方法。 2.1.2 直方图均衡的原理 直方图均衡可以将任意分布规律直方图的原始图像变换为具有均匀分布直方图的图像。 显然,直方图均衡化可以增加像素灰度值的动态范围,使每一灰度层次所占的像素个数尽量均等,可以改善图像的整体对比度。 下面在灰度值为模拟量的情况下讨论直方图均衡的算法原理。 1)基本思想 把原始图的直方图变换为均匀分布的形式,增加像素灰度值的动态范围以增强图像整体对比度。 2)均衡定义 将图像转换为具有均匀分布直方图的图像,这一过程叫做直方图均衡。一般认为直方图p(k)为常数的图像具有高对比度和多变的灰度层次。 对于每一个像素点(x,y),若原始图像灰度值为f(x,y)= k,经过增强处理后成为 g(x,y)= k',则增强变换函数为,其中k' = T(k)k = 0 , 1 , ... , L-1。 这样直方图均衡的问题就转化为:寻找一个变换函数T(r),使变换后图像灰度的概率密度函数ps(s)= 1,即期望输出图像中每一灰度级有相同的概率。 3)算法原理 设s可由T(r)得到,即 s = T(r) 0 ≤ r ≤ 1 变换T(r)需要满足两个条件: (1)T(r)在区间0 ≤ r ≤ 1上为单值且单调递增; (2)当0 ≤ r ≤ 1时,0 ≤ s ≤ 1。 相应的反变换为: r = T -1(s) 0 ≤ s ≤ 1 反变换T -1(s)也满足上述两个条件。 以连续图像为例,分析T(r)变换推到的过程: 要求dr和ds区间内像素点个数是不变的,有: 当dr→0,ds→0,略去下标j,由于s = T(r),p(s)= 1,则最终得到直方图均衡化的灰度变换函数为: S称作原始图像灰度级r的累积分布函数,可以验证S满足前述两个条件。如图显示了连续图像的直方图均衡原理。   2.1.3 直方图均衡的方法 1)均衡过程 对于数字图像,其直方图均衡化处理的计算步骤如下: (1)统计原始图像的归一化直方图。 其中,rk是归一化的输入图像灰度级。 (2)用累积分布函数作变换函数进行图像灰度变换。 (3)建立输入图像与输出图像灰度级之间的对应关系,将变换后灰度级回复成原先的灰度级分为。 与连续形式不同,一般不能证明离散变换能够产生均匀概率密度函数的离散值(均匀直方图)。但是可以很容易看出,此算式的应用有展开输入图像直方图的一般趋势,因此均衡后的图像灰度级能够跨越更大的动态范围。 2)均衡示例 下面给出一个例子说明数字图像直方图均衡的处理过程。 设一幅图像的尺寸为64*64,像素的灰度层次L = 8(8个灰度等级)。则该图像共有 N = 64 * 64 = 4096个像素,如图为图像的直方图。 该图像共有4096个像素点,每个像素用3个比特表示,有0~7共8个灰度。原始图像的灰度分布情况从下表中可以看出,灰度的频率最小为0.02,最大为0.25。显然,直方图呈非均匀分布。 直方图均衡化处理的计算过程和结果如下表所示。 直方图均衡化处理的计算过程和结果 结果如下图所示。   3)图像直方图均衡后分析 (1)变换后直方图趋于平坦,灰度级减少,灰度进行了合并。 (2)变换后含有像素数多的几个灰级间隔被拉大了,压缩的只是像素数少的几个灰度级,实际视觉能够接收的信息量大大地增强了。 可见,直方图均衡处理可以使像素灰度的动态范围增加,有时能够明显改善图像的视觉效果。 下图给出四幅实际图像的直方图均衡效果。 可以看出,应用直方图均衡,明显改善了原始灰度级别动态范围较窄的图像的视觉效果。   2.2 Matlab实现          对一幅给定图像做直方图均衡处理,我们的Matlab代码如下: %load origin image I = imread('Lena_gray.bmp');      %show origin image and its histogram diagram figure(1)    subplot(2,2,1)    imshow(I)          title('Origin Image')    subplot(2,2,2)    imhist(I)          title('Histogram of Origin Image')          %histogram calculation [height,width] = size(I);        nk = zeros(1,256);           for i = 1:height        for j = 1: width            nk(I(i,j)+1)=nk(I(i,j)+1)+1;     end    end        pk = zeros(1,256);  pk=nk./(height*width);   %histogram equalization sk = zeros(1,256);    sk(1) = pk(1);  for i = 2:256             sk(i) = sk(i - 1) + pk(i);    end      kt=zeros(1,256);    kt = uint8(255 .* sk);   F=zeros(size(I)); for i = 1:height        for j = 1: width             F(i,j) = kt(I(i,j)+1);      end    end   %% output kt M = F'; fidkt = fopen('image_out_hex.txt', 'wt'); fprintf(fidkt, '%x\n', M); fidkt = fclose(fidkt);     %show image after hitogram equalization F=uint8(F); subplot(2,2,3)    imshow(F)          title('Histogram Equalization Image')    subplot(2,2,4)    imhist(F)          title('Image of Histogram Equalization Image')           滤波效果如下。可以看到原图比较灰暗,对比度不强,它的直方图统计结果显示,它的大部分像素值集中在0~100的区域内。而做过直方图均衡的图像,对比度明显增强,图像也相对更清晰,随着而来的可能是图像的噪点也被凸显出来,从它的直方图看,从原图比较集中在局部,变化为在真个0~255区间相对均匀的分布,这就是直方图均衡希望达到的效果。          Matlab源码、Lena_gray.jpg原图和比对图存放在project\zstar_ex66\matlab文件夹下。 3 基于FPGA的直方图均衡处理          工程文件夹project\zstar_ex66\zstar.srcs\sources_1\new下的laplace_transform.v模块实现了图像的拉普拉斯边缘提取处理。该模块功能框图如下,使用2个FIFO,分别缓存前后行,即进入图像处理的3组数据流分别是第n-1行、第n行和第n+1行的图像,控制输入数据流和2个FIFO缓存的图像在同一个位置、寄存器对前后2个像素的图像值进行缓存,这样便可实现中心像素点以及前后列、上下行之间数据的同步处理了。 4 装配说明          MT9V034摄像头模块通过Zstar ISB底板(P3)与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图所示。   5 板级调试          本实例对应ex66实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex66\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电,可以看到VGA显示器同时显示左右两个图像,左侧图像为原始图像,右侧图像为直方图均衡处理后图像。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-26
  • 发表了主题帖: 玩转Zynq连载46——[ex65] MT9V034摄像头的图像拉普拉斯边缘提取

      1 系统概述 如图所示,这是整个视频采集系统的原理框图。上电初始,FPGA需要通过IIC接口对CMOS Sensor进行寄存器初始化配置。这些初始化的基本参数,即初始化地址对应的初始化数据都存储在一个预先配置好的FPGA片内ROM中。在初始化配置完成后,CMOS Sensor就能够持续输出标准RGB的视频数据流,FPGA通过对其同步信号,如时钟、行频和场频进行检测,从而从数据总线上实时的采集图像数据。MT9V034摄像头默认初始化数据就能输出正常的视频流,因此FPGA中实际上未作任何IIC初始化配置。 在FPGA内部,采集到的视频数据先通过一个FIFO,将原本25MHz频率下同步的数据流转换到50MHz的频率下。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会通过AXI HP0总线写入DDR3中。与此同时,AXI HP0总线也会读取DDR3中缓存的图像数据,缓存到FIFO中,并最终送往LCD驱动模块进行显示。LCD驱动模块不断的发出读图像数据的请求,并驱动液晶显示器显示视频图像。 本实例除了前面提到对原始图像做DDR3缓存和显示,还会在原始图像缓存到DDR3之前,另外做图像的多行缓存和拉普拉斯边缘提取处理,获得新的图像流,这个图像流通过AXI HP1总线写入到DDR3中。AXI HP1总线也会根据LCD显示模块的请求,读取处理后的图像进行显示。最终在VGA液晶显示器上,可以看到左侧图像是原始的图像,右侧图像是经过边缘提取处理后的图像。   2 图像拉普拉斯边缘提取 2.1 基本概念 在图像增强中,平滑是为了消除图像中噪声的干扰,或者降低对比度。与之相反,有时为了强调图像的边缘和细节,需要对图像进行锐化,提高对比度。 拉普拉斯锐化图像是根据图像某个像素的周围像素到此像素的突变,也就是说它的依据是图像像素的变化程度。我们知道,一个函数的一阶微分描述了函数图像是朝哪里变化的,即增长或者降低;而二阶微分描述的则是图像变化的速度,急剧增长下降还是平缓的增长下降。那么据此我们可以猜测出依据二阶微分能够找到图像的色素的过渡程度,例如白色到黑色的过渡就是比较急剧的。 或者用官方点的话说:当邻域中心像素灰度低于它所在的领域内其它像素的平均灰度时,此中心像素的灰度应被进一步降低,当邻域中心像素灰度高于它所在的邻域内其它像素的平均灰度时,此中心像素的灰度应被进一步提高,以此实现图像的锐化处理。 2.2 拉普拉斯(laplace)算子 最常用的无方向性的二阶差分算子,其模板有3*3、5*5和7*7等多种形式。。          例如,以3*3算子为例,1~8像素是(x,y)点周围邻近的8个像素点。可以使用右侧的2种模板对(x,y)以及周边8个像素点进行运算,替代原来的(x,y)点。 2.3 Matlab实现          基于第2种拉普拉斯边缘提取算子,我们的Matlab代码如下: clear clc I1=imread('.\lena.jpg'); I=im2double(I1); [m,n,c]=size(I); A=zeros(m,n,c);   %for R for i=2:m-1     for j=2:n-1         A(i,j,1)=I(i-1,j-1,1)+I(i+1,j-1,1)+I(i-1,j+1,1)+I(i+1,j+1,1)+I(i+1,j,1)+I(i-1,j,1)+I(i,j+1,1)+I(i,j-1,1)-8*I(i,j,1);     end end   %for G for i=2:m-1     for j=2:n-1         A(i,j,2)=I(i-1,j-1,2)+I(i+1,j-1,2)+I(i-1,j+1,2)+I(i+1,j+1,2)+I(i+1,j,2)+I(i-1,j,2)+I(i,j+1,2)+I(i,j-1,2)-8*I(i,j,2);     end end   %for B for i=2:m-1     for j=2:n-1         A(i,j,3)=I(i-1,j-1,3)+I(i+1,j-1,3)+I(i-1,j+1,3)+I(i+1,j+1,3)+I(i+1,j,3)+I(i-1,j,3)+I(i,j+1,3)+I(i,j-1,3)-8*I(i,j,3);     end end   B=A;   %output imwrite(B,'lena.tif','tif'); imshow('.\lena.jpg');title('origin image');figure imshow('lena.tif');title('image after laplace transform')          滤波效果如下。          Matlab源码、Lena.jpg原图和比对图存放在project\zstar_ex65\matlab文件夹下。 3 基于FPGA的图像平滑处理          工程文件夹project\zstar_ex65\zstar.srcs\sources_1\new下的laplace_transform.v模块实现了图像的拉普拉斯边缘提取处理。该模块功能框图如下,使用2个FIFO,分别缓存前后行,即进入图像处理的3组数据流分别是第n-1行、第n行和第n+1行的图像,控制输入数据流和2个FIFO缓存的图像在同一个位置、寄存器对前后2个像素的图像值进行缓存,这样便可实现中心像素点以及前后列、上下行之间数据的同步处理了。   4 装配说明          MT9V034摄像头模块通过Zstar ISB底板(P3)与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图所示。   5 板级调试          本实例对应ex65实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex65\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电,可以看到VGA显示器同时显示左右两个图像,左侧图像为原始图像,右侧图像为拉普拉斯边缘提取处理后图像。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-25
  • 发表了主题帖: 玩转Zynq连载45——[ex64] MT9V034摄像头的图像拉普拉斯锐化处理

      1 系统概述 如图所示,这是整个视频采集系统的原理框图。上电初始,FPGA需要通过IIC接口对CMOS Sensor进行寄存器初始化配置。这些初始化的基本参数,即初始化地址对应的初始化数据都存储在一个预先配置好的FPGA片内ROM中。在初始化配置完成后,CMOS Sensor就能够持续输出标准RGB的视频数据流,FPGA通过对其同步信号,如时钟、行频和场频进行检测,从而从数据总线上实时的采集图像数据。MT9V034摄像头默认初始化数据就能输出正常的视频流,因此FPGA中实际上未作任何IIC初始化配置。 在FPGA内部,采集到的视频数据先通过一个FIFO,将原本25MHz频率下同步的数据流转换到50MHz的频率下。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会通过AXI HP0总线写入DDR3中。与此同时,AXI HP0总线也会读取DDR3中缓存的图像数据,缓存到FIFO中,并最终送往LCD驱动模块进行显示。LCD驱动模块不断的发出读图像数据的请求,并驱动液晶显示器显示视频图像。 本实例除了前面提到对原始图像做DDR3缓存和显示,还会在原始图像缓存到DDR3之前,另外做图像的多行缓存和拉普拉斯锐化处理,获得新的锐化后的图像流,这个图像流通过AXI HP1总线写入到DDR3中。AXI HP1总线也会根据LCD显示模块的请求,读取处理后的图像进行显示。最终在VGA液晶显示器上,可以看到左侧图像是原始的图像,右侧图像是经过锐化处理后的图像。   2 图像拉普拉斯锐化 2.1 基本概念 在图像增强中,平滑是为了消除图像中噪声的干扰,或者降低对比度。与之相反,有时为了强调图像的边缘和细节,需要对图像进行锐化,提高对比度。 拉普拉斯锐化图像是根据图像某个像素的周围像素到此像素的突变,也就是说它的依据是图像像素的变化程度。我们知道,一个函数的一阶微分描述了函数图像是朝哪里变化的,即增长或者降低;而二阶微分描述的则是图像变化的速度,急剧增长下降还是平缓的增长下降。那么据此我们可以猜测出依据二阶微分能够找到图像的色素的过渡程度,例如白色到黑色的过渡就是比较急剧的。 或者用官方点的话说:当邻域中心像素灰度低于它所在的领域内其它像素的平均灰度时,此中心像素的灰度应被进一步降低,当邻域中心像素灰度高于它所在的邻域内其它像素的平均灰度时,此中心像素的灰度应被进一步提高,以此实现图像的锐化处理。 2.2 拉普拉斯(laplace)算子 最常用的无方向性的二阶差分算子,其模板有3*3、5*5和7*7等多种形式。。          例如,以3*3算子为例,1~8像素是(x,y)点周围邻近的8个像素点。可以使用右侧的2种模板对(x,y)以及周边4或8个像素点进行运算,替代原来的(x,y)点。          当然了,根据中心点的权重程度,也可以使用如下2中模板来实现图像锐化。 2.3 Matlab实现          基于第一种拉普拉斯锐化处理,我们的Matlab代码如下: clear clc I1=imread('.\lena.jpg'); I=im2double(I1); [m,n,c]=size(I); A=zeros(m,n,c);   %for R for i=2:m-1     for j=2:n-1         A(i,j,1)=I(i+1,j,1)+I(i-1,j,1)+I(i,j+1,1)+I(i,j-1,1)-4*I(i,j,1);     end end   %for G for i=2:m-1     for j=2:n-1         A(i,j,2)=I(i+1,j,2)+I(i-1,j,2)+I(i,j+1,2)+I(i,j-1,2)-4*I(i,j,2);     end end   %for B for i=2:m-1     for j=2:n-1         A(i,j,3)=I(i+1,j,3)+I(i-1,j,3)+I(i,j+1,3)+I(i,j-1,3)-4*I(i,j,3);     end end   B=I-A;   %output imwrite(B,'lena.tif','tif'); imshow('.\lena.jpg');title('origin image');figure imshow('lena.tif');title('image after laplace transform')          滤波效果如下。          Matlab源码、Lena.jpg原图和比对图存放在project\zstar_ex64\matlab文件夹下。 3 基于FPGA的图像平滑处理          工程文件夹project\zstar_ex64\zstar.srcs\sources_1\new下的laplace_transform.v模块实现了拉普拉斯锐化处理。该模块功能框图如下,使用2个FIFO,分别缓存前后行,即进入图像处理的3组数据流分别是第n-1行、第n行和第n+1行的图像,控制输入数据流和2个FIFO缓存的图像在同一个位置、寄存器对前后2个像素的图像值进行缓存,这样便可实现中心像素点以及前后列、上下行之间数据的同步处理了。   4 装配说明          MT9V034摄像头模块通过Zstar ISB底板(P3)与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图所示。 5 板级调试          本实例对应ex64实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex64\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电,可以看到VGA显示器同时显示左右两个图像,左侧图像为原始图像,右侧图像为锐化处理后图像。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-24
  • 发表了主题帖: 玩转Zynq连载44——[ex63] MT9V034摄像头的图像平滑处理

      1 系统概述 如图所示,这是整个视频采集系统的原理框图。上电初始,FPGA需要通过IIC接口对CMOS Sensor进行寄存器初始化配置。这些初始化的基本参数,即初始化地址对应的初始化数据都存储在一个预先配置好的FPGA片内ROM中。在初始化配置完成后,CMOS Sensor就能够持续输出标准RGB的视频数据流,FPGA通过对其同步信号,如时钟、行频和场频进行检测,从而从数据总线上实时的采集图像数据。MT9V034摄像头默认初始化数据就能输出正常的视频流,因此FPGA中实际上未作任何IIC初始化配置。 在FPGA内部,采集到的视频数据先通过一个FIFO,将原本25MHz频率下同步的数据流转换到50MHz的频率下。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会通过AXI HP0总线写入DDR3中。与此同时,AXI HP0总线也会读取DDR3中缓存的图像数据,缓存到FIFO中,并最终送往LCD驱动模块进行显示。LCD驱动模块不断的发出读图像数据的请求,并驱动液晶显示器显示视频图像。 本实例除了前面提到对原始图像做DDR3缓存和显示,还会在原始图像缓存到DDR3之前,另外做图像的多行缓存和平滑处理运算,获得新的平滑后的图像流,这个图像流通过AXI HP1总线写入到DDR3中。AXI HP1总线也会根据LCD显示模块的请求,读取处理后的图像进行显示。最终在VGA液晶显示器上,可以看到左侧图像是原始的图像,右侧图像是经过平滑处理后的图像。   2 图像平滑与滤波 2.1 基本概念 从统计学的观点来看,凡是统计特征不随时间变化的噪声称为平稳噪声,而统计特征随时间变化的噪声称为非平稳噪声。幅值基本相同,但是噪声出现的位置是随机的,称为椒盐噪声;如果噪声的幅值是随机的,根据幅值大小的分布,有高斯型和瑞利型两种,分别称为高斯噪声和瑞利噪声。 图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。 消除图像中的噪声成分叫作图像的平滑化或滤波操作。信号或图像的能量大部分集中在幅度谱的低频和中频段是很常见的,而在较高频段,感兴趣的信息经常被噪声淹没。因此一个能降低高频成分幅度的滤波器就能够减弱噪声的影响。 图像滤波的目的有两个,一是抽出对象的特征作为图像识别的特征模式;另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。而对滤波处理的要求也有两条,一是不能损坏图像的轮廓及边缘等重要信息;二是使图像清晰视觉效果好。 平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊;另一类是消除噪音。空间域的平滑滤波一般采用简单平均法进行,就是求邻近像元点的平均亮度值。邻域的大小与平滑的效果直接相关,邻域越大平滑的效果越好,但邻域过大,平滑会使边缘信息损失的越大,从而使输出的图像变得模糊,因此需合理选择邻域的大小。 关于滤波器,一种形象的比喻法是:我们可以把滤波器想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口放到图像之上,透过这个窗口来看我们得到的图像。举一个滤波在我们生活中的应用:美颜的磨皮功能。如果将我们脸上坑坑洼洼比作是噪声的话,那么滤波算法就是来取出这些噪声,使我们自拍的皮肤看起来很光滑。 2.2 滤波算法          各种不同的滤波算法如下: •限幅滤波法(又称程序判断滤波法) • 中位值滤波法 • 算术平均滤波法 • 高斯滤波法 • 递推平均滤波法(又称滑动平均滤波法) • 中位值平均滤波法(又称防脉冲干扰平均滤波法) • 限幅平均滤波法 • 一阶滞后滤波法 • 加权递推平均滤波法 • 消抖滤波法 • 限幅消抖滤波法 •卡尔曼滤波(非扩展卡尔曼) 2.3 均值滤波 均值滤波器是图像处理中一种常见的滤波器,它主要应用于平滑噪声。它的原理主要是利用某像素点周边像素的平均值来达到平滑噪声的效果。          例如,1~8像素是(x,y)点周围邻近的8个像素点。最简单的均值滤波,即对(x,y)以及周边8个像素点求平均替代原来的(x,y)点。            这种滤波方式的优点很明显,算法简单,计算速度快。缺点是降低噪声的同时使图像产生模糊,特别是景物的边缘和细节部分。   2.4 加权均值滤波器          由于我们已经注意到了中心点和周边像素点的重要程度不同,因此可以将均值滤波进行改进,获得图像平滑滤波效果的同时,也在一定程度上尽量降低图像边缘和细节的损失。          基于1/16的加权均值滤波,我们的Matlab代码如下: clear clc I1=imread('.\lena.jpg'); I=im2double(I1); [m,n,c]=size(I); A=zeros(m,n,c);   %           1   2   1 %   1/16 *  2   4   2 %           1   2   1   %for R for i=2:m-1     for j=2:n-1         A(i,j,1)=I(i-1,j-1,1)+I(i+1,j-1,1)+I(i-1,j+1,1)+I(i+1,j+1,1)+2*I(i+1,j,1)+2*I(i-1,j,1)+2*I(i,j+1,1)+2*I(i,j-1,1)+4*I(i,j,1);     end end   %for G for i=2:m-1     for j=2:n-1         A(i,j,2)=I(i-1,j-1,2)+I(i+1,j-1,2)+I(i-1,j+1,2)+I(i+1,j+1,2)+2*I(i+1,j,2)+2*I(i-1,j,2)+2*I(i,j+1,2)+2*I(i,j-1,2)+4*I(i,j,2);     end end   %for B for i=2:m-1     for j=2:n-1         A(i,j,3)=I(i-1,j-1,3)+I(i+1,j-1,3)+I(i-1,j+1,3)+I(i+1,j+1,3)+2*I(i+1,j,3)+2*I(i-1,j,3)+2*I(i,j+1,3)+2*I(i,j-1,3)+4*I(i,j,3);     end end   B=A/16;   %output imwrite(B,'lena.tif','tif'); imshow('.\lena.jpg');title('origin image');figure imshow('lena.tif');title('image after average filter')          滤波效果如下。          Matlab源码、Lena.jpg原图和比对图存放在project\zstar_ex63\matlab文件夹下。 3 基于FPGA的图像平滑处理          工程文件夹project\zstar_ex63\zstar.srcs\sources_1\new下的average_filter.v模块实现了1/16的图像加权均值滤波处理。该模块功能框图如下,使用2个FIFO,分别缓存前后行,即进入图像处理的3组数据流分别是第n-1行、第n行和第n+1行的图像,控制输入数据流和2个FIFO缓存的图像在同一个位置、寄存器对前后2个像素的图像值进行缓存,这样便可实现中心像素点以及前后列、上下行之间数据的同步处理了。   4 装配说明          MT9V034摄像头模块通过Zstar ISB底板(P3)与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图所示。   5 板级调试          本实例对应ex63实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex63\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电,可以看到VGA显示器同时显示左右两个图像,左侧图像为原始图像,右侧图像为平滑处理后图像。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-23
  • 发表了主题帖: 玩转Zynq连载43——[ex62] OV5640摄像头的图像拉普拉斯边缘提取

            1 系统概述 如图所示,这是整个视频采集系统的原理框图。上电初始,FPGA需要通过IIC接口对CMOS Sensor进行寄存器初始化配置。这些初始化的基本参数,即初始化地址对应的初始化数据都存储在一个预先配置好的FPGA片内ROM中。在初始化配置完成后,CMOS Sensor就能够持续输出标准RGB的视频数据流,FPGA通过对其同步信号,如时钟、行频和场频进行检测,从而从数据总线上实时的采集图像数据。 在FPGA内部,采集到的视频数据先通过一个FIFO,将原本25MHz频率下同步的数据流转换到50MHz的频率下。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会通过AXI HP0总线写入DDR3中。与此同时,AXI HP0总线也会读取DDR3中缓存的图像数据,缓存到FIFO中,并最终送往LCD驱动模块进行显示。LCD驱动模块不断的发出读图像数据的请求,并驱动液晶显示器显示视频图像。 本实例除了前面提到对原始图像做DDR3缓存和显示,还会在原始图像缓存到DDR3之前,另外做图像的多行缓存和拉普拉斯边缘提取处理,获得新的图像流,这个图像流通过AXI HP1总线写入到DDR3中。AXI HP1总线也会根据LCD显示模块的请求,读取处理后的图像进行显示。最终在VGA液晶显示器上,可以看到左侧图像是原始的图像,右侧图像是经过边缘提取处理后的图像。   2 图像拉普拉斯边缘提取 2.1 基本概念 在图像增强中,平滑是为了消除图像中噪声的干扰,或者降低对比度。与之相反,有时为了强调图像的边缘和细节,需要对图像进行锐化,提高对比度。 拉普拉斯锐化图像是根据图像某个像素的周围像素到此像素的突变,也就是说它的依据是图像像素的变化程度。我们知道,一个函数的一阶微分描述了函数图像是朝哪里变化的,即增长或者降低;而二阶微分描述的则是图像变化的速度,急剧增长下降还是平缓的增长下降。那么据此我们可以猜测出依据二阶微分能够找到图像的色素的过渡程度,例如白色到黑色的过渡就是比较急剧的。 或者用官方点的话说:当邻域中心像素灰度低于它所在的领域内其它像素的平均灰度时,此中心像素的灰度应被进一步降低,当邻域中心像素灰度高于它所在的邻域内其它像素的平均灰度时,此中心像素的灰度应被进一步提高,以此实现图像的锐化处理。 2.2 拉普拉斯(laplace)算子 最常用的无方向性的二阶差分算子,其模板有3*3、5*5和7*7等多种形式。。          例如,以3*3算子为例,1~8像素是(x,y)点周围邻近的8个像素点。可以使用右侧的2种模板对(x,y)以及周边8个像素点进行运算,替代原来的(x,y)点。 2.3 Matlab实现          基于第2种拉普拉斯边缘提取算子,我们的Matlab代码如下: clear clc I1=imread('.\lena.jpg'); I=im2double(I1); [m,n,c]=size(I); A=zeros(m,n,c);   %for R for i=2:m-1     for j=2:n-1         A(i,j,1)=I(i-1,j-1,1)+I(i+1,j-1,1)+I(i-1,j+1,1)+I(i+1,j+1,1)+I(i+1,j,1)+I(i-1,j,1)+I(i,j+1,1)+I(i,j-1,1)-8*I(i,j,1);     end end   %for G for i=2:m-1     for j=2:n-1         A(i,j,2)=I(i-1,j-1,2)+I(i+1,j-1,2)+I(i-1,j+1,2)+I(i+1,j+1,2)+I(i+1,j,2)+I(i-1,j,2)+I(i,j+1,2)+I(i,j-1,2)-8*I(i,j,2);     end end   %for B for i=2:m-1     for j=2:n-1         A(i,j,3)=I(i-1,j-1,3)+I(i+1,j-1,3)+I(i-1,j+1,3)+I(i+1,j+1,3)+I(i+1,j,3)+I(i-1,j,3)+I(i,j+1,3)+I(i,j-1,3)-8*I(i,j,3);     end end   B=A;   %output imwrite(B,'lena.tif','tif'); imshow('.\lena.jpg');title('origin image');figure imshow('lena.tif');title('image after laplace transform')          滤波效果如下。          Matlab源码、Lena.jpg原图和比对图存放在project\zstar_ex62\matlab文件夹下。 3 基于FPGA的图像平滑处理          工程文件夹project\zstar_ex62\zstar.srcs\sources_1\new下的laplace_transform.v模块实现了图像的拉普拉斯边缘提取处理。该模块功能框图如下,使用2个FIFO,分别缓存前后行,即进入图像处理的3组数据流分别是第n-1行、第n行和第n+1行的图像,控制输入数据流和2个FIFO缓存的图像在同一个位置、寄存器对前后2个像素的图像值进行缓存,这样便可实现中心像素点以及前后列、上下行之间数据的同步处理了。   4 装配说明          OV5640摄像头模块通过Zstar ISB底板(P3)与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图所示。   5 板级调试          本实例对应ex62实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex62\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电,可以看到VGA显示器同时显示左右两个图像,左侧图像为原始图像,右侧图像为拉普拉斯边缘提取处理后图像。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-22
  • 发表了主题帖: 玩转Zynq连载42——[ex61] OV5640摄像头的图像拉普拉斯锐化处理

      1系统概述 如图所示,这是整个视频采集系统的原理框图。上电初始,FPGA需要通过IIC接口对CMOS Sensor进行寄存器初始化配置。这些初始化的基本参数,即初始化地址对应的初始化数据都存储在一个预先配置好的FPGA片内ROM中。在初始化配置完成后,CMOS Sensor就能够持续输出标准RGB的视频数据流,FPGA通过对其同步信号,如时钟、行频和场频进行检测,从而从数据总线上实时的采集图像数据。 在FPGA内部,采集到的视频数据先通过一个FIFO,将原本25MHz频率下同步的数据流转换到50MHz的频率下。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会通过AXI HP0总线写入DDR3中。与此同时,AXI HP0总线也会读取DDR3中缓存的图像数据,缓存到FIFO中,并最终送往LCD驱动模块进行显示。LCD驱动模块不断的发出读图像数据的请求,并驱动液晶显示器显示视频图像。 本实例除了前面提到对原始图像做DDR3缓存和显示,还会在原始图像缓存到DDR3之前,另外做图像的多行缓存和拉普拉斯锐化处理,获得新的锐化后的图像流,这个图像流通过AXI HP1总线写入到DDR3中。AXI HP1总线也会根据LCD显示模块的请求,读取处理后的图像进行显示。最终在VGA液晶显示器上,可以看到左侧图像是原始的图像,右侧图像是经过锐化处理后的图像。   2图像拉普拉斯锐化 2.1 基本概念 在图像增强中,平滑是为了消除图像中噪声的干扰,或者降低对比度。与之相反,有时为了强调图像的边缘和细节,需要对图像进行锐化,提高对比度。 拉普拉斯锐化图像是根据图像某个像素的周围像素到此像素的突变,也就是说它的依据是图像像素的变化程度。我们知道,一个函数的一阶微分描述了函数图像是朝哪里变化的,即增长或者降低;而二阶微分描述的则是图像变化的速度,急剧增长下降还是平缓的增长下降。那么据此我们可以猜测出依据二阶微分能够找到图像的色素的过渡程度,例如白色到黑色的过渡就是比较急剧的。 或者用官方点的话说:当邻域中心像素灰度低于它所在的领域内其它像素的平均灰度时,此中心像素的灰度应被进一步降低,当邻域中心像素灰度高于它所在的邻域内其它像素的平均灰度时,此中心像素的灰度应被进一步提高,以此实现图像的锐化处理。 2.2拉普拉斯(laplace)算子 最常用的无方向性的二阶差分算子,其模板有3*3、5*5和7*7等多种形式。。          例如,以3*3算子为例,1~8像素是(x,y)点周围邻近的8个像素点。可以使用右侧的2种模板对(x,y)以及周边4或8个像素点进行运算,替代原来的(x,y)点。          当然了,根据中心点的权重程度,也可以使用如下2中模板来实现图像锐化。 2.3Matlab实现          基于第一种拉普拉斯锐化处理,我们的Matlab代码如下: clear clc I1=imread('.\lena.jpg'); I=im2double(I1); [m,n,c]=size(I); A=zeros(m,n,c);   %for R for i=2:m-1     for j=2:n-1         A(i,j,1)=I(i+1,j,1)+I(i-1,j,1)+I(i,j+1,1)+I(i,j-1,1)-4*I(i,j,1);     end end   %for G for i=2:m-1     for j=2:n-1         A(i,j,2)=I(i+1,j,2)+I(i-1,j,2)+I(i,j+1,2)+I(i,j-1,2)-4*I(i,j,2);     end end   %for B for i=2:m-1     for j=2:n-1         A(i,j,3)=I(i+1,j,3)+I(i-1,j,3)+I(i,j+1,3)+I(i,j-1,3)-4*I(i,j,3);     end end   B=I-A;   %output imwrite(B,'lena.tif','tif'); imshow('.\lena.jpg');title('origin image');figure imshow('lena.tif');title('image after laplace transform')          滤波效果如下。          Matlab源码、Lena.jpg原图和比对图存放在project\zstar_ex61\matlab文件夹下。 3基于FPGA的图像平滑处理          工程文件夹project\zstar_ex61\zstar.srcs\sources_1\new下的laplace_transform.v模块实现了拉普拉斯锐化处理。该模块功能框图如下,使用2个FIFO,分别缓存前后行,即进入图像处理的3组数据流分别是第n-1行、第n行和第n+1行的图像,控制输入数据流和2个FIFO缓存的图像在同一个位置、寄存器对前后2个像素的图像值进行缓存,这样便可实现中心像素点以及前后列、上下行之间数据的同步处理了。   4装配说明          OV5640摄像头模块通过Zstar ISB底板(P3)与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图所示。   5板级调试          本实例对应ex61实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex61\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电,可以看到VGA显示器同时显示左右两个图像,左侧图像为原始图像,右侧图像为锐化处理后图像。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-21
  • 发表了主题帖: 玩转Zynq连载41——[ex60] OV5640摄像头的图像平滑处理

      1 系统概述 如图所示,这是整个视频采集系统的原理框图。上电初始,FPGA需要通过IIC接口对CMOS Sensor进行寄存器初始化配置。这些初始化的基本参数,即初始化地址对应的初始化数据都存储在一个预先配置好的FPGA片内ROM中。在初始化配置完成后,CMOS Sensor就能够持续输出标准RGB的视频数据流,FPGA通过对其同步信号,如时钟、行频和场频进行检测,从而从数据总线上实时的采集图像数据。 在FPGA内部,采集到的视频数据先通过一个FIFO,将原本25MHz频率下同步的数据流转换到50MHz的频率下。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会通过AXI HP0总线写入DDR3中。与此同时,AXI HP0总线也会读取DDR3中缓存的图像数据,缓存到FIFO中,并最终送往LCD驱动模块进行显示。LCD驱动模块不断的发出读图像数据的请求,并驱动液晶显示器显示视频图像。 本实例除了前面提到对原始图像做DDR3缓存和显示,还会在原始图像缓存到DDR3之前,另外做图像的多行缓存和平滑处理运算,获得新的平滑后的图像流,这个图像流通过AXI HP1总线写入到DDR3中。AXI HP1总线也会根据LCD显示模块的请求,读取处理后的图像进行显示。最终在VGA液晶显示器上,可以看到左侧图像是原始的图像,右侧图像是经过平滑处理后的图像。   2 图像平滑与滤波 2.1 基本概念 从统计学的观点来看,凡是统计特征不随时间变化的噪声称为平稳噪声,而统计特征随时间变化的噪声称为非平稳噪声。幅值基本相同,但是噪声出现的位置是随机的,称为椒盐噪声;如果噪声的幅值是随机的,根据幅值大小的分布,有高斯型和瑞利型两种,分别称为高斯噪声和瑞利噪声。 图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。 消除图像中的噪声成分叫作图像的平滑化或滤波操作。信号或图像的能量大部分集中在幅度谱的低频和中频段是很常见的,而在较高频段,感兴趣的信息经常被噪声淹没。因此一个能降低高频成分幅度的滤波器就能够减弱噪声的影响。 图像滤波的目的有两个,一是抽出对象的特征作为图像识别的特征模式;另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。而对滤波处理的要求也有两条,一是不能损坏图像的轮廓及边缘等重要信息;二是使图像清晰视觉效果好。 平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊;另一类是消除噪音。空间域的平滑滤波一般采用简单平均法进行,就是求邻近像元点的平均亮度值。邻域的大小与平滑的效果直接相关,邻域越大平滑的效果越好,但邻域过大,平滑会使边缘信息损失的越大,从而使输出的图像变得模糊,因此需合理选择邻域的大小。 关于滤波器,一种形象的比喻法是:我们可以把滤波器想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口放到图像之上,透过这个窗口来看我们得到的图像。举一个滤波在我们生活中的应用:美颜的磨皮功能。如果将我们脸上坑坑洼洼比作是噪声的话,那么滤波算法就是来取出这些噪声,使我们自拍的皮肤看起来很光滑。 2.2 滤波算法          各种不同的滤波算法如下: •限幅滤波法(又称程序判断滤波法) • 中位值滤波法 • 算术平均滤波法 • 高斯滤波法 • 递推平均滤波法(又称滑动平均滤波法) • 中位值平均滤波法(又称防脉冲干扰平均滤波法) • 限幅平均滤波法 • 一阶滞后滤波法 • 加权递推平均滤波法 • 消抖滤波法 • 限幅消抖滤波法 •卡尔曼滤波(非扩展卡尔曼) 2.3 均值滤波 均值滤波器是图像处理中一种常见的滤波器,它主要应用于平滑噪声。它的原理主要是利用某像素点周边像素的平均值来达到平滑噪声的效果。          例如,1~8像素是(x,y)点周围邻近的8个像素点。最简单的均值滤波,即对(x,y)以及周边8个像素点求平均替代原来的(x,y)点。          这种滤波方式的优点很明显,算法简单,计算速度快。缺点是降低噪声的同时使图像产生模糊,特别是景物的边缘和细节部分。   2.4 加权均值滤波器          由于我们已经注意到了中心点和周边像素点的重要程度不同,因此可以将均值滤波进行改进,获得图像平滑滤波效果的同时,也在一定程度上尽量降低图像边缘和细节的损失。          基于1/16的加权均值滤波,我们的Matlab代码如下: clear clc I1=imread('.\lena.jpg'); I=im2double(I1); [m,n,c]=size(I); A=zeros(m,n,c);   %           1   2   1 %   1/16 *  2   4   2 %           1   2   1   %for R for i=2:m-1     for j=2:n-1         A(i,j,1)=I(i-1,j-1,1)+I(i+1,j-1,1)+I(i-1,j+1,1)+I(i+1,j+1,1)+2*I(i+1,j,1)+2*I(i-1,j,1)+2*I(i,j+1,1)+2*I(i,j-1,1)+4*I(i,j,1);     end end   %for G for i=2:m-1     for j=2:n-1         A(i,j,2)=I(i-1,j-1,2)+I(i+1,j-1,2)+I(i-1,j+1,2)+I(i+1,j+1,2)+2*I(i+1,j,2)+2*I(i-1,j,2)+2*I(i,j+1,2)+2*I(i,j-1,2)+4*I(i,j,2);     end end   %for B for i=2:m-1     for j=2:n-1         A(i,j,3)=I(i-1,j-1,3)+I(i+1,j-1,3)+I(i-1,j+1,3)+I(i+1,j+1,3)+2*I(i+1,j,3)+2*I(i-1,j,3)+2*I(i,j+1,3)+2*I(i,j-1,3)+4*I(i,j,3);     end end   B=A/16;   %output imwrite(B,'lena.tif','tif'); imshow('.\lena.jpg');title('origin image');figure imshow('lena.tif');title('image after average filter')          滤波效果如下。          Matlab源码、Lena.jpg原图和比对图存放在project\zstar_ex60\matlab文件夹下。 3 基于FPGA的图像平滑处理          工程文件夹project\zstar_ex60\zstar.srcs\sources_1\new下的average_filter.v模块实现了1/16的图像加权均值滤波处理。该模块功能框图如下,使用2个FIFO,分别缓存前后行,即进入图像处理的3组数据流分别是第n-1行、第n行和第n+1行的图像,控制输入数据流和2个FIFO缓存的图像在同一个位置、寄存器对前后2个像素的图像值进行缓存,这样便可实现中心像素点以及前后列、上下行之间数据的同步处理了。   4 装配说明          OV5640摄像头模块通过Zstar ISB底板(P3)与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图所示。   5 板级调试          本实例对应ex60实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex60\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电,可以看到VGA显示器同时显示左右两个图像,左侧图像为原始图像,右侧图像为平滑处理后图像。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-20
  • 发表了主题帖: 玩转Zynq连载40——[ex59] 基于Zynq的双目视觉图像采集显示实例

    本帖最后由 ove学习使我快乐 于 2020-2-20 11:02 编辑   1 CMOS摄像头应用背景与驱动原理 CMOS摄像头(CMOS Sensor)是一种采用CMOS图像传感器的摄像头。摄像头主要有两类,CMOS和CCD。CMOS一般应用在普通数码设备中,CCD一般应用在高档数码设备中,它们都是光学成像,但CCD比CMOS单位成像的效果要好。CCD镜头比CMOS的颜色还原更好,并且分辨率更高。          CCD和CMOS在制造上的主要区别是,CCD是集成在半导体单晶材料上,而CMOS是集成在被称做金属氧化物的半导体材料上,但工作原理没有本质的区别。在成像方面,CCD的成像通透性、明锐度都很不错,色彩还原、曝光可以保证基本准确。而CMOS的产品往往通透性一般,对实物的色彩还原能力偏弱,曝光也都不太好。由于CMOS自身的物理特性,其成像质量和CCD还是有一定距离的。CCD制造工艺较复杂,掌握CCD技术的厂商并不多,采用CCD摄像头的价格相对也比较昂贵。但随着制造工艺的不断改进,目前CMOS和CCD的实际成像效果的差异在逐渐减小。加之CMOS的制造成本和功耗都要比CCD低不少,因此很多摄像头生产厂商更趋向于采用CMOS感光元件。正是由于低廉的价格以及高度的整合性,使得CMOS摄像头得到了更广泛的应用。 CCD是目前比较成熟的成像器件,CMOS被看作未来的成像器件。因为CMOS结构相对简单,与现有的大规模集成电路生产工艺相同,从而生产成本可以大大降低。从原理上看,CMOS的信号是以点为单位的电荷信号,而CCD是以行为单位的电流信号,前者更为敏感,速度也更快,更为省电。现在高级的CMOS并不比一般CCD差,但是CMOS工艺还不是十分成熟,普通的CMOS一般分辨率低而成像较差。 不管CCD还是CMOS,基本上两者都是利用矽感光二极体(photodiode)进行光与电的转换。比较CCD和CMOS的结构,ADC的位置和数量是最大的不同。简单的说,CCD每曝光一次,在快门关闭后进行像素转移处理,将每一行中每一个像素(pixel)的电荷信号依序传入“缓冲器”中,由底端的线路引导输出至CCD旁的放大器进行放大,再串联ADC输出;相应的,CMOS的设计中每个像素旁就直接连着ADC(放大兼类比数字信号转换器),信号直接放大并转换成数字信号。          我们这个模块中所使用的CMOS Sensor的型号为OV5640,其内部功能框图如图1所示。前端有模拟感光模块,经过AD处理后将模拟信号转换为数字信号,后端经过一些处理后输出符合一定协议标准的视频数据流。FPGA器件将根据这个数据流的协议对视频数据进行采集解码,最终显示在720p (1280*720)分辨率的VGA液晶显示器上。 图1 CMOS Sensor内部功能框图   2 视频采集系统设计概述 如图2所示,这是整个视频采集系统的原理框图。上电初始,FPGA需要通过IIC接口对CMOS Sensor进行寄存器初始化配置。这些初始化的基本参数,即初始化地址对应的初始化数据都存储在一个预先配置好的FPGA片内ROM中。在初始化配置完成后,CMOS Sensor就能够持续输出标准RGB的视频数据流,FPGA通过对其同步信号,如时钟、行频和场频进行检测,从而从数据总线上实时的采集图像数据。 在FPGA内部,采集到的视频数据先通过一个FIFO,将原本25MHz频率下同步的数据流转换到50MHz的频率下。接着将这个数据再送入写DDR3缓存的异步FIFO中,这个FIFO中的数据一旦达到一定数量,就会被写入DDR3中。与此同时,使用另一个异步FIFO将DDR3缓存的图像数据读出,并依此送往LCD驱动模块进行显示。LCD驱动模块不断的发出读图像数据的请求,并驱动液晶显示器显示视频图像。 本实例的双目,即2个OV5640摄像头的图像采集,实际上是两个完全一样的图像采集模块,它们采集到的数据分别通过Zynq的AXI HP总线HP1和HP2通道写入到DDR3中。然后LCD显示控制端则分别通过AXI HP总线的HP1和HP2读出两个摄像头的视频图像,最终驱动显示器左右两侧分别显示两个摄像头的图像。 图2 视频采集系统功能框图          如图3所示,这里显示了整个工程的各个模块层次结构。在顶层模块at7.v下面有9个子模块。这9个子模块的功能以及他们所包含的子模块或例化功能描述如表1所示。 图3 视频采集系统工程代码层次结构 表1 工程模块描述 模块名称 功能描述 Zstar_zynq_ps 该模块是Zynq PS(Processor System) IP核的例化,AXI HP总线的配置引出和系统所需时钟和复位都是来自于这个Zynq PS。 Image_controller U2和U4都是例化了这个模块。 该模块实现IIC接口对OV5640的初始化、OV5640输出图像的采集控制等。这个模块内部例化了3个子模块,I2C_OV5640_Init_RGB565模块实现IIC的接口协议和初始化配置;I2C_OV5640_Init_RGB565模块下面例化的I2C_Controller模块实现IIC协议,用于产生初始配置数据的 LUT模块则是I2C_OV5640_RGB565_Config;image_capture模块实现图像采集功能。 Axi_hp0_wr U3和U5都是例化了这个模块。 该模块内部例化了用于缓存写入DDR3数据的FIFO,并实现了AXI HP总线的写通道时序,完成数据通过AXI HP总线写入DDR3的操作。 Axi_hp0_rd U7和U8都是例化了这个模块。 该模块内部例化了用于缓存读出DDR3数据的FIFO,并实现了AXI HP总线的读通道时序,完成数据通过AXI HP总线从DDR3读出的操作。 lcd_driver 该模块驱动LCD,同时产生控制逻辑读取DDR3缓存的2个摄像头实时视频图像。 led_controller 该模块控制LED闪烁,指示工作状态。   3 IIC接口配置模块设计          如图4所示,Iic_ctrl模块和iic_gene模块是用于产生IIC配置的逻辑。Iic_ctrl模块主要是最底层的IIC协议实现,而iic_gene模块则使用状态机产生一串的CMOS Sensor寄存器配置操作,该模块的配置地址和数据是存储在事先设定好的LUT模块I2C_OV5640_RGB565_Config中。 图4 IIC配置产生逻辑功能框图   4 视频流采集设计          在对CMOS Sensor进行了寄存器的初始化配置后,并行数据总线上便开始持续的输出视频数据流。如图8所示,这是CMOS Sensor输出VGA(640*480分辨率)并行数据视频流协议的时序波形。我们可以看到,场同步信号VSYNC的每一个高脉冲表示新的一场图像(或者说是新的一帧图像)马上要开始传输;行同步信号HREF为高电平时,表示目前的数据总线D[7:0]上的数据是有效的视频流。 图8 并行数据视频流协议 如图9所示,视频时钟PCLK的每个上升沿,有效数据D[7:0]、行同步信号HREF和场同步信号VSYNC被锁存到FPGA中。 图9 并行数据视频流时序          一个有效的行将传输640*2Bytes的数据,也就是说,一个像素点会有2Bytes即16bits的有效色彩值。对应R、G、B的位数分别为5bits、6bits、5bits。传输的数据总线是8bits,那么一个像素点对应就有2个8bits需要传输。每两个字节中的R、G、B格式定义如图10所示。 图10 RGB 565输出时序框图          理解了时序波形,我们再来看看代码中是如何对CMOS Sensor送来的这组源同步信号进行采集的。如图11所示,这里通过一个异步FIFO来同步CMOS Sensor和FPGA内部逻辑。我们只要把vpclk、vdb、vhref分别作为FIFO的写入时钟、写入数据和写入使能信号。此外,vvsync作为这个FIFO的复位信号,每一帧新图像前FIFO进行一次清空,实际操作中,为了得到稳定有效的复位信号,我们使用内部时钟对这个复位信号打了一拍。这样,我们便把持续不断的视频流有效数据缓存到了FIFO中。在FIFO的读端,判定数据大等于16*16bit时,就连续读出这16个数据,送到ddr_cache模块的DDR3写缓存FIFO中。 图11 image_capture模块功能框图   5 LCD控制器设计          LCD显示控制部分比较简单,用x_cnt和y_cnt两个计数器,产生一个二维图像的有效显示区域。有效显示区域的图像数据从DDR3中读取,对应的图像就是OV5640采集到的VGA图像。控制接口上,这个模块输出lcd_rfclr信号作为每个图像帧的同步信号,或者称之为复位信号,在每个有效显示图像开始前,这个信号都会拉高一段时间,axi_hp0_rd.v模块可以用这个信号实现FIFO的复位,以及对应的控制信号的复位。读数据请求信号lcd_rfreq1和lcd_rfreq2会产生连续的640*480个时钟周期的高电平,用于读取DDR3中缓存的两个摄像头的图像数据。16位数据总线lcd_rfdb1和lcd_rfdb2则分别在每个读数据请求信号lcd_rfreq1和lcd_rfreq2拉高后有效,对应数据送到显示器进行显示。lcd_rfreq1和lcd_rfreq2信号的拉高则分别在液晶屏的左边半屏和右边半屏。   6 装配说明          2个OV5640摄像头模块通过Zstar ISB底板与Zstar Zynq开发板连接,VGA也是通过Zstar ISB底板与Zstar Zynq开发板连接,VGA板同时需要连接到VGA显示器。连接示意如图12所示。 7板级调试          本实例对应ex59实例工程,已经制作好的BOOT.bin放置在工程路径“zstar_ex59\zstar.sdk\BOOT”下。也可以参考文档《玩转Zynq-实例篇:[ex51] 制作裸跑程序的启动文件BOOT.bin.pdf》制作包含.bit文件的BOOT.bin文件,将其拷贝到TF卡中,插入Zstar开发板的卡槽中,做好装配连接,上电。视频显示如图所示。 图 双目视频采集效果 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-19
  • 发表了主题帖: 玩转Zynq连载39——[ex58] 基于Zynq的XADC采集控制实例

    本帖最后由 ove学习使我快乐 于 2020-2-19 09:43 编辑   1 功能概述        Xilinx FPGA器件特有的XADC(Xilinx Analog-to-Digital Converter)模块创新性的将模拟信号处理混合到FPGA器件中,便于对板级模拟信号采集、处理以及对板级温度、电源电压的监控。 XADC功能如图所示,内部有专门的温度传感器和供电传感器,用于监控FPGA器件本身的工作状态,也提供了1个独立的模拟电压输入通道(VP_0/VN_0)和16个复用的模拟电压输入通道(VAUXP/VAUXN)。内部的2个ADC有12bit位宽和1MSPS采样速率,可以外接精密基准电压源作为参考电压,基本能够满足一般应用。此外,也有专门的控制接口可以和FPGA逻辑互连,便于编程控制。供电电压监控的电压输入范围是0~3V,模拟电压输入通道的电压输入范围是0~1V。 图 XADC功能框图          集成XADC功能,需要例化XADC的IP核,然后通过访问XADC内部的寄存器实现模拟电压采集方式的设置,并读取转换后的模拟电压数据。XADC内部寄存器的映射如图所示。 图 XADC内部寄存器映射关系截图          在Zynq中,XADC模块通过AXI GP总线连接到PS。XADC相当于重新被封装为一个标准的AXI总线外设,它的寄存器映射关系也有所变化。在xilinx官方文档pg091-xadc-wiz.pdf中可以看到重新映射的寄存器地址。          关于Zynq的XADC应用,推荐大家参考xilinx下述3个文档。 pg091-xadc-wiz.pdf ug480_7Series_XADC.pdf ug585-Zynq-7000-TRM.pdf的Chapter 30 XADC Interface 本实例工程对应zstar_ex58。硬件上,XADC通过AXI接口连接到PS;PS编程读取XADC内部的温度和供电电压值,通过UART定时打印转换的最终温度和电压值。   2 电压换算关系 模拟电压值换算          对于1个独立的模拟电压输入通道(VP_0/VN_0)和16个复用的模拟电压输入通道(VAUXP/VAUXN),它的输入范围是0~1V,参考电压1V。因此它读出的数据和实际电压值之间的换算关系如下:          对于12bit的ADC值,Vactual = Vdigital/4096          对于16bit的ADC值,Vactual = Vdigital/65536   温度值换算          从XADC的温度传感器读出的温度值,通过以下公式可以换算为实际的摄氏温度:          对于12bit的ADC值,Tactual = Tdigital*503.975/4096 – 273.15 对于16bit的ADC值,Tactual = Tdigital*503.975/65536 – 273.15   供电电压的换算公式          对于XADC中供电传感器读取的供电电压值,其量程范围是0~3V,参考电压3V。所以读取的值与实际电压之间的换算关系如下:          对于12bit的ADC值,Vactual = Vdigital*3/4096          对于16bit的ADC值,Vactual = Vdigital*3/65536   3 XADC IP添加与配置 在zstar_ex56工程实例的基础上,下面我们看看如何对XADC IP进行添加和配置。在Block Design的Diagram页面空白处单击右键,如图所示,点击Add IP…。          Search后输入关键词XADC,出现XADC Wizard IP,双击添加这个IP到Diagram中。          和前面的操作一样,输入关键词axi interconnect,将AXI Interconnect IP也添加到Diagram中。          新添加的2个IP模块如图所示。XADC无需多言,你懂得。这个AXI Interconnect的用处是将XADC的s_axi_lite接口转换到Zynq的AXI GP接口(AXI3),它相当于一个接口适配模块。 双击axi_interconnect_0组件,如图所示,弹出属性菜单中修改Number of Slave Interfaces和Number of Master Interfaces都为1。 双击xadc_wiz_0组件,弹出属性菜单中修改如下。          ● 接口选项(Interface Options)选择AXI4Lite,通过AXI Interconnect可以连接Zynq。          ● 时序模式(Timing Mode)选择Continuous Mode。          ● 启动通道选择(Startup Channel Selection)勾选Channel Sequencer。          ● 输入时钟频率(DCLK Frequency)输入100MHz。          ● ADC转换率(ADC Conversion Rate)输入1000KSPS,即所支持的最高速率。          ● 其它选项使用默认设置即可。          ADC Setup页面配置如图所示。 序列模式(Sequencer Mode)选择Continuous Mode,即对ADC通道进行连续采集。 通道平均(Channel Averaging)选择16,即XADC内部做16个连续采样值的均值滤波后输出。 其它选项使用默认设置即可。          Alarms页面如图所示,这里可以勾选需要进行监控的电压通道,并且可以设定报警闸值。          Channel Sequencer页面需要勾选TEMPERATURE、VCCINT、VCCAUX、VCCBRAM、VCCPINT、VCCPAUX、VCCDDRO和VP/VN,表示开启这些通道的ADC转换功能。          完成XADC的配置后,将axi_interconnect_0、xadc_wiz_0和processing_system7_0这3个模块连接如图所示。注意Vp_Vn是XADC的外部输入引脚,需要引出,若使用了XADC的16个复用通道,也一样要引出到顶层模块做引脚申明,并手动配置引脚号。          在Address Editor中,点击Auto Assign Address,确认xadc_wiz_0已经分配了相应的地址空间如图所示。          完成配置,生成新的PS系统后,更新顶层模块的接口,主要是XADC相关的几个新的接口,做相应连接(可以参考工程源码),然后重新编译整个Vivado工程。   4嵌入式软件编程          参考文档《玩转Zynq-工具篇:导出PS硬件配置和新建SDK工程.pdf》导出PS硬件工程,并打开EDK新建一个HelloWorld的模板工程。          重新编辑helloworld.c源码如下。在系统初始化(init_platform)后,依次读取XADC的温度采样值并转成实际温度值打印、读取XADC的VCCINT采样值并转成实际电压值打印、读取XADC的VCCAUX采样值并转成实际电压值打印、读取XADC的VP/VN采样值并转成实际电压值打印、读取XADC的VBRAM采样值并转成实际电压值打印。每隔5s做一次读取打印操作。 #include <stdio.h> #include "platform.h" #include "xil_printf.h" #include "sleep.h" #include "xil_io.h"   #define XPAR_AXI_GP0_BASEADDR        0x43c00000 #define XPAR_XADC_TEMPERATURE      0x200 #define XPAR_XADC_VCCINT           0x204 #define XPAR_XADC_VCCAUX                   0x208 #define XPAR_XADC_VPVN                        0x20c #define XPAR_XADC_VBRAM                    0x218   int main() {          u32 temp;          float voltage;   init_platform();   printf("XADC TEST\n\r");   while(1)     { printf("\n\r");          temp = Xil_In32(XPAR_AXI_GP0_BASEADDR + XPAR_XADC_TEMPERATURE);          temp = temp*503.975/65535 - 273.15; printf("Temperature is %d degree\n\r",temp);           voltage = Xil_In32(XPAR_AXI_GP0_BASEADDR + XPAR_XADC_VCCINT);          voltage = voltage/65536*3; printf("VCCINT is %f\n\r",voltage);           voltage = Xil_In32(XPAR_AXI_GP0_BASEADDR + XPAR_XADC_VCCAUX);          voltage = voltage/65536*3; printf("VCCAUX is %f\n\r",voltage);           voltage = Xil_In32(XPAR_AXI_GP0_BASEADDR + XPAR_XADC_VPVN);          voltage = voltage/65536; printf("VPVN is %f\n\r",voltage);           voltage = Xil_In32(XPAR_AXI_GP0_BASEADDR + XPAR_XADC_VBRAM);          voltage = voltage/65536*3; printf("VBRAM is %f\n\r",voltage);            sleep(5);     }   cleanup_platform();     return 0; }         5 板级调试          在Zstar板子上,设置跳线帽P3为JTAG模式,即PIN2-3短接。          连接好串口线(USB线连接PC的USB端口和Zstar板的UART接口)和Xilinx下载线(下载器连接PC的USB端口和Zstar板的JTAG插座)。使用5V电源给板子供电。          接着参考《玩转Zynq-工具篇:SDK在线运行裸跑程序.pdf》将zstar.bit文件和helloworld.elf文件烧录到Zynq中运行起来。          打开Putty,并设置好串口,可以看到如图缩回,每隔5s不断的打印采样到的当前温度和电压值。温度传感器在FPGA器件内部,因此采样到的Temperature值达到了52°C。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2020-02-18
  • 发表了主题帖: 玩转Zynq连载38——[ex57] Zynq AXI HP总线带宽测试

      1 概述          用于PL与DDR3交互的AXI HP总线,它的性能到底如何?吞吐量是否能满足我们的应用?必须4个通道同时使用?还是只使用1个通道?时钟频率的高低对AXI HP总线的带宽有什么影响?这些问题想必是每一个初次使用AXI HP总线的开发者希望评估到的。那么,本实例就搭了一个很基本的架构出来,使用100MHz的AXI HP总线时钟频率(可更改),任意开关每个独立的AXI HP读或写通道,以评估不同通道使用情况下的数据吞吐量。大家可以在此基础上,更改不同的AXI HP总线时钟频率,以评估时钟频率对AXI HP总线的影响。   2 AXI总线协议介绍          参考文档《玩转Zynq-基础篇:AXI总线协议介绍.pdf》。   3 Zynq PS的AXI HP与VIO IP配置          如图所示,在ZYNQ7 Processing System在,点击Page Navigator --> PS-PL Configuration,展开HP Slave AXI Interface,勾选所有的S AXI? interface(?代表0/1/2/3)并选中S AXI HP? DATA WIDTH为64。          在系统框图中,如图所示,将新出现的S_AXI_HP0/S_AXI_HP1/S_AXI_HP2/S_AXI_HP3这4条AXI HP总线,以及它们的时钟AXI_HP0_ACLK/AXI_HP1_ACLK/AXI_HP2_ACLK/AXI_HP3_ACLK接口都引出。          如图所示,在Address Editor页面,默认S_AXI_HP0/S_AXI_HP1/S_AXI_HP2/S_AXI_HP3的地址还未分配,需要点击左侧的图标重新分配地址。          分配好地址后,如图所示。          接着,我们需要参考文档《玩转Zynq-工具篇:基于Vivado的Virtual IO在线板级调试.pdf》新增一个VIO IP核,这个VIO IP的配置如图所示。Input Probe Count和Output Probe Count都为8。          PROBE_IN Ports页面8个Port的Width(位宽)都设置为32。          PROBE_OUT Ports页面8个Port的Width(位宽)都设置为1。          在PL代码中,VIO的8个Output Probe将分别用于控制4条HP总线的读通道和写通道的开关;VIO的8个Input Probe将锁存显示对应HP总线读或写通道每秒的数据传输字节数。   4 PL代码解析          工程代码的层次结构如图所示。 zstar.v模块是顶层模块,将ZYNQ Procssing System引出的4条AXI HP总线的读写通道分别连接到各个具体的逻辑模块中。 timer_1s_generation.v模块是1s定时模块,每秒钟定时产生一个脉宽为100个时钟周期的复位信号timer_1s_rst_n,读写模块的带宽以这个复位信号为周期进行计算。 axi_hp0_wr.v模块实现连续数据写入AXI HP总线的写通道。axi_hp0_rd.v模块不断的送AXI HP的读地址。Vio_0.v模块是例化的VIO IP模块,引出各个HP总线的读或写使能开关以及对应通道的带宽。   5 嵌入式软件工程创建          参考文档《玩转Zynq-工具篇:导出PS硬件配置和新建SDK工程.pdf》导出PS硬件工程,并打开EDK新建一个HelloWorld的模板工程。本实例并不需要在嵌入式软件中做任何其它的功能实现,只需要在.bit文件烧录完成后,运行嵌入式软件即可(主要是PL端的时钟源是来自Zynq PS,因此必须在嵌入式软件运行起来后,才能够产生时钟信号)。   6 板级调试          在Zstar板子上,设置跳线帽P3为JTAG模式,即PIN2-3短接。          连接好串口线(USB线连接PC的USB端口和Zstar板的UART接口)和Xilinx下载线(下载器连接PC的USB端口和Zstar板的JTAG插座)。使用5V电源给板子供电。          参考文档《玩转Zynq-环境篇:XilinxPlatformCableUSB下载器使用指南》烧录PL工程编译产生的.bit和.ltx文件到Zstar板中,如图所示。          参考《玩转Zynq-工具篇:SDK在线运行裸跑程序.pdf》导出硬件并打开EDK,创建HelloWorld模板工程。运行工程,注意PL的.bit文件已经烧录好,不用再次烧录,直接运行.elf文件即可。          回到Vivado,在Hardware Manager界面点击左上角的Refresh device按钮。          双击刷新后出现的hw_vio_1所在行。          出现的dashboard_1界面中,点击左侧的+号,弹出Add Probes窗口,选中所有VIO信号,点击OK,将它们加入到主界面中进行控制或状态监控。          可以选中所有的Output类型的VIO,右键单击,弹出菜单中选择Toggle Button,后续可以通过点击这些信号来更改1或0的电平状态切换。          同样的,选中所有Input类型的VIO总线信号,单击右键,弹出菜单中展开Radix,点击Unsigned Decimal,即以10进制查看这些总线接口。          接下来,我们就可以通过点击各个en信号,对应的开启某个或某几个AXI HP总线的读或写通道,查看它们的数据吞吐量。如图所示,AXI HP0的读通道开启,吞吐量达到每秒344MByte。          如图所示,AXI HP0的读通道和写通道同时开启,吞吐量分别达到每秒333MByte和556MByte。          如图所示,所有4条AXI HP总线的读通道和写通道同时开启,每个读通道的吞吐量都在每秒255MByte左右,每个写通道的吞吐量都在每秒340MByte左右。说明4条AXI HP总线的吞吐量其实是对等设计的,在同等时钟频率和访问方式下,它们的吞吐量是相当的。相比于使用更少的AXI HP总线,从测试发现相同条件下的单通道带宽反而降低了。究其原因,很好解释,在更多的AXI HP总线通道(不同DDR3地址块)之间频繁切换所需要的DDR3地址切换开销会越来越大,那么就导致单通道的带宽会有所降低。 此内容由EEWORLD论坛网友ove学习使我快乐原创,如需转载或用于商业用途需征得作者同意并注明出处

统计信息

已有25人来访过

  • 芯币:117
  • 好友:--
  • 主题:54
  • 回复:1
  • 课时:--
  • 资源:--

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言