OpenCores
URL https://opencores.org/ocsvn/ov7670-sccb/ov7670-sccb/trunk

Subversion Repositories ov7670-sccb

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/ov7670-sccb/trunk/hdl/english/hdl/SCCBMaster.vhd
0,0 → 1,448
---------------------------------------------------------------------------------------------------------------------------------------------
-- OV7670 uses SCCB interface for configuring it's registers. That interface is compatible with I2C.
-- But unlike I2C, SCCB has logical-1 state on it's data line.
-- High - Low - High Impedance
--
-- The most important point of this interface is; ACK and NACK bits are useless in write mode. SCCB
-- uses a "Don't Care" bit. That bit is logical-0. You can see the data frame of a write process:
--
-- |A6|A5|A4|A3|A2|A1|A0|R/W|DC|-|R7|R6|R5|R4|R3|R2|R1|R0|DC|-|D7|D6|D5|D4|D3|D2|D1|D0|DC|
-- 7-bit Address 8-Bit Register/Data 8-bit Data
-- R => logical-1
-- W => logical-0
--
-- Warning: This module made for only writing data to registers. Read process will be added. :)
--
--
-- Used Sources : OV7670 Datasheet
-- : OmniVision SCCB Specification
-- : http://www.dejazzer.com/hardware.html (Face detection on FPGA: OV7670 CMOS camera + DE2-115 FPGA board)
-- : http://www.dejazzer.com/eigenpi/digital_camera/digital_camera.html
--
--
---------------------------------------------------------------------------------------------------------------------------------------------
 
 
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.NUMERIC_STD.all;
 
entity SCCBMaster is
generic(
GInputClock : integer := 50_000_000; -- FPGA main clock speed
GBusClock : integer := 400_000 -- Speed of SCCB clock to be used
);
port(
PIClock : in std_logic; -- System clock input
PIReset : in std_logic; -- Reset(active low) input
PIEnable : in std_logic; -- Enable input that enables the SCCB interface
PIAddress : in std_logic_vector(6 downto 0); -- SCCB slave device's address input
PIRegister : in std_logic_vector(7 downto 0); -- SCCB slave device's register input
PIWriteData : in std_logic_vector(7 downto 0); -- Data input
PIStart : in std_logic; -- Module's backend start input
PODone : out std_logic; -- Gives an logical-1 output when the process is complete
POReady : out std_logic; -- Output for determine SCCB line is ready for another operation
PIOSIOD : inout std_logic; -- SCCB serial data I/O
POSIOC : out std_logic -- SCCB clock output
);
end SCCBMaster;
 
architecture Behavioral of SCCBMaster is
 
------------------------------------------------------------------------------------------------------------------
-- In this step; signals and state machine states created for I/O ports and references.
------------------------------------------------------------------------------------------------------------------
 
type TStatesWrite is (idle, start_condition, send_addr, addr_dc, send_reg, reg_dc, send_data, data_dc, stop);
signal SStateWriteBase : TStatesWrite := idle;
constant CClockCountMax : integer := (GInputClock / GBusClock);
signal SStart : std_logic := '0';
signal SStartReg : std_logic := '0';
signal SStartedWrite : std_logic := '0';
 
signal SEnable : std_logic := '0';
signal SAddress : std_logic_vector(6 downto 0) := (others => '0');
signal SRegister : std_logic_vector(7 downto 0) := (others => '0');
signal SWriteData : std_logic_vector(7 downto 0) := (others => '0');
signal SBusy : std_logic := '0';
signal SBusy2 : std_logic := '0';
signal SDone : std_logic := '0';
signal SReady : std_logic := '0';
 
signal SDataClockRef : std_logic := '0';
signal SDataClockRefPrev : std_logic := '0';
-- signal SSIODClock : std_logic := '0'; -- DEBUG ONLY!
-- signal SSIODClockPrev : std_logic; -- DEBUG ONLY!
signal SSIOCClock : std_logic := '1';
signal SSIOCClockPrev : std_logic;
signal SSIODWrite : std_logic := '0';
signal SSIODRead : std_logic := '0';
signal SSIOCWrite : std_logic := '0';
signal SSIOCRead : std_logic := '0';
signal SAddr : std_logic_vector(6 downto 0) := (others => '0');
signal SReg : std_logic_vector(7 downto 0) := (others => '0');
signal SData : std_logic_vector(7 downto 0) := (others => '0');
signal SAddrReg : std_logic_vector(6 downto 0) := (others => '0');
signal SRegReg : std_logic_vector(7 downto 0) := (others => '0');
signal SDataReg : std_logic_vector(7 downto 0) := (others => '0');
signal SCounter : integer range 0 to 8 := 0;
 
signal SCounterSCCB : integer range 0 to CClockCountMax := 0;
signal SCounter2 : integer range 0 to 3 := 0;
 
begin
 
------------------------------------------------------------------------
-- In this part; the I/O ports are directed to according signals
------------------------------------------------------------------------
SStart <= PIStart;
SEnable <= PIEnable;
SAddress <= PIAddress;
SRegister <= PIRegister;
SWriteData <= PIWriteData;
PODone <= SDone;
POReady <= SReady;
 
POSIOC <= SSIOCWrite when (SStateWriteBase = idle or SStateWriteBase = start_condition or SStateWriteBase = stop ) else
SSIOCClock;
 
PIOSIOD <= SSIODWrite when SEnable = '1' else 'Z';
 
SStartReg <= '1' when SStart = '1' and SEnable = '1' else
'0' when (SSIOCClock = '0' and SSIOCClockPrev = '1') or PIReset = '0' or SEnable = '0' else
SStartReg;
 
-------------------------------------------------------------------------------------------------------------------------------
-- READY process; if write operation is over (SDone == '1') and write state machine is at start(SStateWriteBase == idle)
-- then it changes SReady to logic-1. And when the system at reset state(PIReset == '0') it changes SReady to logic-0.
-------------------------------------------------------------------------------------------------------------------------------
READY : process(PIClock, PIReset)
begin
if PIReset = '0' then
SReady <= '0';
elsif rising_edge(PIClock) then
if SStateWriteBase = idle then
SReady <= '1';
else
SReady <= '0';
end if;
end if;
end process;
 
-------------------------------------------------------------------------------------------------------------------------------
-- According to SStart signal state, this process; it assigns address, register and data inputs into their "register"
-- signals. When the system triggered by the reset input, all the register signals will be cleared.
-------------------------------------------------------------------------------------------------------------------------------
 
DATA_CAPTURE : process(PIClock, PIReset)
begin
if PIReset = '0' then
SAddrReg <= (others => '0');
SRegReg <= (others => '0');
SDataReg <= (others => '0');
elsif rising_edge(PIClock) then
if SStart = '1' then
SAddrReg <= SAddress;
SRegReg <= SRegister;
SDataReg <= SWriteData;
elsif SSIOCClock = '0' and SSIOCClockPrev = '1' then
SAddrReg <= SAddrReg;
SRegReg <= SRegReg;
SDataReg <= SDataReg;
else
SAddrReg <= SAddrReg;
SRegReg <= SRegReg;
SDataReg <= SDataReg;
end if;
end if;
end process;
 
