Assignment
Assignment
Assignment
kit
The objective of this project is to design a simple digital camera system in order to
illustrate some of the main concepts related to digital design with VHDL and
FPGAs, image and video formats, CMOS cameras, basic image processing
algorithms (black and white filters, edge detection, etc.) embedded programming
of microcontrollers, and others. This camera is not something that you will be able
to compete with against today's sophisticated commercial cameras, but it provides
a learning exercise and a platform for you to potentially try out new ideas and
enhancements.
Procedure:
First, take a look at the camera pins and assign them to the De-10 board:
entity ov7670_registers is
Port ( clk : in STD_LOGIC;
resend : in STD_LOGIC;
advance : in STD_LOGIC;
command : out std_logic_vector(15 downto 0);
finished : out STD_LOGIC);
end ov7670_registers;
begin
process(clk)
begin
if rising_edge(clk) then
case address is
when x"00" => sreg <= x"1280"; -- COM7 Reset
when x"01" => sreg <= x"1280"; -- COM7 Reset
when x"02" => sreg <= x"1204"; -- COM7 Size & RGB output
when x"03" => sreg <= x"1100"; -- CLKRC Prescaler - Fin/(1+1)
when x"04" => sreg <= x"0C00"; -- COM3 Lots of stuff, enable scaling, all others off
when x"05" => sreg <= x"3E00"; -- COM14 PCLK scaling off
when x"06" => sreg <= x"8C00"; -- RGB444 Set RGB format
when x"07" => sreg <= x"0400"; -- COM1 no CCIR601
when x"08" => sreg <= x"4010"; -- COM15 Full 0-255 output, RGB 565
when x"09" => sreg <= x"3a04"; -- TSLB Set UV ordering, do not auto-reset window
when x"0A" => sreg <= x"1438"; -- COM9 - AGC Celling
when x"0B" => sreg <= x"4f40"; --x"4fb3"; -- MTX1 - colour conversion matrix
when x"0C" => sreg <= x"5034"; --x"50b3"; -- MTX2 - colour conversion matrix
when x"0D" => sreg <= x"510C"; --x"5100"; -- MTX3 - colour conversion matrix
when x"0E" => sreg <= x"5217"; --x"523d"; -- MTX4 - colour conversion matrix
when x"0F" => sreg <= x"5329"; --x"53a7"; -- MTX5 - colour conversion matrix
when x"10" => sreg <= x"5440"; --x"54e4"; -- MTX6 - colour conversion matrix
when x"11" => sreg <= x"581e"; --x"589e"; -- MTXS - Matrix sign and auto contrast
when x"12" => sreg <= x"3dc0"; -- COM13 - Turn on GAMMA and UV Auto adjust
when x"13" => sreg <= x"1100"; -- CLKRC Prescaler - Fin/(1+1)
when x"14" => sreg <= x"1711"; -- HSTART HREF start (high 8 bits)
when x"15" => sreg <= x"1861"; -- HSTOP HREF stop (high 8 bits)
when x"16" => sreg <= x"32A4"; -- HREF Edge offset and low 3 bits of HSTART
and HSTOP
when x"17" => sreg <= x"1903"; -- VSTART VSYNC start (high 8 bits)
when x"18" => sreg <= x"1A7b"; -- VSTOP VSYNC stop (high 8 bits)
when x"19" => sreg <= x"030a"; -- VREF VSYNC low two bits
This code is used to set the register of the camera, each pixel will have a corresponding value
and the register will save a value to COMMAND
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity i2c_sender is
Port ( clk : in STD_LOGIC;
siod : inout STD_LOGIC;
sioc : out STD_LOGIC;
taken : out STD_LOGIC;
send : in STD_LOGIC;
id : in STD_LOGIC_VECTOR (7 downto 0);
reg : in STD_LOGIC_VECTOR (7 downto 0);
value : in STD_LOGIC_VECTOR (7 downto 0));
end i2c_sender;
signal divider : unsigned (7 downto 0) := "00000001"; -- this value gives a 254 cycle
pause before the initial frame is sent
signal busy_sr : std_logic_vector(31 downto 0) := (others => '0');
signal data_sr : std_logic_vector(31 downto 0) := (others => '1');
begin
process(busy_sr, data_sr(31))
begin
if busy_sr(11 downto 10) = "10" or
busy_sr(20 downto 19) = "10" or
busy_sr(29 downto 28) = "10" then
siod <= 'Z';
else
siod <= data_sr(31);
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
taken <= '0';
if busy_sr(31) = '0' then
SIOC <= '1';
if send = '1' then
if divider = "00000000" then
data_sr <= "100" & id & '0' & reg & '0' & value & '0' & "01";
busy_sr <= "111" & "111111111" & "111111111" & "111111111" & "11";
taken <= '1';
else
divider <= divider+1; -- this only happens on powerup
end if;
end if;
else
This code take the value of COMMAND to the SIOC signal of the camera
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity VGA is
Port (
CLK25 : in STD_LOGIC; -- 25 MHz input clock
clkout : out STD_LOGIC; -- Output clock to the ADV7123 and TFT display
Hsync,Vsync : out STD_LOGIC; -- output the two synchronization signals for the VGA
display
Nblank : out STD_LOGIC; -- control signal for ADV7123 D / A converter
activeArea : out STD_LOGIC;
Nsync : out STD_LOGIC -- synchronization signals and control of the TFT screen
);
end VGA;
end Behavioral;
Set up a 640x480 resolution screen, or VGA with horizontal and vertical pixel
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity digital_cam_impl1 is
Port ( clk_50 : in STD_LOGIC;
btn_resend : in STD_LOGIC;
led_config_finished : out STD_LOGIC;
ov7670_pclk : in STD_LOGIC;
ov7670_xclk : out STD_LOGIC;
ov7670_vsync : in STD_LOGIC;
ov7670_href : in STD_LOGIC;
ov7670_data : in STD_LOGIC_vector(7 downto 0);
ov7670_sioc : out STD_LOGIC;
ov7670_siod : inout STD_LOGIC;
ov7670_pwdn : out STD_LOGIC;
ov7670_reset : out STD_LOGIC
);
end digital_cam_impl1;
COMPONENT VGA
PORT(
CLK25 : IN std_logic;
Hsync : OUT std_logic;
Vsync : OUT std_logic;
Nblank : OUT std_logic;
clkout : OUT std_logic;
activeArea : OUT std_logic;
Nsync : OUT std_logic
);
END COMPONENT;
COMPONENT ov7670_controller
PORT(
clk : IN std_logic;
resend : IN std_logic;
siod : INOUT std_logic;
config_finished : OUT std_logic;
sioc : OUT std_logic;
reset : OUT std_logic;
pwdn : OUT std_logic;
xclk : OUT std_logic
);
END COMPONENT;
COMPONENT frame_buffer
PORT(
data : IN std_logic_vector(11 downto 0);
rdaddress : IN std_logic_vector(16 downto 0);
rdclock : IN std_logic;
wraddress : IN std_logic_vector(16 downto 0);
wrclock : IN std_logic;
wren : IN std_logic;
q : OUT std_logic_vector(11 downto 0)
);
END COMPONENT;
COMPONENT ov7670_capture
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(16 downto 0);
dout : OUT std_logic_vector(11 downto 0);
we : OUT std_logic
);
END COMPONENT;
COMPONENT RGB
PORT(
Din : IN std_logic_vector(11 downto 0);
Nblank : IN std_logic;
R : OUT std_logic_vector(7 downto 0);
G : OUT std_logic_vector(7 downto 0);
B : OUT std_logic_vector(7 downto 0)
);
END COMPONENT;
COMPONENT Address_Generator
PORT(
CLK25 : IN std_logic;
enable : IN std_logic;
vsync : in STD_LOGIC;
address : OUT std_logic_vector(16 downto 0)
);
END COMPONENT;
signal clk_50_camera : std_logic;
signal clk_25_vga : std_logic;
signal wren : std_logic;
signal resend : std_logic;
signal nBlank : std_logic;
signal vSync : std_logic;
begin
end my_structural;
this design basically connects a CMOS camera (OV7670 module) to DE2-115 board; video
frames are picked up from camera, buffered on the FPGA (using embedded RAM), and
displayed on the VGA monitor, which is also connected to the board; clock signals generated
inside FPGA using ALTPLL's that take as input the board's 50MHz signal from on-board
oscillator.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity RGB is
Port (
Din : in STD_LOGIC_VECTOR (11 downto 0); -- gray level of 8-bit pixels
Nblank : in STD_LOGIC; -- signal indicates the display area, outside the
display area
-- the three colors take 0
R,G,B : out STD_LOGIC_VECTOR (7 downto 0) -- the three colors on 10 bits
);
end RGB;
Now input the color to the pixel with the correct Din and Nblank
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ov7670_controller is
Port ( clk : in STD_LOGIC;
resend : in STD_LOGIC;
config_finished : out std_logic;
sioc : out STD_LOGIC;
siod : inout STD_LOGIC;
reset : out STD_LOGIC;
pwdn : out STD_LOGIC;
xclk : out STD_LOGIC
);
end ov7670_controller;
COMPONENT ov7670_registers
PORT(
clk : IN std_logic;
advance : IN std_logic;
resend : in STD_LOGIC;
command : OUT std_logic_vector(15 downto 0);
finished : OUT std_logic
);
END COMPONENT;
COMPONENT i2c_sender
PORT(
clk : IN std_logic;
send : IN std_logic;
taken : out std_logic;
id : IN std_logic_vector(7 downto 0);
reg : IN std_logic_vector(7 downto 0);
value : IN std_logic_vector(7 downto 0);
siod : INOUT std_logic;
sioc : OUT std_logic
);
END COMPONENT;
begin
Controll the OV760 camera - transferes registers to the camera over an I2C like bus, with
clk , taken, siod, send , sioc , id , reg , value,…. Signals
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 (16 downto 0);
dout : out STD_LOGIC_VECTOR (11 downto 0);
we : out STD_LOGIC);
end ov7670_capture;
capture_process: 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 dout we address address_next
-- cycle -1 x | xx xxxxxxxxxxxxxxxx xxxxxxxxxxxx x xxxx xxxx
-- cycle 0 1 | x1 xxxxxxxxRRRRRGGG xxxxxxxxxxxx x xxxx addr
-- cycle 1 0 | 10 RRRRRGGGGGGBBBBB xxxxxxxxxxxx x addr addr
-- cycle 2 x | 0x GGGBBBBBxxxxxxxx RRRRGGGGBBBB 1 addr addr+1
-- detect the rising edge on href - the start of the scan line
if href_hold = '0' and latched_href = '1' then
case line is
when "00" => line <= "01";
when "01" => line <= "10";
when "10" => line <= "11";
when others => line <= "00";
end case;
end if;
href_hold <= latched_href;
end process;
end Behavioral;
Use the “line” command to control the frequency of captured image on the camera-4 cycles.
The data will be stored in RAM
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY frame_buffer IS
PORT
(
data : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
rdaddress : IN STD_LOGIC_VECTOR (16 DOWNTO 0);
rdclock : IN STD_LOGIC;
wraddress : IN STD_LOGIC_VECTOR (16 DOWNTO 0);
wrclock : IN STD_LOGIC;
wren : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR (11 DOWNTO 0)
);
END frame_buffer;
-- read signals
signal q_top : STD_LOGIC_VECTOR (11 DOWNTO 0);
signal q_bottom : STD_LOGIC_VECTOR (11 DOWNTO 0);
-- write signals
signal wren_top : STD_LOGIC;
signal wren_bottom : STD_LOGIC;
BEGIN
Inst_buffer_top : my_frame_buffer_15to0
PORT MAP (
data => data(11 downto 0),
rdaddress => rdaddress(15 downto 0),
rdclock => rdclock,
wraddress => wraddress(15 downto 0),
wrclock => wrclock,
wren => wren_top,
q => q_top
);
Inst_buffer_bottom : my_frame_buffer_15to0
PORT MAP (
data => data(11 downto 0),
rdaddress => rdaddress(15 downto 0),
rdclock => rdclock,
wraddress => wraddress(15 downto 0),
wrclock => wrclock,
wren => wren_bottom,
q => q_bottom
);
END SYN;
This code is used to create a buffer to store pixels data for a frame of 320x240 pixels, data for
each pixel is 12 bits
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Address_Generator is
Port (
CLK25,enable : in STD_LOGIC;
vsync : in STD_LOGIC;
address : out STD_LOGIC_VECTOR (16 downto 0)
);
end Address_Generator;
process(CLK25)
begin
if rising_edge(CLK25) then
if (enable='1') then
end if;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.std_logic_unsigned.all;
entity sdram_rw is
Port (
-- connections to sdram controller;
clk_i : in STD_LOGIC; -- 25 MHz
rst_i : in STD_LOGIC;
addr_i : out STD_LOGIC_vector(24 downto 0);
dat_i : out STD_LOGIC_vector(31 downto 0);
dat_o : in STD_LOGIC_vector(31 downto 0);
we_i : out STD_LOGIC;
ack_o : in STD_LOGIC;
stb_i : out STD_LOGIC;
cyc_i : out STD_LOGIC;
-- connections to frame buffer 2 for which we need to
-- generate addresses and pass image data from SDRAM;
addr_buf2 : OUT STD_LOGIC_VECTOR (16 downto 0);
dout_buf2 : OUT std_logic_vector(11 downto 0);
we_buf2 : OUT std_logic;
-- connections from frame buffer 1 from where we
-- take snapshot; we of buf 1 is controlled by ov7670_capture
-- here we only read from buffer 1;
addr_buf1 : OUT STD_LOGIC_VECTOR (16 downto 0);
din_buf1 : IN std_logic_vector(11 downto 0);
-- rw controls
take_snapshot : in STD_LOGIC; -- store to SDRAM;
display_snapshot : in STD_LOGIC; -- read/fetch from SDRAM;
led_done : out STD_LOGIC
);
end sdram_rw;
architecture my_behavioral of sdram_rw is
-- we need to read 320x240 = 76800 words; we use 1 word in SDRAM per pixel
-- even though right now pixel data is only 12 bits of useful info;
-- this is just in case we'll use 24 bits per pixel in the future;
constant NUM_PIXELS : std_logic_vector(16 downto 0) :=
std_logic_vector(to_unsigned(76799, 17));
begin
process (clk_i)
begin
if rising_edge (clk_i) then
if (rst_i = '1') then
state <= IDLE_ST;
led_done_r <= '0';
we_buf2_r <= '0';
elsif (take_snapshot = '1' and state = IDLE_ST) then
state <= START_WRITE_ST;
led_done_r <= '0';
we_buf2_r <= '0';
addr_buf1_r <= (others => '0');
elsif (display_snapshot = '1' and state = IDLE_ST) then
state <= START_READ_ST;
led_done_r <= '0';
we_buf2_r <= '1';
addr_buf2_r <= (others => '0');
else
case state is
-- each pixel data writing into sdram goes tru the sequence of 3 states:
-- WRITE_ST --> WAIT_WRITE_ACK_ST --> WRITE_WAIT_ST
when WRITE_ST =>
state <= WAIT_WRITE_ACK_ST;
stb_i_r <= '1';
cyc_i_r <= '1';
we_i_r <= '1';
-- now, this is a bit tricky: pick up data coming from buffer 1 here;
-- data should be stable already, because I changed the address in the previous
-- cycle inside state WRITE_WAIT_ST, but on falling edge of clk_i, from within
-- a different process;
--dat_i_r <= ("00000000000000000000" & "000000001111"); -- blue debug;
dat_i_r <= ("00000000000000000000" & din_buf1_r); -- pass this to be written to
sdram;
-- increment address for buf1; very important to do this here instead of
-- in WRITE_WAIT_ST state; otherwise, we get a pixel lag that will shift the image
-- to the right;
addr_buf1_r <= addr_buf1_r + 1;
-- each pixel data reading process goes tru the sequence of 3 states:
-- READ_ST --> WAIT_READ_ACK_ST --> READ_WAIT_ST
-- which means three clock periods of 25 MHz; note that sdram
-- controller operates with clk_100 that is much faster;
when READ_ST => -- tell sdram_controller we want to read from addr_i_r
stb_i_r <= '1';
cyc_i_r <= '1';
we_i_r <= '0';
state <= WAIT_READ_ACK_ST;
when WAIT_READ_ACK_ST => -- wait for controller which should assert ack_o
-- here we "stall" in this state until ack_o is asserted;
if (ack_o = '1') then
stb_i_r <= '0';
cyc_i_r <= '0';
--dout_buf2_r <= "110000000011"; -- pink debug;
dout_buf2_r <= dat_o_r(11 downto 0); -- what comes from sdram_controller is sent
to buffer 2;
state <= READ_WAIT_ST;
end if;
-- when arrived to this state, a whole frame was written or read and we should
-- stay here and not repeat the process of writing or reading a frame
-- unless the whole thing is reset, which places us again in IDLE_ST state;
when DONE_ST =>
state <= DONE_ST; -- this ways we read or write all pixels only once;
led_done_r <= '1'; -- notify user it's success; will be used for self reset too at
top_level;
when others =>
state <= IDLE_ST;
led_done_r <= '0';
end case;
end if;
end if;
end process;
end my_behavioral;
used here to write into sdram the frame from frame buffer 1, also, used to read from sdram
and place the frame into frame buffer 2, the led done is asserted to signal that all pixels have
been written or read;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.std_logic_unsigned.all;
entity sdram_controller is
Port (
clk_i: in STD_LOGIC; -- clk_100
dram_clk_i: in STD_LOGIC; -- clk_100_3ns
rst_i: in STD_LOGIC;
dll_locked: in STD_LOGIC;
-- all ddr signals
dram_addr: out STD_LOGIC_vector(12 downto 0);
dram_bank: out STD_LOGIC_vector(1 downto 0);
dram_cas_n: out STD_LOGIC;
dram_cke: out STD_LOGIC;
dram_clk: out STD_LOGIC;
dram_cs_n: out STD_LOGIC;
dram_dq: inout STD_LOGIC_vector(15 downto 0);
dram_ldqm: out STD_LOGIC;
dram_udqm: out STD_LOGIC;
dram_ras_n: out STD_LOGIC;
dram_we_n: out STD_LOGIC;
-- wishbone bus
addr_i: in STD_LOGIC_vector(24 downto 0);
dat_i: in STD_LOGIC_vector(31 downto 0);
dat_o: out STD_LOGIC_vector(31 downto 0);
we_i: in STD_LOGIC;
ack_o: out STD_LOGIC;
stb_i: in STD_LOGIC;
cyc_i: in STD_LOGIC
);
end sdram_controller;
-- row width 13
-- column width 10
-- bank width 2
-- user address is specified as {bank,row,column}
begin
dram_addr <= dram_addr_r;
dram_bank <= dram_bank_r;
dram_cas_n <= dram_cas_n_r;
dram_ras_n <= dram_ras_n_r;
dram_we_n <= dram_we_n_r;
dram_dq <= dram_dq_r when oe_r = '1' else (others => 'Z');
process (clk_i)
begin
if rising_edge (clk_i) then
if (stb_i_r = '1' and current_state = ACT_ST) then
stb_i_r <= '0';
elsif (stb_i = '1' and cyc_i = '1') then
address_r <= addr_i;
dat_i_r <= dat_i;
we_i_r <= we_i; -- pick whatever value we_i has;
stb_i_r <= stb_i;
end if;
end if;
end process;
process (clk_i)
begin
if rising_edge (clk_i) then
if (current_init_state = INIT_DONE_ST) then
init_done <= '1';
end if;
end if;
end process;
-- state change
process (clk_i, rst_i)
begin
if rising_edge (clk_i) then
if (rst_i = '1') then
current_init_state <= INIT_IDLE;
else
current_init_state <= next_init_state;
end if;
end if;
end process;
-- ack_o signal
process (clk_i)
begin
if rising_edge (clk_i) then
if (current_state = READ_PRE_ST or current_state = WRITE_PRE_ST) then
ack_o_r <= '1';
elsif (current_state = WAIT_PRE_ST) then
ack_o_r <= '0';
end if;
end if;
end process;
-- data
process (clk_i, rst_i)
begin
if rising_edge (clk_i) then
if (rst_i = '1') then
dat_o_r <= (others => '0');
dram_dq_r <= (others => '0');
oe_r <= '0';
elsif (current_state = WRITE0_ST) then
dram_dq_r <= dat_i_r(31 downto 16);
oe_r <= '1';
elsif (current_state = WRITE1_ST) then
dram_dq_r <= dat_i_r(15 downto 0);
oe_r <= '1';
elsif (current_state = READ4_ST) then
-- we should actually be reading this on READ3, but
-- because of delay the data comes a cycle later...
dat_o_r(31 downto 16) <= dram_dq;
dram_dq_r <= (others => 'Z');
oe_r <= '0';
elsif (current_state = READ_PRE_ST) then
dat_o_r(15 downto 0) <= dram_dq;
dram_dq_r <= (others => 'Z');
oe_r <= '0';
else
dram_dq_r <= (others => 'Z');
oe_r <= '0';
end if;
end if;
end process;
-- address
process (clk_i)
begin
if rising_edge (clk_i) then
if (current_init_state = INIT_MODE_REG) then
dram_addr_r <= MODE_REGISTER;
elsif (current_init_state = INIT_INIT_PRE) then
-- from page 6 of datasheet of SDRAM chips on DE2-115 board:
-- A10 is sampled during a PRECHARGE command to
-- determine if all banks are to be precharged (A10 HIGH)
-- or bank selected by BA0, BA1 (LOW).
dram_addr_r <= "0010000000000"; -- A[10] = '1' to precharge all
elsif (current_state = ACT_ST) then
dram_addr_r <= address_r(22 downto 10);
dram_bank_r <= address_r(24 downto 23);
elsif (current_state = WRITE0_ST or current_state = READ0_ST) then
-- enter column with bit A10 set to 1 indicating auto precharge;
dram_addr_r <= "001" & address_r(9 downto 0);
dram_bank_r <= address_r(24 downto 23);
else
dram_addr_r <= (others => '0');
dram_bank_r <= "00";
end if;
end if;
end process;
-- commands
process (clk_i)
begin
if rising_edge (clk_i) then
if (current_init_state = INIT_INIT_PRE
or current_init_state = INIT_MODE_REG
or current_state = REFRESH_ST
or current_state = ACT_ST) then
dram_ras_n_r <= '0';
else
dram_ras_n_r <= '1';
end if;
if (current_state = READ0_ST
or current_state = WRITE0_ST
or current_state = REFRESH_ST
or current_init_state = INIT_MODE_REG) then
dram_cas_n_r <= '0';
else
dram_cas_n_r <= '1';
end if;
if (current_init_state = INIT_INIT_PRE
or current_state = WRITE0_ST
or current_init_state = INIT_MODE_REG) then
dram_we_n_r <= '0';
else
dram_we_n_r <= '1';
end if;
end if;
end process;
end my_behavioral;
this is the most important code: DRAM. Generate a DRAM to save the data temporarily
http://www.dejazzer.com/eigenpi/digital_camera/digital_camera.html