[X]关闭
1

04uifdma_vbuf实现双通道摄像头采集(AXI4 FDMA数据缓存篇)

摘要: 是否还记得刚刚前文中提到的uifdma_vbuf中的stride参数,并没有详细介绍其用途,本文中的重点就是关于stride参数的应用。通过设置stride参数我们可以让一个显示器输出多个通道的画面,并且通过uifdma_vbuf的缓存控制 ...

软件版本:vitis2019.2(vivado2019.2)

操作系统:WIN10 64bit

硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA(本文使用米联客(milianke)MK7160FA开发板)

登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!

4.1概述    

    是否还记得刚刚前文中提到的uifdma_vbuf中的stride参数,并没有详细介绍其用途,本文中的重点就是关于stride参数的应用。通过设置stride参数我们可以让一个显示器输出多个通道的画面,并且通过uifdma_vbuf的缓存控制机制可以确保图形不撕裂。

本文实验目的:

1:掌握2个uifdma_vbuf IP的同时使用,以及读写通道之间的同步设计

2:实现1个5640摄像头数据共享给2个uifdma_vbuf的写数据通道

3:掌握uifdma_vbuf IP stride参数的设置,实现一个屏幕显示多个图像的方法

4:掌握图像处理中多通道读写的多缓存机制

4.2硬件电路分析

4.2.1FEP扩展接口

摄像头扩展卡安装在FEP扩展接口上,这里主要用到了摄像头接口的定义,需要注意MK7160默认IO是3.3V的需要匹配3.3V的扩展卡和摄像头。

 

4.2.2fpga_pin.xdc摄像头和HDMI输出IO约束

create_clock -period 10.000 -name sysclk [get_ports sysclk]

set_property PACKAGE_PIN AA3 [get_ports sysclk]

set_property IOSTANDARD SSTL135 [get_ports sysclk]

 

set_property PACKAGE_PIN E18 [get_ports card1_power_en]

set_property IOSTANDARD LVCMOS33 [get_ports card1_power_en]

#---------------------------sensor---------------------------

set_property PACKAGE_PIN F17 [get_ports cmos1_pclk_i]

set_property PACKAGE_PIN E15 [get_ports cmos1_vsync_i]

set_property PACKAGE_PIN E16 [get_ports cmos1_href_i]

set_property PACKAGE_PIN E17 [get_ports cmos1_xclk_o]

set_property PACKAGE_PIN D16 [get_ports cmos1_data_i[0]]

set_property PACKAGE_PIN D15 [get_ports cmos1_data_i[1]]

set_property PACKAGE_PIN F15 [get_ports cmos1_data_i[2]]

set_property PACKAGE_PIN G15 [get_ports cmos1_data_i[3]]

set_property PACKAGE_PIN B16 [get_ports cmos1_data_i[4]]

set_property PACKAGE_PIN C16 [get_ports cmos1_data_i[5]]

set_property PACKAGE_PIN J16 [get_ports cmos1_data_i[6]]

set_property PACKAGE_PIN J15 [get_ports cmos1_data_i[7]]

set_property PACKAGE_PIN K16 [get_ports cmos1_scl]

set_property PACKAGE_PIN K17 [get_ports cmos1_sda]

 

set_property IOSTANDARD LVCMOS33 [get_ports cmos1_vsync_i]

set_property IOSTANDARD LVCMOS33 [get_ports cmos1_href_i]

set_property IOSTANDARD LVCMOS33 [get_ports cmos1_pclk_i]

set_property IOSTANDARD LVCMOS33 [get_ports cmos1_xclk_o]

set_property IOSTANDARD LVCMOS33 [get_ports cmos1_data_i[*]]

set_property IOSTANDARD LVCMOS33 [get_ports cmos1_scl]

set_property IOSTANDARD LVCMOS33 [get_ports cmos1_sda]

set_property PULLUP true [get_ports cmos1_scl]

set_property PULLUP true [get_ports cmos1_sda]

 

set_property PACKAGE_PIN Y23 [get_ports HDMI_TX_CLK_P]

set_property PACKAGE_PIN W25 [get_ports {HDMI_TX_P[0]}]

set_property PACKAGE_PIN Y22 [get_ports {HDMI_TX_P[1]}]

set_property PACKAGE_PIN Y25 [get_ports {HDMI_TX_P[2]}]

 

set_property IOSTANDARD TMDS_33 [get_ports HDMI_TX_CLK_P]

set_property IOSTANDARD TMDS_33 [get_ports {HDMI_TX_P[*]}]

 

 