-------------------------------------------------------------------------------------------------------------------------------
-- CLKGEN process; generates clock reference signals for SCCB interface. The important thing at this point is:
-- If we inspect the datasheet of the OV7670, we can see data changes at half of the period of SCCB's logic-0.
-- For that reason we need to create a data reference signal that changes at half of the period of SIOC reference signal.
--
-- |¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______ =====>>> SIOC Reference Clock
-- | | | | |
-- | | | | |
-- |¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_ =====>>> DATA Reference Clock
--
-------------------------------------------------------------------------------------------------------------------------------
CLKGEN : process(PIClock)
variable VCounter : integer range 0 to CClockCountMax := 0;
begin
if rising_edge(PIClock) then
--SSIODClockPrev <= SSIODClock;
SSIOCClockPrev <= SSIOCClock;
SDataClockRefPrev <= SDataClockRef;
if SCounterSCCB = (CClockCountMax / 4) - 1 then
SDataClockRef <= not SDataClockRef;
if SCounter2 = 1 then
--SSIODClock <= not SSIODClock;
SSIOCClock <= not SSIOCClock;
SCounter2 <= 0;
else
SCounter2 <= SCounter2 + 1;
end if;
SCounterSCCB <= 0;
else
SCounterSCCB <= SCounterSCCB +1;
end if;
 
end if;
end process;
 
-------------------------------------------------------------------------------------------------------------------------------------------
-- DATA_WRITE process; It contains the state machine that will write in accordance with the SCCB interface. When PIReset input trig-
-- gered, all of the states, signals and registers will be cleared.
--
-- !!!!IMPORTANT!!!!
--
-- When the SCCB interface at the idle state, it will hold the SIOD output at high impedance and SIOC output at logic-1 state. Start
-- condition changes the SIOD line to logic-1 and after half of the SIOC referance period, changes the SIOC line to logic-0 to start
-- communication. The finish state is; when there is no data to be written, firstly changes the SIOC line to logic-1 state and after
-- half of the SIOC referance period, the SIOD line will be changed to high impedance state. But if there is another data needs to
-- be written, then SIOD line will be changed to logic-1 state.
--
--
-- SIOD -------¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
-- |_______________________________| |_______________| |______
-- | | | | | | |
-- | | | | | | |
-- | | | | | | |
-- SIOC ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯| | |¯¯¯¯¯¯¯| | |¯¯¯¯¯¯¯| | |¯¯¯¯¯¯¯| | |¯¯¯¯¯¯¯| |
-- |_______________| |_______| |_______| |_______| |_______| |___|______
-- | | | | | | |
-- | | | | | | |
-- SIOC Ref |¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______
-- | | | | | | |
-- | | | | | | |
-- SIOD Ref |¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_
--
-------------------------------------------------------------------------------------------------------------------------------------------
 
DATA_WRITE : process(PIClock, PIReset)
variable VCounter : integer range 0 to 16 := 0;
begin
if PIReset = '0' then
SStateWriteBase <= idle;
SStartedWrite <= '0';
SAddr <= (others => '0');
SReg <= (others => '0');
SData <= (others => '0');
SSIODWrite <= 'Z';
SSIOCWrite <= '1';
SBusy <= '0';
SDone <= '0';
SBusy2 <= '0';
VCounter := 0;
SCounter <= 7;
elsif rising_edge(PIClock) then
case SStateWriteBase is
-------------------------------------------------------------------------------------------------------------------------------------------
-- "idle" state; when SStartReg is triggered; takes address, register and write data to cache and changes the it's state to
-- "start_condition" at rising edge of SIOC reference clock.
-- If SStartReg signal is not triggered(SIOD = 'Z' - SIOC = '1'), then system will remain in the "idle" state.
-------------------------------------------------------------------------------------------------------------------------------------------
when idle =>
if SSIOCClock = '0' and SSIOCClockPrev = '1' then
if SStartReg = '1' then
SSIODWrite <= '1';
SSIOCWrite <= '1';
SStartedWrite <= '1';
SDone <= '0';
SAddr <= SAddrReg;
SReg <= SRegReg;
SData <= SDataReg;
else
SAddr <= (others => '0');
SReg <= (others => '0');
SData <= (others => '0');
SStateWriteBase <= idle;
SSIODWrite <= 'Z';
SSIOCWrite <= '1';
SStartedWrite <= '0';
SDone <= '1';
end if;
elsif SSIOCClock = '1' and SSIOCClockPrev = '0' and SStartedWrite = '1' then
SSIODWrite <= '0';
SStartedWrite <= '0';
SStateWriteBase <= start_condition;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- start_condition" state; after 2 SIOC reference clock pulse, it writes the cached address data's first bit to SIOD line while shifting
-- cached address data to left when rising edge of SIOD reference and SIOC reference is logic-0. After that the state will change to
-- "send_addr" state.
-------------------------------------------------------------------------------------------------------------------------------------------
when start_condition =>
if SSIOCClock = '0' and SSIOCClockPrev = '1' then
SBusy <= '1';
if SBusy = '1' then
SBusy2 <= '1';
end if;
SSIOCWrite <= '0';
elsif SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' and SBusy2 = '1' then
if SAddr(6) = '1' then
SSIODWrite <= '1';
SAddr <= std_logic_vector(shift_left(unsigned(SAddr), 1));
elsif SAddr(6) = '0' then
SSIODWrite <= '0';
SAddr <= std_logic_vector(shift_left(unsigned(SAddr), 1));
end if;
SBusy <= '0';
SBusy2 <= '0';
SStateWriteBase <= send_addr;
 
else
SStateWriteBase <= start_condition;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "send_addr" state; writes the remaining address data to SIOD line and writes the "Don't Care" bit (logic-0) to SIOD line when rising
-- edge of SIOD reference clock and at SIOC reference clock is 0.
-------------------------------------------------------------------------------------------------------------------------------------------
when send_addr =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
if VCounter <= 5 then
VCounter := VCounter + 1;
if(SAddr(6) = '1') then
SSIODWrite <= '1';
SAddr <= std_logic_vector(shift_left(unsigned(SAddr), 1));
elsif (SAddr(6) = '0') then
SSIODWrite <= '0';
SAddr <= std_logic_vector(shift_left(unsigned(SAddr), 1));
end if;
else
VCounter := 0;
SSIODWrite <= '0'; ---->>>> Don't Care Bit!
SStateWriteBase <= addr_dc;
SBusy <= '0';
end if;
else
SStateWriteBase <= send_addr;
end if;
 
