Zedboard OV7670

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was completed in an hour in January 2013.

I've attached a low cost OV7670 module used for OV7670_camera to my Zedboard, using the PMOD connector.

Zedboard OV7670.jpg

Zedboard OV7670 2.jpg

The codebase is pretty much the same as the OV7670_camera, but enhanced to make the most of the larger frame buffer available in the Zynq-7020. It also fixes a few bugs in the original design.

Contents

Capturing the pixel data

This is the crux of the design:

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Description: Captures the pixels coming from the OV7670 camera and 
--              Stores them in block RAM
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity ov7670_capture is
    Port ( pclk  : in   STD_LOGIC;
           vsync : in   STD_LOGIC;
           href  : in   STD_LOGIC;
           d     : in   STD_LOGIC_VECTOR (7 downto 0);
           addr  : out  STD_LOGIC_VECTOR (18 downto 0);
           dout  : out  STD_LOGIC_VECTOR (11 downto 0);
           we    : out  STD_LOGIC);
end ov7670_capture;

architecture Behavioral of ov7670_capture is
   signal d_latch      : std_logic_vector(15 downto 0) := (others => '0');
   signal address      : STD_LOGIC_VECTOR(18 downto 0) := (others => '0');
   signal address_next : STD_LOGIC_VECTOR(18 downto 0) := (others => '0');
   signal wr_hold      : std_logic_vector(1 downto 0)  := (others => '0');
   
begin
   addr <= address;
   process(pclk)
   begin
      if rising_edge(pclk) then
         -- This is a bit tricky href starts a pixel transfer that takes 3 cycles
         --        Input   | state after clock tick   
         --         href   | wr_hold    d_latch           d                 we address  address_next
         -- cycle -1  x    |    xx      xxxxxxxxxxxxxxxx  xxxxxxxxxxxxxxxx  x   xxxx     xxxx
         -- cycle 0   1    |    x1      xxxxxxxxRRRRRGGG  xxxxxxxxxxxxxxxx  x   xxxx     addr
         -- cycle 1   0    |    10      RRRRRGGGGGGBBBBB  xxxxxxxxRRRRRGGG  x   addr     addr
         -- cycle 2   x    |    0x      GGGBBBBBxxxxxxxx  RRRRRGGGGGGBBBBB  1   addr     addr+1

         if vsync = '1' then 
            address <= (others => '0');
            address_next <= (others => '0');
            wr_hold <= (others => '0');
         else
            dout    <= d_latch(10 downto 7) & d_latch(15 downto 12) & d_latch(4 downto 1); 
            address <= address_next;
            we      <= wr_hold(1);
            wr_hold <= wr_hold(0) & (href and not wr_hold(0));
            d_latch <= d_latch( 7 downto  0) & d;

            if wr_hold(1) = '1' then
               address_next <= std_logic_vector(unsigned(address_next)+1);
            end if;

         end if;
      end if;
   end process;
end Behavioral;

The full project

Source will be here soon, but for now here is a zip of the project.

File:Zedboard OV7670.zip

Here is an updated project, which uses my I3C2 controller to initialise the camera correctly, and captures in QVGA (160x120) so it is small enough to work with my Nexys2:

File:Ov7670 fr nexys2.zip

Here is (yet another) updated project, which uses my I3C2 controller to initialise the camera correctly, and captures in QVGA (160x120) but this time for the Zedboard:

File:Ov7670 fr zedboard.zip

This version shows a 640x480 picture, and if you press the left or right buttons on the Zedboard it shows either 160x120 or 320x240 frame, so with only a little bit of work it should fit most needs.

The camera initialisation now works correctly every time - I was missing the 1ms pause between the device resets and the register programming.

A design for a PCB

This is my first ever PCB design, and it is yet to be sent to a PCB service for making, so think of it as a work in progress!

File:Zedboard Camera PCB.zip

A big thanks

Chris Wilson at the University of Florida helped out by finding the correct register settings to get colours working correctly. It required some undocumented register settings.

Here is the before and after images:

Ov7670 compared.jpg

Also a big thanks for Fellag Ratiba for her help in sorting out a few of the bugs - some of her code is in the project...

Personal tools