xapp1167与TRD14.4 关系
xapp1167与TRD14.4 都是学习zynq的最佳参考设计。都是基于ZC702,而不是zedboard的,如果要用zedboard那么必须修改硬件配置,因为在702板子中HDMI用的是软核,而zedboard中用的芯片,另外还有网卡等等都不一样配置也不一样。
2:TRD14 :http://www.wiki.xilinx.com/Zynq+Base+TRD+14.3
3:还有一个比较好的资料是workshop:http://china.xilinx.com/support/university/professors.html
TRD
TRD中包含5个文件,其中HW_platform、 zynq_fsbl、 standalone_bsp,外加uboot.elf 用于BOOT.BIN生成,sobel_qt用于界面应用程序,sobel_cmd包含了软件实现sobel代码实现和VDMA的驱动程序等等,只不过没有在LINUX环境中编译,用的是SDK中编译环境,其实编译器还是LINUX编译链。
TRD是用了sobel的FPGA硬件IP核与软件实现sobel算法比较,如下图是sobel的硬件核输入输出是AXI-Stream流,配合一个VDMA(HP接口)用作视频流与DDR的数据交换
以下是TRD中软件实现sobel的函数 img_filters.c
/***************************************************************************** * * @file img_filters.h * * Implementation of software Sobel filter. * ******************************************************************************/ #include <stdio.h> #include <malloc.h> #include "img_filters.h" static ZNQ_U8 line_buffer[3][1920]; // considering max width as 1920 TODO: change this in more professional way. unsigned char rgb2y(ZNQ_U8 R, ZNQ_U8 G, ZNQ_U8 B) { unsigned char y; y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16; return y; } void img_process(ZNQ_S32 *rgb_data_in, ZNQ_S32 *rgb_data_out, int height, int width, int stride) { short x_weight; short y_weight; short edge_weight; ZNQ_U8 edge_val; ZNQ_U8 in_R, in_G, in_B; ZNQ_INT pix_i = 0, pix_j = 0; /* Clearing 0th row : Sobel filter is not applied on 0th ROW: to have consistent data flow */ for(pix_j = 0; pix_j < width; pix_j++) { rgb_data_out[pix_j] = 0; } rgb_data_out = rgb_data_out + stride; /* convert initial(i-1 & i) 2-rows of RGB pixel data into line buffers after conv. into Y(luminance) */ for(pix_j = 0; pix_j < (width + 1); pix_j++) { //line_buffer[0][pix_j] = (((ZNQ_INT)(in_pix[0][pix_j].R + in_pix[0][pix_j].G + in_pix[0][pix_j].B) + 64) >> 2) ; in_B = ((*rgb_data_in) & 0x000000FF); in_G = (((*rgb_data_in) >>8 )& 0x000000FF); in_R = (((*rgb_data_in) >>16)& 0x000000FF); line_buffer[0][pix_j] = rgb2y(in_R, in_G, in_B) ; rgb_data_in++; } rgb_data_in = rgb_data_in + stride - width - 1; /* In-case Stride is different from WIDTH of the row */ for(pix_j = 0; pix_j < (width + 1); pix_j++) /* 1st row */ { /* line_buffer[1][pix_j] = (((ZNQ_INT)(in_pix[1][pix_j].R + in_pix[1][pix_j].G + in_pix[1][pix_j].B) + 64) >> 2) ; */ in_B = ((*rgb_data_in) & 0x000000FF); in_G = (((*rgb_data_in) >>8 )& 0x000000FF); in_R = (((*rgb_data_in) >>16)& 0x000000FF); line_buffer[1][pix_j] = rgb2y(in_R, in_G, in_B) ; rgb_data_in++; } rgb_data_in = rgb_data_in + stride - width - 1; /* In-case Stride is different from WIDTH of the row */ /* ++ went 1beyond so (-1) */ for(pix_i = 2; pix_i < height; pix_i++) { /* copy (pix_i) row into line_buffer, i.e: line_buffer[2] <-- row[pix_i] */ for(pix_j = 0; pix_j < (width + 1); pix_j++) { /* line_buffer[2][pix_j] = (((ZNQ_INT)(in_pix[pix_i][pix_j].R + in_pix[pix_i][pix_j].G + in_pix[pix_i][pix_j].B) + 64) >> 2) ; */ //new pixel...rgb2y(temp1); in_B = ((*rgb_data_in) & 0x000000FF); in_G = (((*rgb_data_in) >>8 )& 0x000000FF); in_R = (((*rgb_data_in) >>16)& 0x000000FF); line_buffer[2][pix_j] = rgb2y(in_R, in_G, in_B) ; rgb_data_in++; } rgb_data_in = rgb_data_in + stride - width - 1; /* In-case Stride is different from WIDTH of the row */ *rgb_data_out = 0; // making first pixel zero. /* compute Sobel filtering over (pix_i - 1) pixels, i.e: sobel_filtering(&line_buffer[1][0])*/ for(pix_j = 1; pix_j < (width + 1); pix_j++) { x_weight = line_buffer[0][pix_j-1]*(-1) + line_buffer[0][pix_j+1] + line_buffer[1][pix_j-1]*(-2) + line_buffer[1][pix_j+1]*(2) + line_buffer[2][pix_j-1]*(-1) + line_buffer[2][pix_j+1] ; // x_weight = window[0][0]*(-1) + window[0][2] + window[1][0]*(-2) + window[1][2]*(2) + window[2][0]*(-1) + window[2][2] ; y_weight = line_buffer[0][pix_j-1] + line_buffer[0][pix_j]*(2) + line_buffer[0][pix_j+1] + line_buffer[2][pix_j-1]*(-1) + line_buffer[2][pix_j]*(-2) + line_buffer[2][pix_j+1]*(-1) ; // y_weight = window[0][0] + window[0][1]*(2) + window[0][2] + window[2][0]*(-1) + window[2][1]*(-2) + window[2][2]*(-1) ; edge_weight = ABS(x_weight) + ABS(y_weight); //Added RGB fix-06-dec-12 if(edge_weight < 255) edge_val = (255-(unsigned char)(edge_weight)); else edge_val = 0; if(edge_val > 200) edge_val = 255; else if(edge_val < 100) edge_val = 0; //out_pix2_ptr = &(out_pix2[0][0]); // out_pix2[pix_i-1][pix_j].R = out_pix2[pix_i-1][pix_j].G = out_pix2[pix_i-1][pix_j].B = edge_val; // write the edge value into RGB ////////////////////////////////////////////// { rgb_data_out++; /* col starts from 1 NOT 0...???*be careful here */ *rgb_data_out = (edge_val) | (edge_val<<8) | (edge_val<<16) | 0xFF000000; } } /* --Sobel_filtering(row[pix_i - 1]) complete */ rgb_data_out = rgb_data_out + stride - width; /* In-case Stride is different from WIDTH of the row */ /* copy the history of pixel data */ /* row[pix_i - 2] <-- row[pix_i - 1], i.e: line_buf[0] <-- line_buf[1] */ /* row[pix_i - 1] <-- row[pix_i], i.e: line_buf[1] <-- line_buf[2] */ for(pix_j = 0; pix_j < (width /* PBJ no need of '+ 1' */); pix_j++) { line_buffer[0][pix_j] = line_buffer[1][pix_j] ; line_buffer[1][pix_j] = line_buffer[2][pix_j] ; } } // clearing the last line for(pix_j=0; pix_j < width; pix_j++) { rgb_data_out[pix_j] = 0; } }
XAPP1167
Accelerating OpenCV Applications with Zynq-7000 All Programmable SoC using Vivado HLS Video Libraries
xapp1167主要是用HLS实现sobel算法,在HLS中用的OPENCV库编写,然后生成pcore加入EDK中,
XAPP1167包含
4. DESIGN FILE HIERARCHY
=========================
The directory structure underneath this top-level folder is described
below:
|-- boot_image/
| |-- bootgen.sh # Script to build BOOT.bin
| |-- bootimage.bif # Include file names to create boot image
| |-- system.bit # Hardware bitstream to configure the FPGA
| |-- u-boot.elf # u-boot Boot Loader executable
| |-- zynq_fsbl.elf # Zynq First stage boot loader executable
|
|-- hw/
| |-- xps_proj/ # XPS hardware project for TRD design
|
|-- opencv_install/
| |-- arm_Linux/ # OpenCV libraries and header files for ARM
|
|-- sd_image/
| |-- BOOT.bin # Zynq Boot Image, which is created from
| | FSBL, hardware bitstream and u-boot
| |-- devicetree.dtb # Linux device tree binary, loaded into
| | memory by u-boot (1080p resolution)
| |-- init.sh # Script to set up environment, sourced at the
| | end of the boot process
| |-- opencv_lib.img # Pre-compiled OpenCV libraries required to
| | run the application
| |-- run.sh # Wrapper script for application
| |-- uramdisk.image.gz # Ramdisk image, loaded into memory by u-boot
| |-- uImage # Linux kernel image, loaded into memory by
| | u-boot
| |-- video_library_cmd # Cmd line based Linux application executable
|
|-- sw/
| |-- demo/ # Demo design for OpenCV-acceleration
| |-- fast-corner/ # Corner-detection design for OpenCV-acceleration
| |-- share/ # Shared source files for ARM Linux application
|
|-- README.txt # This file
|
|-- Video_Library_Windows.bat # The batch file to start TRD on Windows
To enable easily building the reference designs, a Makefile is also provided
with the following targets:
‘make elf‘ -- build sw (video_library_cmd)
‘make sim‘ -- build and run csim test
‘make core‘ -- synthesis and export pcore
‘make bitstream‘ -- generate bistream (system.bit)
‘make boot‘ -- generate boot image (BOOT.bin)
‘make all‘ -- build sw and hw, generate sd_image
Running ‘make all‘ from the Linux command line or the Vivado HLS Command Prompt under Windows that launched by provided batch file rebuilds the entire design and generates an SD card image that can be run. Detailed instructions to Build Hardware
and Software for this TRD are provided in XAPP1167.
我们用vivado HLS command 窗口进去E:\vivado_project\xapp1167_ise\sw\demo
make all
然后在目录中生成所有的硬软件源文件,包括EDK,HLS。。工程
最后这句话我们终于明白了:
XAPP1167是详细解释了怎么实现TRD的软硬件过程,而TRD仅仅是个操作步骤流程图说明,没有带任何具体实现
HLS OPENCV 实现sobel
***************************************************************************/ #include "top.h" void image_filter(AXI_STREAM& INPUT_STREAM, AXI_STREAM& OUTPUT_STREAM, int rows, int cols) { //Create AXI streaming interfaces for the core #pragma HLS INTERFACE axis port=INPUT_STREAM #pragma HLS INTERFACE axis port=OUTPUT_STREAM #pragma HLS RESOURCE core=AXI_SLAVE variable=rows metadata="-bus_bundle CONTROL_BUS" #pragma HLS RESOURCE core=AXI_SLAVE variable=cols metadata="-bus_bundle CONTROL_BUS" #pragma HLS RESOURCE core=AXI_SLAVE variable=return metadata="-bus_bundle CONTROL_BUS" #pragma HLS INTERFACE ap_stable port=rows #pragma HLS INTERFACE ap_stable port=cols RGB_IMAGE img_0(rows, cols); RGB_IMAGE img_1(rows, cols); RGB_IMAGE img_2(rows, cols); RGB_IMAGE img_3(rows, cols); RGB_IMAGE img_4(rows, cols); RGB_IMAGE img_5(rows, cols); RGB_PIXEL pix(50, 50, 50); #pragma HLS dataflow hls::AXIvideo2Mat(INPUT_STREAM, img_0); hls::Sobel<1,0,3>(img_0, img_1); hls::SubS(img_1, pix, img_2); hls::Scale(img_2, img_3, 2, 0); hls::Erode(img_3, img_4); hls::Dilate(img_4, img_5); hls::Mat2AXIvideo(img_5, OUTPUT_STREAM); }
参考
==============
XAPP1167 - Accelerating OpenCV Applications with Zynq-7000 All Programmable SoC using Vivado HLS Video Libraries
UG902 - Vivado Design Suite User Guide: High-Level Synthesis
US873 - Zynq Concepts, Tools and Techniques
UG798 - Xilinx Design Tools: Installation and Licensing Guide
UG926 - Zynq-7000 ZC702 Evaluation Kit Getting Started Guide
UG850 - ZC702 Evaluation Board User Guide
http://www.wiki.xilinx.com/Zynq+Base+TRD+14.5