when addr_dc =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
SAddr <= (others => '0');
elsif SDataClockRef = '0' and SDataClockRefPrev = '1' and SSIOCClock = '0' then
SStateWriteBase <= send_reg;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "send_reg" state; It writes the register data to the SIOD line as soon as the rising edge of the SIOD reference and the SIOC
-- reference are logic-0. After finishing writing register data, it will write a "Don't Care" bit.
-------------------------------------------------------------------------------------------------------------------------------------------
when send_reg =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
SBusy <= '1';
if SBusy = '1' then
if VCounter <= 7 then
VCounter := VCounter + 1;
if(SReg(7) = '1') then
SSIODWrite <= '1';
SReg <= std_logic_vector(shift_left(unsigned(SReg), 1));
elsif (SReg(7) = '0') then
SSIODWrite <= '0';
SReg <= std_logic_vector(shift_left(unsigned(SReg), 1));
end if;
else
SBusy <= '0';
VCounter := 0;
SSIODWrite <= '0'; ---->>>> Don't Care Bit!
SStateWriteBase <= reg_dc;
end if;
end if;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "reg_dc" state; after "Don't Care" bit is written, like the other states, according SIOD and SIOC reference states it will write
-- the cached data's first bit while shifting to the left to SIOD line and changes it's state to "send_data".
-------------------------------------------------------------------------------------------------------------------------------------------
when reg_dc =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
SReg <= (others => '0');
SStateWriteBase <= send_data;
if(SData(7) = '1') then
SSIODWrite <= '1';
SData <= std_logic_vector(shift_left(unsigned(SData), 1));
SBusy <= '0';
elsif (SData(7) = '0') then
SSIODWrite <= '0';
SData <= std_logic_vector(shift_left(unsigned(SData), 1));
SBusy <= '0';
end if;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "send_data" state; when the first bit of the data is written, the remaining bits will be written to the SIOD line while shifting
-- to the left. When data write is done, it will write "Don't Care" bit to SIOD line and after 1 SIOD and SIOC reference clock it
-- will change it's state to "data_dc".
-------------------------------------------------------------------------------------------------------------------------------------------
when send_data =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
if VCounter <= 6 then
VCounter := VCounter + 1;
if(SData(7) = '1') then
SSIODWrite <= '1';
SData <= std_logic_vector(shift_left(unsigned(SData), 1));
elsif (SData(7) = '0') then
SSIODWrite <= '0';
SData <= std_logic_vector(shift_left(unsigned(SData), 1));
end if;
else
SSIODWrite <= '0'; ----
SBusy <= '1';
if SBusy = '1' then
VCounter := 0;
SStateWriteBase <= data_dc;
SBusy <= '0';
end if;
end if;
end if;
----------------------------------------------------------------------------------------------
-- "data_dc" state; waits only one SIOC reference clock and change it's state to "stop".
----------------------------------------------------------------------------------------------
when data_dc =>
if SSIOCClock = '1' and SSIOCClockPrev = '0' then
SData <= (others => '0');
SStateWriteBase <= stop;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "stop" state; for stopping the SCCB communication, firstly changes SIOC line to logic-1 state and after 1 SIOC reference clock, it
-- changes the SIOD line to logic-1 state and goes to "idle" state.
-------------------------------------------------------------------------------------------------------------------------------------------
when stop =>
SSIOCWrite <= '1';
if SSIOCClock = '1' and SSIOCClockPrev = '0' then
SSIODWrite <= '1';
SBusy <= '1';
SAddr <= (others => '0');
SReg <= (others => '0');
SData <= (others => '0');
if SBusy = '1' then
--SReady <= '1';
SStateWriteBase <= idle;
SDone <= '1';
SBusy <= '0';
end if;
elsif SSIOCClock = '0' and SSIOCClockPrev = '1' then
SSIODWrite <= '1';
end if;
 
when others =>
end case;
end if;
end process;
 
end Behavioral;
/ov7670-sccb/trunk/hdl/english/hdl/SCCBRegisterTable.vhd
0,0 → 1,326
-----------------------------------------------------------------------------------
-- OV7670 CMOS kamera modulunun RGB565 modunda calismasini saglayan register
-- ve bu registerlerin olmasi gereken verileri icerir.
-----------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.NUMERIC_STD.all;
 
entity SCCBRegisterTable is
port (
PIClock : in std_logic;
PIReset : in std_logic;
PITrig : in std_logic;
PIDone : in std_logic;
PIReady : in std_logic;
POCfgFinished : out std_logic;
POStart : out std_logic;
POEnable : out std_logic;
POAddress : out std_logic_vector(6 downto 0);
PORegister : out std_logic_vector(7 downto 0);
POWriteData : out std_logic_vector(7 downto 0)
);
 
end SCCBRegisterTable;
 
architecture Behavioral of SCCBRegisterTable is
constant CDeviceBaseAddress : std_logic_vector(7 downto 0) := x"21";
constant CDeviceWriteAddress : std_logic_vector(7 downto 0) := x"42";
constant CDeviceReadAddress : std_logic_vector(7 downto 0) := x"43";
 
 
signal STrig : std_logic := '0';
signal SDone : std_logic := '0';
signal SReady : std_logic := '0';
signal SCfgFinished : std_logic := '0';
signal SStart : std_logic := '0';
signal SEnable : std_logic := '0';
signal SAddress : std_logic_vector(6 downto 0) := (others => '0');
signal SRegister : std_logic_vector(7 downto 0) := (others => '0');
signal SWriteData : std_logic_vector(7 downto 0) := (others => '0');
 
signal STrigPrev : std_logic := '0';
signal STrigRising : std_logic := '0';
signal STrigFalling : std_logic := '0';
 
signal SReadyPrev : std_logic := '0';
signal SReadyRising : std_logic := '0';
 
signal SCounter : integer range 0 to 58 := 0;
 
signal SWaitCtr : integer range 0 to 255 := 0;
 
begin
STrig <= PITrig;
SDone <= PIDone;
SReady <= PIReady;
 
POCfgFinished <= SCfgFinished;
POStart <= SStart;
POEnable <= SEnable;
POAddress <= SAddress;
PORegister <= SRegister;
POWriteData <= SWriteData;
 
READY_EDGE : process(PIClock, PIReset)
begin
if PIReset = '0' then
SReadyPrev <= '0';
SReadyRising <= '0';
elsif rising_edge(PIClock) then
SReadyPrev <= SReady;
if SReady = '1' and SReadyPrev = '0' then
SReadyRising <= '1';
else
SReadyRising <= '0';
end if;
end if;
end process;
 
TRIG_EDGES : process(PIClock, PIReset)
begin
if PIReset = '0' then
STrigPrev <= '0';
STrigRising <= '0';
STrigFalling <= '0';
elsif rising_edge(PIClock) then
STrigPrev <= STrig;
if STrig = '1' and STrigPrev = '0' then
STrigRising <= '1';
else
STrigRising <= '0';
end if;
if STrig = '0' and STrigPrev = '1' then
STrigFalling <= '1';
else
STrigFalling <= '0';
end if;
end if;
end process;
 