set_property DCI_CASCADE {32 34} [get_iobanks 33]

 

set_property CFGBVS VCCO [current_design]

set_property CONFIG_VOLTAGE 3.3 [current_design]

set_property BITSTREAM.GENERAL.COMPRESS true [current_design]

set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]

set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]

set_property BITSTREAM.CONFIG.SPI_FALL_EDGE Yes [current_design]

4.3硬件连接

4.4PL图形化设计

4.4.1系统框图

为2个输入图像在一个显示器输出,而不出现撕裂,关键就是在于uifdmavbuf的同步机制,这里让uifdmavbuf1的vid_wsync_o作为同步信号,分别给uifdmavbuf1的读和写通道,以及uifdmavbuf2的写通道使用。uifdmavbuf2的读通道没有使用。

4.4.2PL图形化编程

4.4.3uifdma_vbuf参数设置

这里是把摄像头的输出分辨率设置为640*480,并且把相同的摄像头数据分别输入到uifdma_vbuf0和uifdma_vbuf1的写通道。输出到显示器的分辨率为1280*720

 

4.5程序分析

4.5.1显示原理设计

 

为了把2个图像显示到1个显示器,首先得搞清楚以下关系:

hsize:每1行图像实际在内存中占用的有效空间,以32bit表示一个像素的时候占用内存大小为hsize*4

hstride:用于设置每行图像第一个像素的地址,以32bit 表示一个像素的时候h_cnt* hstride*4

vsize:有效的行

可以看到以上

video1_hstride= hstride;

video2_hstride= hstride;

因此很容易得出video1的每行第一个像素的地址也是h_cnt* hstride*4

同理如果我们需要把video2在hsize和vsize空间的任何位置显示,我们只要关心video2每一行图像第一个像素的地址,可以用以下公式h_cnt* hstride*4+offset

比如我们这里背景输出到显示器的分辨率为1280*720, video2的分辨率是640*480需要移动上图的右下脚,offset=(1280-640)*4*(720-480)

4.5.2多缓存设计原理图

上图中uifdma_vbuf0 ip的write channel的帧同步计数器用于uifdma_vbuf0的读写通道同步以及uifmda_vdbuf1的写通道同步。可以看到uifdma_vbuf0的写通道地址和uifdma_vbuf1的写通道地址相同,另外uifdma_vbuf0的读通道地址,晚一帧于uifdma_vbuf0的写通道地址,这样就可以确保视频图像不会出现读写数据缓存冲突而导致的图像撕裂问题了。以下给出帧计数器,以及地址切换部分代码。具体的可以阅读uifdma_vbuf的源码。

写同步计数器:

if(W0_FS) begin

W_MS <= S_RST;

if(W0_Fbuf < WVBUF_SIZE)

W0_Fbuf <= W0_Fbuf + 1'b1;

else

W0_Fbuf <= 7'd0;

end

写地址的切换:

assign fdma_waddr = fdma_waddr_base + W0_addr;

always @(*) begin

case(W0_Fbuf_sync[1:0])

0:fdma_waddr_base = WVBUF0_ADDR;

1:fdma_waddr_base = WVBUF1_ADDR;

2:fdma_waddr_base = WVBUF2_ADDR;

default :

fdma_waddr_base = WVBUF0_ADDR;

endcase

end

帧延迟控制:

module uisetvbuf#(

parameter integer BUF_DELAY = 1,

parameter integer BUF_LENTH = 3

)

(

input [3 :0] bufn_i,

output [3 :0] bufn_o

);

assign bufn_o = (bufn_i+(BUF_LENTH -BUF_DELAY))%BUF_LENTH;

endmodule

读地址的切换:

assign fdma_raddr = fdma_raddr_base + R0_addr;

always @(*) begin

case(R0_Fbuf_sync[1:0])

0:fdma_raddr_base = RVBUF0_ADDR;

1:fdma_raddr_base = RVBUF1_ADDR;

2:fdma_raddr_base = RVBUF2_ADDR;

default :

fdma_raddr_base = RVBUF2_ADDR;

endcase

end

4.6实验结果


路过

雷人

握手

鲜花

鸡蛋
发表评论

最新评论

引用 uisrc 2021-8-12 20:30
本章节源码下载地址链接:https://pan.baidu.com/s/1NT-ArWeJuLTtPX-Fv1oGFA 提取码1111

查看全部评论(1)

本文作者
2021-8-12 09:44
  • 7
    粉丝
  • 2679
    阅读
  • 1
    回复
  • 1
  • 2
  • 3
热门评论
排行榜