1 AXI OV7670 Decoder
AXI OV7670 Decoder
The AXI OV7670 Decoder provides an AXI interface decoder for the output of the OmniVision OV7670 VGA video camera. The decoder provides a bridge between the camera input and video processing cores with AXI4-Stream Video Protocol interfaces. It also provides a software based camera configuration core.
This IP is largely based on the codes provided in class and on the Xilinx LogiCORE IP Video In to AXI4-Stream.
It is of great importance to fully read this document before trying to use the IP. It is highly recommend to read the datasheets for the Xilinx IP’s mentioned in this document.
This IP was designed to operate with the Digilent Nexys4 DDR FPGA board and Vivado 2014.1
DISCLAIMER
THIS IP IS PROVIDED ‘AS-IS’, WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN NO EVENT WILL THE AUTHORS BE HELD LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THIS IP.
Permission is granted to anyone to use this IP for any purpose and to alter it and redistribute it freely. All Xilinx, Inc. licensing requirements must be met for that.
This IP was NOT designed by a professional. It was designed by an undergraduate student. Therefore, do not expect the code to be error free, optimized, error tolerant and there is no API.
This IP and this file were made by Gustavo Maia Ferreira as part of the course ECE532 Digital Systems Design, spring 2015, University of Toronto, CA.
Xilinx, Inc. Xilinx, the Xilinx logo, Artix, ISE, Kintex, Spartan, Virtex, Vivado, Zynq, and other designated brands included herein are trademarks of Xilinx in the United States and other countries. AMBA, AMBA Designer, ARM, ARM1176JZ-S, CoreSight, Cortex, and PrimeCell are trademarks of ARM in the EU and other countries. OmniPixel, VarioPixel, OmniVision and the OmniVision logo are registered trademarks of OmniVision Technologies, Inc. All other trademarks are the property of their respective owners.
Chapter 1: Overview
2 AXI OV7670 Decoder
CHAPTER 1: OVERVIEW
Functional Description
The AXI OV7670 Decoder provides an AXI4-Stream Video Protocol for the input of the OV7670 camera and a software based camera configuration.
The top-level block diagram of the AXI OV7670 Decoder is shown in Figure 1.
Figure 1 - Top-Level block diagram of AXI OV7670 Decoder
OV7670 Camera Interface
The OV7670 Camera Interface consists of 15 out of the 16 signals that connect to the camera as a PMOD. These signals are divided between Video Input (video data and timing) and I2C Signals (camera configuration). One extra signal is required to be set externally, which is OV7670_XCLK, the system clock.
AXI4-Lite Interface
The AXI4-Lite Interface implements a 32-bit AXI4-Lite slave interface for changing between the RGB colour formats available with the camera, writing the camera configuration and soft reset of the camera configuration. A Memory Write Logic is needed to translate the information at the input registers to the internal memory.
AXI OV7670 DECODER
AX
I4-L
ite In
terfa
ce
S_AXI
Video In to AXI4-
Stream IPM_AXIS
Memory
Write
Logic
I2C_AV_CONFIG
BRAM Memory I2C_Controller
Video In
(Pre-Decoder)
I2C Signals
Video Input
Chapter 1: Overview
3 AXI OV7670 Decoder
AXI4-Stream Interface
The AXI4-Stream Interface implements a 32-bit AXI4-Stream Video Protocol master interface. It consists of parallel video data (tdata), handshaking signals (tvalid and tready) and two flags (tlast and tuser). The flag tlast corresponds to the video protocol signal end of line (EOL) and the flag tuser corresponds to the video protocol start of frame (SOF). The Xilinx IP Video In to AXI4-Stream generates this interface. The output is a 32-bit pixel RGB888, with 8 bits 0 added at the 8 MSBs.
I2C_AV_Config
This block implements the I2C standard for the camera configuration. It is based on the code provided in class. A BRAM memory is used instead of a Look-up Table, allowing for modifications via software.
Video In (pre-decoder)
This block provides a bridge between the camera data and timing signals to the expected input of the Video In to AXI4-Stream IP. It is based on the code provided in class.
Chapter 2: Product Specification
4 AXI OV7670 Decoder
CHAPTER 2: PRODUCT SPECIFICATION
Performance
The core was implemented in an Artix-7 xc7a100tcsg324-1 with a 100 MHz clock frequency.
Resource Utilization
Table 1 - Device Resources Utilization (Post-Implementation)
Device Resources
Flip-Flops LUTs Memory LUTs BRAM
417 349 97 1
Port Descriptions
The AXI OV7670 Decoder I/O signals are listed and described in Table 2.
Table 2 - Port Descriptions
Signal Name Interface I/O Description
s_axi_aclk Clock I AXI Clock
s_axi_aresetn Reset I AXI Reset, active-Low
s_axi_* S_AXI NA AXI4-Lite Slave interface signals
m_axis_aclk Clock I AXIS Clock
m_axis_aresetn Reset I AXIS Reset, active-Low
m_axis_* M_AXIS NA AXI4-Stream Master interface signals
pclk Camera I Pixel clock
vsync Camera I Vertical Sync
href Camera I HREF
d Camera I Video component input
resetI2C Camera I Reset I2C. Default 0
I2C_SCLK Camera O I2C Clock
I2C_SDAT Camera I/O I2C Data
pwdn Camera O Power down mode select. Default 1
reset System I I2C Reset, active-High.
Config_Done System O Flag for camera configuration finished
Chapter 2: Product Specification
5 AXI OV7670 Decoder
Register Space
The AXI OV7670 Decoder registers are shown in Table 3. Table 3 - AXI OV7670 Decoder registers
Address Space Offset
Register Name
Access Type
Default Value
Description
0x00 slv_reg0 R/W 0x0 Write camera configuration
0x04 slv_reg1 R/W 0x0 Reset camera configuration
0x08 slv_reg2 R/W 0x0 Select decoder type
Write Camera Configuration (slv_reg0)
The camera configuration is saved in an internal memory. To write to this memory, each word must be passed via this register. The memory can store up to 256 words. A new word is written every time new data is written to this register. Therefore, all the 256 memory positions must be written using this register.
The code in Appendix A provides an example of how to configure the camera. Details can be found in the camera datasheet.
This register must be written following the standard presented in Figure 2.
Figure 2 - Memory write register
Table 4 - Memory write register description
Bits Access Type
Description
[31:24] R/W Not used
[23:16] R/W Internal memory address for the respective camera configuration word
[15:8] R/W Camera register address for the respective camera configuration word
[7:0] R/W Register value for the respective register address
31 24 23 16 15 8 7 0
Not used Internal Memory Position Camera Register Register Value
Chapter 2: Product Specification
6 AXI OV7670 Decoder
Reset Camera Configuration (slv_reg1)
This register provides a camera configuration reset to Microblaze. Active High. If bit 0 is 1, camera configuration is run again.
Figure 3 - Reset camera configuration register
Select Decoder Type (slv_reg2)
This register provides flexibility to the decoder. RGB444, RGB555 and RGB565 are supported. The other colour formats are not specified by the preliminary camera datasheet.
Figure 4 - Select Decoder Type register
Table 5 – Select Decoder Type description
Bits Access Type
Description
[31:3] R/W Not used
[2:0] R/W Select decoder type 000: RGB444 001: RGB555 010: RGB565
Decoding is accomplished by shifting bits. If another type of decoding is needed, the IP source code should be changed.
31 1 0
Not used Reset Bit
31 3 0
Not used Colour Format
2
Chapter 3: Designing with the Core
7 AXI OV7670 Decoder
CHAPTER 3: DESIGNING WITH THE CORE
Operation
The camera inputs and outputs should be connected to this core. One camera input still needs to be connected externally. This input (OV7670_XCLK) connects to the system clock. The Stream interface should be connected to the next component of the dataflow, usually an AXI4-Stream Interconnect or the Video DMA. The AXI4-Lite interface should be connected as a Slave to the microprocessor.
Programming Sequence
Before using the video data, the camera must be configured. The code provided in Appendix A is an example of the camera configuration code. The camera datasheet must be consulted for more information. After the initial configuration, any memory position can be changed but the I2C Controller must be reset. The second slave register provides the microprocessor with such reset option. The decoder type at the third slave register must match with the video data configured on the camera.
Clocking
The AXI OV7670 Decoder has three clock domains:
s_axi_aclk – Associates with the AXI4-Lite slave interface.
m_axis_aclk – Associates with the AXI4-Stream master interface.
pclk – Camera pixel clock.
The two AXI clocks can be the same. The clock domain crossing is handled by the Video In to AXI-Stream IP.
Resets
Similarly to the clocks, the AXI OV7670 Decoder has two active-Low resets, one for each AXI interface. The camera configuration reset can be used when it is wanted to run the I2C configuration again. It can be achieved by software using slv_reg1 or by hardware using the input reset. Both are active High.
Chapter 4: Example Design
8 AXI OV7670 Decoder
CHAPTER 4: EXAMPLE DESIGN
The example design is a Video In / Video Out design. This IP is used as a bridge between the camera output and the AXI4-Stream Interface. It is connected to a Video DMA via an AXI4-Stream Interconnect. The VDMA moves the video data to the memory. The image is displayed using the TFT Controller IP.
Figure 5 is a high-level view of the video data flow of this design.
Figure 5 - Video Data Flow
AXI OV7670
DecoderVDMA
TFT
Controller
AXI Interconnect
(MicroBlaze, memory, etc.)
VGA DisplayCamera
AXI4-Stream
Appendix
9 AXI OV7670 Decoder
APPENDIX A – Additional Resources
The following code is used to test the IP. The function config_OV7670 has the camera configuration. It can be used as default code and new configurations can be added after the comment “// Mirror” (this line is inverting the camera output). #include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#define PRINT xil_printf
void print(char *str);
volatile unsigned int * decoder = (unsigned int*) XPAR_OV7670_DECODER_0_S00_AXI_BASEADDR;
volatile unsigned int * vdma = (unsigned int*) XPAR_AXI_VDMA_0_BASEADDR;
volatile unsigned int * AR = (unsigned int*) XPAR_TFT_0_BASEADDR;//TFT CONFIGURE PARAMETER
void config_OV7670() {
decoder[1] = 0;
decoder[0] = 0x000000;
decoder[0] = 0x010000;
decoder[0] = 0x023a04;
decoder[0] = 0x033dc8;
decoder[0] = 0x041e31;
decoder[0] = 0x056b00;
decoder[0] = 0x0632b6;
decoder[0] = 0x071713;
decoder[0] = 0x081801;
decoder[0] = 0x091902;
decoder[0] = 0x0A1a7a;
decoder[0] = 0x0B030a;
decoder[0] = 0x0C0c00;
decoder[0] = 0x0D3e00;
decoder[0] = 0x0E7000;
decoder[0] = 0x0F7100;
decoder[0] = 0x107211;
decoder[0] = 0x117300;
decoder[0] = 0x12a202;
decoder[0] = 0x131180;
decoder[0] = 0x147a20;
decoder[0] = 0x157b1c;
decoder[0] = 0x167c28;
decoder[0] = 0x177d3c;
decoder[0] = 0x187e55;
decoder[0] = 0x197f68;
decoder[0] = 0x1A8076;
decoder[0] = 0x1B8180;
decoder[0] = 0x1C8288;
decoder[0] = 0x1D838f;
decoder[0] = 0x1E8496;
decoder[0] = 0x1F85a3;
decoder[0] = 0x2086af;
decoder[0] = 0x2187c4;
decoder[0] = 0x2288d7;
decoder[0] = 0x2389e8;
decoder[0] = 0x2413e0;
decoder[0] = 0x250000;
decoder[0] = 0x261000;
decoder[0] = 0x270d00;
decoder[0] = 0x281428;
decoder[0] = 0x29a505;
decoder[0] = 0x2Aab07;
decoder[0] = 0x2B2475;
decoder[0] = 0x2C2563;
decoder[0] = 0x2D26a5;
decoder[0] = 0x2E9f78;
decoder[0] = 0x2Fa068;
decoder[0] = 0x30a103;
decoder[0] = 0x31a6df;
decoder[0] = 0x32a7df;
decoder[0] = 0x33a8f0;
decoder[0] = 0x34a990;
decoder[0] = 0x35aa94;
decoder[0] = 0x3613ef;
Appendix
10 AXI OV7670 Decoder
decoder[0] = 0x370e61;
decoder[0] = 0x380f4b;
decoder[0] = 0x391602;
decoder[0] = 0x3A2102;
decoder[0] = 0x3B2291;
decoder[0] = 0x3C2907;
decoder[0] = 0x3D330b;
decoder[0] = 0x3E350b;
decoder[0] = 0x3F371d;
decoder[0] = 0x403871;
decoder[0] = 0x41392a;
decoder[0] = 0x423c78;
decoder[0] = 0x434d40;
decoder[0] = 0x444e20;
decoder[0] = 0x456900;
decoder[0] = 0x467419;
decoder[0] = 0x478d4f;
decoder[0] = 0x488e00;
decoder[0] = 0x498f00;
decoder[0] = 0x4A9000;
decoder[0] = 0x4B9100;
decoder[0] = 0x4C9200;
decoder[0] = 0x4D9600;
decoder[0] = 0x4E9a80;
decoder[0] = 0x4Fb084;
decoder[0] = 0x50b10c;
decoder[0] = 0x51b20e;
decoder[0] = 0x52b382;
decoder[0] = 0x53b80a;
decoder[0] = 0x544314;
decoder[0] = 0x5544f0;
decoder[0] = 0x564534;
decoder[0] = 0x574658;
decoder[0] = 0x584728;
decoder[0] = 0x59483a;
decoder[0] = 0x5A5988;
decoder[0] = 0x5B5a88;
decoder[0] = 0x5C5b44;
decoder[0] = 0x5D5c67;
decoder[0] = 0x5E5d49;
decoder[0] = 0x5F5e0e;
decoder[0] = 0x606404;
decoder[0] = 0x616520;
decoder[0] = 0x626605;
decoder[0] = 0x639404;
decoder[0] = 0x649508;
decoder[0] = 0x659508;
decoder[0] = 0x666d55;
decoder[0] = 0x676e11;
decoder[0] = 0x686f9f;
decoder[0] = 0x696a40;
decoder[0] = 0x6A0140;
decoder[0] = 0x6B0240;
decoder[0] = 0x6C13e7;
decoder[0] = 0x6D1500;
decoder[0] = 0x6E4f80;
decoder[0] = 0x6F5080;
decoder[0] = 0x705100;
decoder[0] = 0x715222;
decoder[0] = 0x72535e;
decoder[0] = 0x735480;
decoder[0] = 0x74589e;
decoder[0] = 0x754108;
decoder[0] = 0x763f00;
decoder[0] = 0x777505;
decoder[0] = 0x7876e1;
decoder[0] = 0x794c00;
decoder[0] = 0x7A7701;
decoder[0] = 0x7B4b09;
decoder[0] = 0x7Cc9F0;
decoder[0] = 0x7D4138;
decoder[0] = 0x7E5640;
decoder[0] = 0x7F3411;
decoder[0] = 0x803b02;
decoder[0] = 0x81a489;
decoder[0] = 0x829600;
decoder[0] = 0x839730;
decoder[0] = 0x849820;
decoder[0] = 0x859930;
decoder[0] = 0x869a84;
decoder[0] = 0x879b29;
Appendix
11 AXI OV7670 Decoder
decoder[0] = 0x889c03;
decoder[0] = 0x899d4c;
decoder[0] = 0x8A9e3f;
decoder[0] = 0x8B7804;
decoder[0] = 0x8C7901;
decoder[0] = 0x8Dc8f0;
decoder[0] = 0x8E790f;
decoder[0] = 0x8Fc800;
decoder[0] = 0x907910;
decoder[0] = 0x91c87e;
decoder[0] = 0x92790a;
decoder[0] = 0x93c880;
decoder[0] = 0x94790b;
decoder[0] = 0x95c801;
decoder[0] = 0x96790c;
decoder[0] = 0x97c80f;
decoder[0] = 0x98790d;
decoder[0] = 0x99c820;
decoder[0] = 0x9A7909;
decoder[0] = 0x9Bc880;
decoder[0] = 0x9C7902;
decoder[0] = 0x9Dc8c0;
decoder[0] = 0x9E7903;
decoder[0] = 0x9Fc840;
decoder[0] = 0xA07905;
decoder[0] = 0xA1c830;
decoder[0] = 0xA27926;
decoder[0] = 0xA30903;
decoder[0] = 0xA43b42;
decoder[0] = 0xA58c02;
decoder[0] = 0xA640d0;
decoder[0] = 0xA71204;
decoder[0] = 0xA81e11; // Mirror
decoder[0] = 0xA90000;
decoder[0] = 0xAA0000;
decoder[0] = 0xAB0000;
decoder[0] = 0xAC0000;
decoder[0] = 0xAD0000;
decoder[0] = 0xAE0000;
decoder[0] = 0xAF0000;
decoder[0] = 0xB00000;
decoder[0] = 0xB10000;
decoder[0] = 0xB20000;
decoder[0] = 0xB30000;
decoder[0] = 0xB40000;
decoder[0] = 0xB50000;
decoder[0] = 0xB60000;
decoder[0] = 0xB70000;
decoder[0] = 0xB80000;
decoder[0] = 0xB90000;
decoder[0] = 0xBA0000;
decoder[0] = 0xBB0000;
decoder[0] = 0xBC0000;
decoder[0] = 0xBD0000;
decoder[0] = 0xBE0000;
decoder[0] = 0xBF0000;
decoder[0] = 0xC00000;
decoder[0] = 0xC10000;
decoder[0] = 0xC20000;
decoder[0] = 0xC30000;
decoder[0] = 0xC40000;
decoder[0] = 0xC50000;
decoder[0] = 0xC60000;
decoder[0] = 0xC70000;
decoder[0] = 0xC80000;
decoder[0] = 0xC90000;
decoder[0] = 0xCA0000;
decoder[0] = 0xCB0000;
decoder[0] = 0xCC0000;
decoder[0] = 0xCD0000;
decoder[0] = 0xCE0000;
decoder[0] = 0xCF0000;
decoder[0] = 0xD00000;
decoder[0] = 0xD10000;
decoder[0] = 0xD20000;
decoder[0] = 0xD30000;
decoder[0] = 0xD40000;
decoder[0] = 0xD50000;
decoder[0] = 0xD60000;
decoder[0] = 0xD70000;
Appendix
12 AXI OV7670 Decoder
decoder[0] = 0xD80000;
decoder[0] = 0xD90000;
decoder[0] = 0xDA0000;
decoder[0] = 0xDB0000;
decoder[0] = 0xDC0000;
decoder[0] = 0xDD0000;
decoder[0] = 0xDE0000;
decoder[0] = 0xDF0000;
decoder[0] = 0xE00000;
decoder[0] = 0xE10000;
decoder[0] = 0xE20000;
decoder[0] = 0xE30000;
decoder[0] = 0xE40000;
decoder[0] = 0xE50000;
decoder[0] = 0xE60000;
decoder[0] = 0xE70000;
decoder[0] = 0xE80000;
decoder[0] = 0xE90000;
decoder[0] = 0xEA0000;
decoder[0] = 0xEB0000;
decoder[0] = 0xEC0000;
decoder[0] = 0xED0000;
decoder[0] = 0xEE0000;
decoder[0] = 0xEF0000;
decoder[0] = 0xF00000;
decoder[0] = 0xF10000;
decoder[0] = 0xF20000;
decoder[0] = 0xF30000;
decoder[0] = 0xF40000;
decoder[0] = 0xF50000;
decoder[0] = 0xF60000;
decoder[0] = 0xF70000;
decoder[0] = 0xF80000;
decoder[0] = 0xF90000;
decoder[0] = 0xFA0000;
decoder[0] = 0xFB0000;
decoder[0] = 0xFC0000;
decoder[0] = 0xFD0000;
decoder[0] = 0xFE0000;
decoder[0] = 0xFF0000;
decoder[1] = 1; // run camera configuration
decoder[1] = 0;
//PRINT("Finished camera configuration\n");
}
int main ()
{
init_platform();
config_OV7670();
vdma[12] = 0x0000000B; // enable vdma
vdma[43] = 0x80000000; // write base address
vdma[42] = 4*1024; // stride (bytes)
vdma[41] = 4*640; // image size (bytes)
vdma[40] = 512; // number of lines
*AR = 0x80000000;//output;
//decoder[0] = 0xA98C00; // no RGB444. Other formats only work if RGB444 is disabled.
//decoder[0] = 0xAA40F0; // RGB555
//decoder[0] = 0xAB40D0; // RGB565
decoder[2] = 0; // 0 = RGB444, 1 = RGB555, 2 = RGB565
return 0;
}
Appendix
13 AXI OV7670 Decoder
APPENDIX B – Known Issues
During the implementation of this IP, four critical warnings will show up. Those are
[Common 17-55], [Vivado 12-259], [Vivado 12-1387], [Memdata 28-122]. During
the bitstream generation the last warning and the error [Memdata 28-96] will also
appear. All those can be ignored. The first three are related to hierarchical
constraints and the other are related to the fact that the internal memory has no
bmm file linked to it. Fixing these warning is one of the “to do” activities for this IP.
Video decoding is accomplished by simply shifting bits. Depending on the
application, this is not a good strategy. Bytes for YUV and YCbCr colour spaces
are not described in the preliminary camera datasheet. Fixing and expanding the
decoding capabilities of this IP is another “to do” activity.
There is no API other than the default API generated by SDK. No time for that
either.