BACKEND : process(PIClock, PIReset)
begin
if PIReset = '0' then
SCfgFinished <= '0';
SStart <= '0';
SEnable <= '0';
SAddress <= (others => '0');
SRegister <= (others => '0');
SWriteData <= (others => '0');
SCounter <= 0;
elsif rising_edge(PIClock) then
if SWaitCtr <= 254 then
SWaitCtr <= SWaitCtr + 1;
else
if (SReady = '1' and STrigFalling = '1' and SStart = '0') or (SStart = '1' and SReadyRising = '1') then
SEnable <= '1';
SStart <= '1';
SAddress <= CDeviceBaseAddress(6 downto 0);
if SCounter <= 56 then
SCounter <= SCounter + 1;
case SCounter is
when 0 =>
SRegister <= x"12";
SWriteData <= x"80";
when 1 =>
SRegister <= x"12";
SWriteData <= x"80";
when 2 =>
SRegister <= x"12";
SWriteData <= x"04";
when 3 =>
SRegister <= x"11";
SWriteData <= x"00";
when 4 =>
SRegister <= x"0C";
SWriteData <= x"00";
when 5 =>
SRegister <= x"3E";
SWriteData <= x"00";
when 6 =>
SRegister <= x"8C";
SWriteData <= x"00";
when 7 =>
SRegister <= x"04";
SWriteData <= x"00";
when 8 =>
SRegister <= x"40";
SWriteData <= x"10";
when 9 =>
SRegister <= x"3A";
SWriteData <= x"04";
when 10 =>
SRegister <= x"14";
SWriteData <= x"38";
when 11 =>
SRegister <= x"4F";
SWriteData <= x"40";
when 12 =>
SRegister <= x"50";
SWriteData <= x"34";
when 13 =>
SRegister <= x"51";
SWriteData <= x"0C";
when 14 =>
SRegister <= x"52";
SWriteData <= x"17";
when 15 =>
SRegister <= x"53";
SWriteData <= x"29";
when 16 =>
SRegister <= x"54";
SWriteData <= x"40";
when 17 =>
SRegister <= x"58";
SWriteData <= x"1E";
when 18 =>
SRegister <= x"3D";
SWriteData <= x"C0";
when 19 =>
SRegister <= x"11";
SWriteData <= x"00";
when 20 =>
SRegister <= x"17";
SWriteData <= x"11";
when 21 =>
SRegister <= x"18";
SWriteData <= x"61";
when 22 =>
SRegister <= x"32";
SWriteData <= x"A4";
when 23 =>
SRegister <= x"19";
SWriteData <= x"03";
when 24 =>
SRegister <= x"1A";
SWriteData <= x"7B";
when 25 =>
SRegister <= x"03";
SWriteData <= x"0A";
when 26 =>
SRegister <= x"0E";
SWriteData <= x"61";
when 27 =>
SRegister <= x"0F";
SWriteData <= x"4B";
when 28 =>
SRegister <= x"16";
SWriteData <= x"02";
when 29 =>
SRegister <= x"1E";
SWriteData <= x"37";
when 30 =>
SRegister <= x"21";
SWriteData <= x"02";
when 31 =>
SRegister <= x"22";
SWriteData <= x"91";
when 32 =>
SRegister <= x"29";
SWriteData <= x"07";
when 33 =>
SRegister <= x"33";
SWriteData <= x"0B";
when 34 =>
SRegister <= x"35";
SWriteData <= x"0B";
when 35 =>
SRegister <= x"37";
SWriteData <= x"1D";
when 36 =>
SRegister <= x"38";
SWriteData <= x"71";
when 37 =>
SRegister <= x"39";
SWriteData <= x"2A";
when 38 =>
SRegister <= x"3C";
SWriteData <= x"78";
when 39 =>
SRegister <= x"4D";
SWriteData <= x"40";
when 40 =>
SRegister <= x"4E";
SWriteData <= x"20";
when 41 =>
SRegister <= x"69";
SWriteData <= x"00";
when 42 =>
SRegister <= x"6B";
SWriteData <= x"4A";
when 43 =>
SRegister <= x"74";
SWriteData <= x"10";
when 44 =>
SRegister <= x"8D";
SWriteData <= x"4F";
when 45 =>
SRegister <= x"8E";
SWriteData <= x"00";
when 46 =>
SRegister <= x"8F";
SWriteData <= x"00";
when 47 =>
SRegister <= x"90";
SWriteData <= x"00";
when 48 =>
SRegister <= x"91";
SWriteData <= x"00";
when 49 =>
SRegister <= x"96";
SWriteData <= x"00";
when 50 =>
SRegister <= x"9A";
SWriteData <= x"00";
when 51 =>
SRegister <= x"B0";
SWriteData <= x"84";
when 52 =>
SRegister <= x"B1";
SWriteData <= x"0C";
when 53 =>
SRegister <= x"B2";
SWriteData <= x"0E";
when 54 =>
SRegister <= x"B3";
SWriteData <= x"82";
when 55 =>
SRegister <= x"B8";
SWriteData <= x"0A";
when others =>
SRegister <= x"FF";
SWriteData <= x"FF";
SStart <= '0';
SEnable <= '0';
SCfgFinished <= '1';
SCounter <= 0;
end case;
else
SAddress <= SAddress;
SEnable <= SEnable;
SStart <= '0';
SCounter <= 0;
SRegister <= SRegister;
SWriteData <= SWriteData;
end if;
else
SAddress <= SAddress;
SEnable <= SEnable;
SStart <= SStart;
SRegister <= SRegister;
SWriteData <= SWriteData;
end if;
end if;
end if;
end process;
 
end Behavioral;
/ov7670-sccb/trunk/hdl/turkish/hdl/SCCBMaster.vhd
0,0 → 1,447
---------------------------------------------------------------------------------------------------------------------------------------------
-- OV7670 kamera modulu ayarlarinin yapilmasi icin SCCB protokolunu kullanir. Bu protokol I2C uyumludur.
-- SCCB protokolu I2C'den farkli olarak lojik-1 durumuna da sahiptir.
-- High - Low - High Impedance
--
-- Bu protokolun en onemli noktasi; ACK ve NACK bitleri yazma islemi icin gereksizdir. Bu bitler yerine
-- "Don't Care" isimli lojik-0 biti kullanılır. Asagida ornek bir yazma isleminin veri paketi gorulmektedir:
--
-- |A6|A5|A4|A3|A2|A1|A0|R/W|DC|-|R7|R6|R5|R4|R3|R2|R1|R0|DC|-|D7|D6|D5|D4|D3|D2|D1|D0|DC|
-- 7-bit Address 8-Bit Register/Data 8-bit Data
-- R => lojik-1
-- W => lojik-0
--
-- SCCB hattindan sadece veri gonderileceginden sadece WRITE islemi eklenmistir. OV7670 kamera modulu paralel
-- 8-bit kamera veri hatti bulunduruyor. Bu noktada READ adimi eklenmedi!
--
-- Kullanilan kaynaklar : OV7670 Datasheet
-- : OmniVision SCCB Specification
-- : http://www.dejazzer.com/hardware.html (Face detection on FPGA: OV7670 CMOS camera + DE2-115 FPGA board)
-- : http://www.dejazzer.com/eigenpi/digital_camera/digital_camera.html
--
-- TODO => Aciklamalari Ingilizce yap!
--
---------------------------------------------------------------------------------------------------------------------------------------------
 
 
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.NUMERIC_STD.all;
 
