Вы находитесь на странице: 1из 13

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 IPs 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.

1
AXI OV7670 Decoder
Chapter 1: Overview

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.

AXI OV7670 DECODER

Video Input Video In Video In to AXI4-


M_AXIS
(Pre-Decoder) Stream IP
AXI4-Lite Interface

I2C_AV_CONFIG

Memory I2C Signals


S_AXI Write
Logic BRAM Memory I2C_Controller

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.

2
AXI OV7670 Decoder
Chapter 1: Overview

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.

3
AXI OV7670 Decoder
Chapter 2: Product Specification

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

4
AXI OV7670 Decoder
Chapter 2: Product Specification

Register Space
The AXI OV7670 Decoder registers are shown in Table 3.

Table 3 - AXI OV7670 Decoder registers

Address Space Register Access Default Description


Offset Name Type Value
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.

Not used Internal Memory Position Camera Register Register Value

31 24 23 16 15 8 7 0

Figure 2 - Memory write register

Table 4 - Memory write register description

Bits Access Description


Type
[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

5
AXI OV7670 Decoder
Chapter 2: Product Specification

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.

Not used Reset Bit

31 1 0

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.

Not used Colour Format

31 3 2 0

Figure 4 - Select Decoder Type register

Table 5 Select Decoder Type description

Bits Access Description


Type
[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.

6
AXI OV7670 Decoder
Chapter 3: Designing with the Core

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.

7
AXI OV7670 Decoder
Chapter 4: Example Design

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.

(MicroBlaze, memory, etc.)

AXI Interconnect

Camera AXI OV7670 TFT VGA Display


VDMA
Decoder Controller

AXI4-Stream

Figure 5 - Video Data Flow

8
AXI OV7670 Decoder
Appendix

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;

9
AXI OV7670 Decoder
Appendix

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;

10
AXI OV7670 Decoder
Appendix

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;

11
AXI OV7670 Decoder
Appendix

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;
}

12
AXI OV7670 Decoder
Appendix

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.

13
AXI OV7670 Decoder

Вам также может понравиться