entity SCCBMaster is
generic(
GInputClock : integer := 50_000_000; -- FPGA' nin ana clock hizi
GBusClock : integer := 400_000 -- SCCB hattinin calistirilmasi icin belirlenecek hiz (400 kHz SCCB fast mode)
);
port(
PIClock : in std_logic; -- Sistem clock girisi
PIReset : in std_logic; -- Reset(active low) girisi
PIEnable : in std_logic; -- SCCB hattini aktif edecek enable girisi
PIAddress : in std_logic_vector(6 downto 0); -- SCCB hattina bagli olan slave cihazlarinin ana adreslerini isaret eden giris
PIRegister : in std_logic_vector(7 downto 0); -- Slave birimin islem yapilacak register adresini belirten giris
PIWriteData : in std_logic_vector(7 downto 0); -- Master -> Slave yonunde yazilacak data
PIStart : in std_logic; -- SCCB master backend calistirma girisi
PODone : out std_logic; -- SCCB arayuzunun yazma islemini bitirdigini belirten cikis
POReady : out std_logic; -- SCCB arayuzunun islem yapmaya hazir oldugunu belirten cikis
PIOSIOD : inout std_logic; -- SCCB seri data cikisi - girisi
POSIOC : out std_logic -- SCCB seri clock cikisi
);
end SCCBMaster;
 
architecture Behavioral of SCCBMaster is
 
------------------------------------------------------------------------------------------------------------------
-- Bu adimda sistemin calisacagi durum makinesinin durumlari, giris ve cikis portlarina baglanacak sinyaller,
-- durumlar icin gerekli olacak counter ve busy bitleri gibi sinyaller olusturulmustur.
------------------------------------------------------------------------------------------------------------------
 
type TStatesWrite is (idle, start_condition, send_addr, addr_dc, send_reg, reg_dc, send_data, data_dc, stop);
signal SStateWriteBase : TStatesWrite := idle;
constant CClockCountMax : integer := (GInputClock / GBusClock);
signal SStart : std_logic := '0';
signal SStartReg : std_logic := '0';
signal SStartedWrite : std_logic := '0';
 
signal SEnable : std_logic := '0';
signal SAddress : std_logic_vector(6 downto 0) := (others => '0');
signal SRegister : std_logic_vector(7 downto 0) := (others => '0');
signal SWriteData : std_logic_vector(7 downto 0) := (others => '0');
signal SBusy : std_logic := '0';
signal SBusy2 : std_logic := '0';
signal SDone : std_logic := '0';
signal SReady : std_logic := '0';
 
signal SDataClockRef : std_logic := '0';
signal SDataClockRefPrev : std_logic := '0';
-- signal SSIODClock : std_logic := '0'; -- DEBUG AMACLIDIR!
-- signal SSIODClockPrev : std_logic; -- DEBUG AMACLIDIR!
signal SSIOCClock : std_logic := '1';
signal SSIOCClockPrev : std_logic;
signal SSIODWrite : std_logic := '0';
signal SSIODRead : std_logic := '0';
signal SSIOCWrite : std_logic := '0';
signal SSIOCRead : std_logic := '0';
signal SAddr : std_logic_vector(6 downto 0) := (others => '0');
signal SReg : std_logic_vector(7 downto 0) := (others => '0');
signal SData : std_logic_vector(7 downto 0) := (others => '0');
signal SAddrReg : std_logic_vector(6 downto 0) := (others => '0');
signal SRegReg : std_logic_vector(7 downto 0) := (others => '0');
signal SDataReg : std_logic_vector(7 downto 0) := (others => '0');
signal SCounter : integer range 0 to 8 := 0;
 
signal SCounterSCCB : integer range 0 to CClockCountMax := 0;
signal SCounter2 : integer range 0 to 3 := 0;
 
begin
 
------------------------------------------------------------------------
-- Bu adimda giris ve cikis portlari sinyallere yonlendirilmistir.
------------------------------------------------------------------------
SStart <= PIStart;
SEnable <= PIEnable;
SAddress <= PIAddress;
SRegister <= PIRegister;
SWriteData <= PIWriteData;
PODone <= SDone;
POReady <= SReady;
 
POSIOC <= SSIOCWrite when (SStateWriteBase = idle or SStateWriteBase = start_condition or SStateWriteBase = stop ) else
SSIOCClock;
PIOSIOD <= SSIODWrite when SEnable = '1' else 'Z';
 
SStartReg <= '1' when SStart = '1' and SEnable = '1' else
'0' when (SSIOCClock = '0' and SSIOCClockPrev = '1') or PIReset = '0' or SEnable = '0' else
SStartReg;
 
-------------------------------------------------------------------------------------------------------------------------------
-- READY prosesi; eger yazma islemi bittiyse(SDone == '1') ve yazma durum makinesi baslangictaysa(SStateWriteBase == idle)
-- SReady sinyalini lojik-1 yapar. Ayrica sistem durdurulduysa(PIReset == '0') SReady sinyalini lojik-0 yapar.
-------------------------------------------------------------------------------------------------------------------------------
READY : process(PIClock, PIReset)
begin
if PIReset = '0' then
SReady <= '0';
elsif rising_edge(PIClock) then
if SStateWriteBase = idle then
SReady <= '1';
else
SReady <= '0';
end if;
end if;
end process;
 
-------------------------------------------------------------------------------------------------------------------------------
-- Backend tarafina gelen baslatma sinyaline gore(SStart == '1') address, register ve data bilgilerini olusturulan register
-- sinyallerine atar. Sistemin resetlenme durumuna gore bu sinyaller temizlenir.
-------------------------------------------------------------------------------------------------------------------------------
 
DATA_CAPTURE : process(PIClock, PIReset)
begin
if PIReset = '0' then
SAddrReg <= (others => '0');
SRegReg <= (others => '0');
SDataReg <= (others => '0');
elsif rising_edge(PIClock) then
if SStart = '1' then
SAddrReg <= SAddress;
SRegReg <= SRegister;
SDataReg <= SWriteData;
elsif SSIOCClock = '0' and SSIOCClockPrev = '1' then
SAddrReg <= SAddrReg;
SRegReg <= SRegReg;
SDataReg <= SDataReg;
else
SAddrReg <= SAddrReg;
SRegReg <= SRegReg;
SDataReg <= SDataReg;
end if;
end if;
end process;
 
-------------------------------------------------------------------------------------------------------------------------------
-- CLKGEN prosesi; SCCB arayuzu icin gerekli olan REFERANS saat sinyallerini uretir. Bu noktada onemli olan durum sudur:
-- OV7670 datasheeti incelendiginde gonderilecek veriler SIOC cikisinin lojik-0 olduğu durumun tam ortasında degistirilir.
-- Bu nedenden dolayi SIOC cikisi icin ek olarak bu cikisin yari periyoduna sahip ikincil bir saat sinyali uretilir.
--
-- |¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______ =====>>> SIOC Referans Saat
-- | | | | |
-- | | | | |
-- |¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_ =====>>> DATA Referans Saat
--
-------------------------------------------------------------------------------------------------------------------------------
CLKGEN : process(PIClock)
variable VCounter : integer range 0 to CClockCountMax := 0;
begin
if rising_edge(PIClock) then
--SSIODClockPrev <= SSIODClock;
SSIOCClockPrev <= SSIOCClock;
SDataClockRefPrev <= SDataClockRef;
if SCounterSCCB = (CClockCountMax / 4) - 1 then
SDataClockRef <= not SDataClockRef;
if SCounter2 = 1 then
--SSIODClock <= not SSIODClock;
SSIOCClock <= not SSIOCClock;
SCounter2 <= 0;
else
SCounter2 <= SCounter2 + 1;
end if;
SCounterSCCB <= 0;
else
SCounterSCCB <= SCounterSCCB +1;
end if;
 
end if;
end process;
 
-------------------------------------------------------------------------------------------------------------------------------------------
-- DATA_WRITE prosesi; SCCB arayuzune uygun olarak yazma islemi yapacak olan durum makinesini icerir. Aktif 0 olarak ca-
-- lisan PIReset, aktif oldugu durumda butun islemleri, sayicilari, cikislari ve registerleri temizler.
--
-- !!!!ONEMLI!!!!
-- SCCB arayuzu, idle durumundayken SIOD hattini yuksek empedans('Z'), SIOC hattini ise lojik-1 seviyesinde tutar. Baslangic kosulu,
-- SIOD hattini 'Z' durumundan lojik-1 durumuna getirir, ardindan SIOC hattini referans saatin yarı periyodu kadar bekledikten sonra
-- lojik-0 yaparak haberlesmeyi baslatir. Bitme kosulu ise, eger baska veri yazilmayacaksa ilk olarak SIOC'yi lojik-1, ardindan SIOD
-- hattini yarim periyot bekledikten sonra 'Z' yapar. Ancak baska veri yazilmaya devam edecek ise SIOD hattini 'Z' yerine lojik-1 yapar.
--
--
-- SIOD -------¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
-- |_______________________________| |_______________| |______
-- | | | | | | |
-- | | | | | | |
-- | | | | | | |
-- SIOC ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| |¯¯¯¯¯¯¯| | |¯¯¯¯¯¯¯| | |¯¯¯¯¯¯¯| | |¯¯¯¯¯¯¯| | |¯¯¯¯¯¯¯| |
-- |_______________| |_______| |_______| |_______| |_______| |___|______
-- | | | | | | |
-- | | | | | | |
-- SIOC Ref |¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______
-- | | | | | | |
-- | | | | | | |
-- SIOD Ref |¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_
--
-------------------------------------------------------------------------------------------------------------------------------------------
 
DATA_WRITE : process(PIClock, PIReset)
variable VCounter : integer range 0 to 16 := 0;
begin
if PIReset = '0' then
SStateWriteBase <= idle;
SStartedWrite <= '0';
SAddr <= (others => '0');
SReg <= (others => '0');
SData <= (others => '0');
SSIODWrite <= 'Z';
SSIOCWrite <= '1';
SBusy <= '0';
SDone <= '0';
SBusy2 <= '0';
VCounter := 0;
SCounter <= 7;
elsif rising_edge(PIClock) then
case SStateWriteBase is
-------------------------------------------------------------------------------------------------------------------------------------------
-- "idle" durumu; SStartReg tetiklendiginde address, register ve data bilgilerini registerlerden toplar ve SIOC referans
-- saatinin yukselen kenarinda "start_condition" durumuna gecer.
-- SStartReg'in tetiklenmedigi durumda sistem reset (SIOD = 'Z' - SIOC = '1') durumunda kalir.
-------------------------------------------------------------------------------------------------------------------------------------------
when idle =>
if SSIOCClock = '0' and SSIOCClockPrev = '1' then
if SStartReg = '1' then
SSIODWrite <= '1';
SSIOCWrite <= '1';
SStartedWrite <= '1';
SDone <= '0';
SAddr <= SAddrReg;
SReg <= SRegReg;
SData <= SDataReg;
else
SAddr <= (others => '0');
SReg <= (others => '0');
SData <= (others => '0');
SStateWriteBase <= idle;
SSIODWrite <= 'Z';
SSIOCWrite <= '1';
SStartedWrite <= '0';
SDone <= '1';
end if;
elsif SSIOCClock = '1' and SSIOCClockPrev = '0' and SStartedWrite = '1' then
SSIODWrite <= '0';
SStartedWrite <= '0';
SStateWriteBase <= start_condition;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "start_condition" durumu; 2 SIOC referans clock darbesinden sonra SIOD referansinin yukselen kenari ve SIOC referansinin
-- lojik-0 oldugu anda cache olarak alinan address verisinin ilk bitini sola 1 kere kaydirarak SIOD hattina yazar ve "send_addr"
-- durumuna gecer.
-------------------------------------------------------------------------------------------------------------------------------------------
when start_condition =>
if SSIOCClock = '0' and SSIOCClockPrev = '1' then
SBusy <= '1';
if SBusy = '1' then
SBusy2 <= '1';
end if;
SSIOCWrite <= '0';
elsif SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' and SBusy2 = '1' then
if SAddr(6) = '1' then
SSIODWrite <= '1';
SAddr <= std_logic_vector(shift_left(unsigned(SAddr), 1));
elsif SAddr(6) = '0' then
SSIODWrite <= '0';
SAddr <= std_logic_vector(shift_left(unsigned(SAddr), 1));
end if;
SBusy <= '0';
SBusy2 <= '0';
SStateWriteBase <= send_addr;
 
else
SStateWriteBase <= start_condition;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "send_addr" durumu; SIOD referansinin yukselen kenari ve SIOC referansinin lojik-0 oldugu anda address verisinin geri kalanini
-- SIOD hattina yazar. Ardindan "Don't Care" bit durumuna gecer ve gecerken SIOD hattini lojik-0 tutar.
-------------------------------------------------------------------------------------------------------------------------------------------
when send_addr =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
if VCounter <= 5 then
VCounter := VCounter + 1;
if(SAddr(6) = '1') then
SSIODWrite <= '1';
SAddr <= std_logic_vector(shift_left(unsigned(SAddr), 1));
elsif (SAddr(6) = '0') then
SSIODWrite <= '0';
SAddr <= std_logic_vector(shift_left(unsigned(SAddr), 1));
end if;
else
VCounter := 0;
SSIODWrite <= '0'; ---->>>> Don't Care Bit!
SStateWriteBase <= addr_dc;
SBusy <= '0';
end if;
else
SStateWriteBase <= send_addr;
end if;
 
when addr_dc =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
SAddr <= (others => '0');
elsif SDataClockRef = '0' and SDataClockRefPrev = '1' and SSIOCClock = '0' then
SStateWriteBase <= send_reg;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "send_reg" durumu; SIOD referansinin yukselen kenari ve SIOC referansinin lojik-0 oldugu anda register verisini SIOD hattina yazar.
-- Ardindan "Don't Care" bit durumuna gecer ve gecerken SIOD hattini lojik-0 tutar.
-------------------------------------------------------------------------------------------------------------------------------------------
when send_reg =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
SBusy <= '1';
if SBusy = '1' then
if VCounter <= 7 then
VCounter := VCounter + 1;
if(SReg(7) = '1') then
SSIODWrite <= '1';
SReg <= std_logic_vector(shift_left(unsigned(SReg), 1));
elsif (SReg(7) = '0') then
SSIODWrite <= '0';
SReg <= std_logic_vector(shift_left(unsigned(SReg), 1));
end if;
else
SBusy <= '0';
VCounter := 0;
SSIODWrite <= '0'; ---->>>> Don't Care Bit!
SStateWriteBase <= reg_dc;
end if;
end if;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "reg_dc" durumu; "Don't Care" biti yazildiktan sonra diger durumlarda oldugu gibi SIOD ve SIOC referans saat sinyallerine
-- gore islem yapar. Bu sefer data verisinin ilk bitini sola kaydirarak SIOD hattina yazar ve "send_data" durumuna gecer.
-------------------------------------------------------------------------------------------------------------------------------------------
when reg_dc =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
SReg <= (others => '0');
SStateWriteBase <= send_data;
if(SData(7) = '1') then
SSIODWrite <= '1';
SData <= std_logic_vector(shift_left(unsigned(SData), 1));
SBusy <= '0';
elsif (SData(7) = '0') then
SSIODWrite <= '0';
SData <= std_logic_vector(shift_left(unsigned(SData), 1));
SBusy <= '0';
end if;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "reg_dc" durumu; gonderilmek istenen verinin ilk biti yazdirildiktan sonra geri kalan bitler sola kaydirilarak SIOD hattina
-- yazilir. Ardindan "Don't Care" biti yazilir, 1 SIOD ve SIOC referans saati beklenir ve "data_dc" durumuna gecilir.
-------------------------------------------------------------------------------------------------------------------------------------------
when send_data =>
if SDataClockRef = '1' and SDataClockRefPrev = '0' and SSIOCClock = '0' then
if VCounter <= 6 then
VCounter := VCounter + 1;
if(SData(7) = '1') then
SSIODWrite <= '1';
SData <= std_logic_vector(shift_left(unsigned(SData), 1));
elsif (SData(7) = '0') then
SSIODWrite <= '0';
SData <= std_logic_vector(shift_left(unsigned(SData), 1));
end if;
else
SSIODWrite <= '0'; ----
SBusy <= '1';
if SBusy = '1' then
VCounter := 0;
SStateWriteBase <= data_dc;
SBusy <= '0';
end if;
end if;
end if;
------------------------------------------------------------------------------------------
-- "data_dc" durumu; sadece 1 clock SIOC referans bekleyerek "stop" durumuna gecer.
------------------------------------------------------------------------------------------
when data_dc =>
if SSIOCClock = '1' and SSIOCClockPrev = '0' then
SData <= (others => '0');
SStateWriteBase <= stop;
end if;
-------------------------------------------------------------------------------------------------------------------------------------------
-- "stop" durumu; ilk olarak SCCB haberlesmesini sonlandirmak icin ilk olarak SIOC hattini lojik-1 yapar, ardindan 1 SIOC saat
-- referansi bekledikten sonra SIOD hattini lojik-1 yapar ve "idle" durumuna gecis yapar.
-------------------------------------------------------------------------------------------------------------------------------------------
when stop =>
SSIOCWrite <= '1';
if SSIOCClock = '1' and SSIOCClockPrev = '0' then
SSIODWrite <= '1';
SBusy <= '1';
SAddr <= (others => '0');
SReg <= (others => '0');
SData <= (others => '0');
if SBusy = '1' then
--SReady <= '1';
SStateWriteBase <= idle;
SDone <= '1';
SBusy <= '0';
end if;
elsif SSIOCClock = '0' and SSIOCClockPrev = '1' then
SSIODWrite <= '1';
end if;
 
when others =>
end case;
end if;
end process;
 
end Behavioral;
/ov7670-sccb/trunk/hdl/turkish/hdl/SCCBRegisterTable.vhd
0,0 → 1,326
-----------------------------------------------------------------------------------
-- OV7670 CMOS kamera modulunun RGB565 modunda calismasini saglayan register
-- ve bu registerlerin olmasi gereken verileri icerir.
-----------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.NUMERIC_STD.all;
 
entity SCCBRegisterTable is
port (
PIClock : in std_logic;
PIReset : in std_logic;
PITrig : in std_logic;
PIDone : in std_logic;
PIReady : in std_logic;
POCfgFinished : out std_logic;
POStart : out std_logic;
POEnable : out std_logic;
POAddress : out std_logic_vector(6 downto 0);
PORegister : out std_logic_vector(7 downto 0);
POWriteData : out std_logic_vector(7 downto 0)
);
 
end SCCBRegisterTable;
 
architecture Behavioral of SCCBRegisterTable is
constant CDeviceBaseAddress : std_logic_vector(7 downto 0) := x"21";
constant CDeviceWriteAddress : std_logic_vector(7 downto 0) := x"42";
constant CDeviceReadAddress : std_logic_vector(7 downto 0) := x"43";
 
 
signal STrig : std_logic := '0';
signal SDone : std_logic := '0';
signal SReady : std_logic := '0';
signal SCfgFinished : std_logic := '0';
signal SStart : std_logic := '0';
signal SEnable : std_logic := '0';
signal SAddress : std_logic_vector(6 downto 0) := (others => '0');
signal SRegister : std_logic_vector(7 downto 0) := (others => '0');
signal SWriteData : std_logic_vector(7 downto 0) := (others => '0');
 
signal STrigPrev : std_logic := '0';
signal STrigRising : std_logic := '0';
signal STrigFalling : std_logic := '0';
 
signal SReadyPrev : std_logic := '0';
signal SReadyRising : std_logic := '0';
 
signal SCounter : integer range 0 to 58 := 0;
 
signal SWaitCtr : integer range 0 to 255 := 0;
 
begin
STrig <= PITrig;
SDone <= PIDone;
SReady <= PIReady;
 
POCfgFinished <= SCfgFinished;
POStart <= SStart;
POEnable <= SEnable;
POAddress <= SAddress;
PORegister <= SRegister;
POWriteData <= SWriteData;
 
READY_EDGE : process(PIClock, PIReset)
begin
if PIReset = '0' then
SReadyPrev <= '0';
SReadyRising <= '0';
elsif rising_edge(PIClock) then
SReadyPrev <= SReady;
if SReady = '1' and SReadyPrev = '0' then
SReadyRising <= '1';
else
SReadyRising <= '0';
end if;
end if;
end process;
 
TRIG_EDGES : process(PIClock, PIReset)
begin
if PIReset = '0' then
STrigPrev <= '0';
STrigRising <= '0';
STrigFalling <= '0';
elsif rising_edge(PIClock) then
STrigPrev <= STrig;
if STrig = '1' and STrigPrev = '0' then
STrigRising <= '1';
else
STrigRising <= '0';
end if;
if STrig = '0' and STrigPrev = '1' then
STrigFalling <= '1';
else
STrigFalling <= '0';
end if;
end if;
end process;
 
BACKEND : process(PIClock, PIReset)
begin
if PIReset = '0' then
SCfgFinished <= '0';
SStart <= '0';
SEnable <= '0';
SAddress <= (others => '0');
SRegister <= (others => '0');
SWriteData <= (others => '0');
SCounter <= 0;
elsif rising_edge(PIClock) then
if SWaitCtr <= 254 then
SWaitCtr <= SWaitCtr + 1;
else
if (SReady = '1' and STrigFalling = '1' and SStart = '0') or (SStart = '1' and SReadyRising = '1') then
SEnable <= '1';
SStart <= '1';
SAddress <= CDeviceBaseAddress(6 downto 0);
if SCounter <= 56 then
SCounter <= SCounter + 1;
case SCounter is
when 0 =>
SRegister <= x"12";
SWriteData <= x"80";
when 1 =>
SRegister <= x"12";
SWriteData <= x"80";
when 2 =>
SRegister <= x"12";
SWriteData <= x"04";
when 3 =>
SRegister <= x"11";
SWriteData <= x"00";
when 4 =>
SRegister <= x"0C";
SWriteData <= x"00";
when 5 =>
SRegister <= x"3E";
SWriteData <= x"00";
when 6 =>
SRegister <= x"8C";
SWriteData <= x"00";
when 7 =>
SRegister <= x"04";
SWriteData <= x"00";
when 8 =>
SRegister <= x"40";
SWriteData <= x"10";
when 9 =>
SRegister <= x"3A";
SWriteData <= x"04";
when 10 =>
SRegister <= x"14";
SWriteData <= x"38";
when 11 =>
SRegister <= x"4F";
SWriteData <= x"40";
when 12 =>
SRegister <= x"50";
SWriteData <= x"34";
when 13 =>
SRegister <= x"51";
SWriteData <= x"0C";
when 14 =>
SRegister <= x"52";
SWriteData <= x"17";
when 15 =>
SRegister <= x"53";
SWriteData <= x"29";
when 16 =>
SRegister <= x"54";
SWriteData <= x"40";
when 17 =>
SRegister <= x"58";
SWriteData <= x"1E";
when 18 =>
SRegister <= x"3D";
SWriteData <= x"C0";
when 19 =>
SRegister <= x"11";
SWriteData <= x"00";
when 20 =>
SRegister <= x"17";
SWriteData <= x"11";
when 21 =>
SRegister <= x"18";
SWriteData <= x"61";
when 22 =>
SRegister <= x"32";
SWriteData <= x"A4";
when 23 =>
SRegister <= x"19";
SWriteData <= x"03";
when 24 =>
SRegister <= x"1A";
SWriteData <= x"7B";
when 25 =>
SRegister <= x"03";
SWriteData <= x"0A";
when 26 =>
SRegister <= x"0E";
SWriteData <= x"61";
when 27 =>
SRegister <= x"0F";
SWriteData <= x"4B";
when 28 =>
SRegister <= x"16";
SWriteData <= x"02";
when 29 =>
SRegister <= x"1E";
SWriteData <= x"37";
when 30 =>
SRegister <= x"21";
SWriteData <= x"02";
when 31 =>
SRegister <= x"22";
SWriteData <= x"91";
when 32 =>
SRegister <= x"29";
SWriteData <= x"07";
when 33 =>
SRegister <= x"33";
SWriteData <= x"0B";
when 34 =>
SRegister <= x"35";
SWriteData <= x"0B";
when 35 =>
SRegister <= x"37";
SWriteData <= x"1D";
when 36 =>
SRegister <= x"38";
SWriteData <= x"71";
when 37 =>
SRegister <= x"39";
SWriteData <= x"2A";
when 38 =>
SRegister <= x"3C";
SWriteData <= x"78";
when 39 =>
SRegister <= x"4D";
SWriteData <= x"40";
when 40 =>
SRegister <= x"4E";
SWriteData <= x"20";
when 41 =>
SRegister <= x"69";
SWriteData <= x"00";
when 42 =>
SRegister <= x"6B";
SWriteData <= x"4A";
when 43 =>
SRegister <= x"74";
SWriteData <= x"10";
when 44 =>
SRegister <= x"8D";
SWriteData <= x"4F";
when 45 =>
SRegister <= x"8E";
SWriteData <= x"00";
when 46 =>
SRegister <= x"8F";
SWriteData <= x"00";
when 47 =>
SRegister <= x"90";
SWriteData <= x"00";
when 48 =>
SRegister <= x"91";
SWriteData <= x"00";
when 49 =>
SRegister <= x"96";
SWriteData <= x"00";
when 50 =>
SRegister <= x"9A";
SWriteData <= x"00";
when 51 =>
SRegister <= x"B0";
SWriteData <= x"84";
when 52 =>
SRegister <= x"B1";
SWriteData <= x"0C";
when 53 =>
SRegister <= x"B2";
SWriteData <= x"0E";
when 54 =>
SRegister <= x"B3";
SWriteData <= x"82";
when 55 =>
SRegister <= x"B8";
SWriteData <= x"0A";
when others =>
SRegister <= x"FF";
SWriteData <= x"FF";
SStart <= '0';
SEnable <= '0';
SCfgFinished <= '1';
SCounter <= 0;
end case;
else
SAddress <= SAddress;
SEnable <= SEnable;
SStart <= '0';
SCounter <= 0;
SRegister <= SRegister;
SWriteData <= SWriteData;
end if;
else
SAddress <= SAddress;
SEnable <= SEnable;
SStart <= SStart;
SRegister <= SRegister;
SWriteData <= SWriteData;
end if;
end if;
end if;
end process;
 
end Behavioral;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.