-- OV7640_Model.vhd-- 現在のOV7640の仕様機能のみをモデル化する
-- Yデータは0から+1していく。UデータはFFから2つずつ減算(つまりずっと奇数)、VデータはFEから2つずつ減算(つまりずっと偶数)
-- clkに対してpclkは5ns程度遅延させる
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity OV7640_Model is
port(
clk : in std_logic; -- クロック入力
n_reset : in std_logic; -- リセット入力
vsync : out std_logic;
href : out std_logic;
pclk : out std_logic;
ydata : out std_logic_vector(7 downto 0)
-- sio_c : in std_logic;
-- sio_d : inout std_logic
);
end OV7640_Model;
architecture BEHAVIOR of OV7640_Model is
constant H_ACTIVE_VIDEO : integer := 640;
constant H_BLANK_SPACE : integer := 124;
constant H_SUM : integer := H_ACTIVE_VIDEO + H_BLANK_SPACE;
constant V_ACTIVE_VIDEO : integer := 480;
constant V_FRONT_PORCH : integer := 31;
constant V_SYNC_PULSE : integer := 3;
constant V_BACK_PORCH : integer := 11;
constant V_SUM : integer := V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;
signal h_count : unsigned(10 downto 0); -- 水平カウンタ
signal v_count : unsigned(9 downto 0); -- 垂直カウンタ
signal u_data : unsigned(7 downto 0);
signal v_data : unsigned(7 downto 0);
signal y_data : unsigned(7 downto 0);
signal reset : std_logic;
signal vsync_node : std_logic;
signal ydata_node : std_logic_vector(7 downto 0);
signal pclock : std_logic;
signal href_node : std_logic;
begin
reset <= not n_reset;
pclock <= transport clk after 5 ns;
pclk <= pclock;
-- 水平タイミング生成
process(reset, pclock) begin
if reset='1' then
h_count <= (others => '0');
elsif pclock'event and pclock='1' then
if h_count(10 downto 1) < H_SUM-1 then
h_count <= h_count + 1;
else -- CMOSカメラはUYなどと2クロックで1画素のため
h_count <= (others => '0');
end if;
end if;
end process;
href_node <= '1' when h_count<H_ACTIVE_VIDEO and v_count<V_ACTIVE_VIDEO else '0';
href <= href_node after 1 ns;
-- 垂直タイミング
process(reset, pclock) begin
if reset='1' then
v_count <= unsigned(CONV_STD_LOGIC_VECTOR((V_ACTIVE_VIDEO + V_FRONT_PORCH)-1,10));
elsif pclock'event and pclock='1' then
if h_count(10 downto 0)=H_SUM-1 then
if v_count < V_SUM-1 then
v_count <= v_count + 1;
else
v_count <= (others => '0');
end if;
end if;
end if;
end process;
-- vsync の出力タイミング
process(v_count) begin
if v_count>=(V_ACTIVE_VIDEO + V_FRONT_PORCH)-1 then
if v_count<V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE then
vsync_node <= '1';
else
vsync_node <= '0';
end if;
else
vsync_node <= '0';
end if;
end process;
vsync <= vsync_node after 1 ns;
-- ydata の出力
process(reset, pclock) begin -- Yデータ
if reset='1' then
y_data <= (others => '0');
elsif pclock'event and pclock='1' then
if h_count(10 downto 1)<H_ACTIVE_VIDEO and h_count(0)='1' then -- 水平の表示区間で2クロックに1回カウントアップ
y_data <= y_data + 1;
elsif h_count=0 and v_count=0 then -- 1フレーム描画の最初にリセット
y_data <= (others => '0');
end if;
end if;
end process;
process(reset, pclock) begin -- Uデータ
if reset='1' then
u_data <= (others => '1');
elsif pclock'event and pclock='1' then
if h_count(10 downto 1)<H_ACTIVE_VIDEO and h_count(1 downto 0)=0 then -- 水平の表示区間で4クロックに1回-2
u_data <= u_data - 2;
elsif h_count=0 and v_count=0 then -- 1フレーム描画の最初にリセット
u_data <= (others => '1');
end if;
end if;
end process;
process(reset, pclock) begin -- Vデータ
if reset='1' then
v_data <= X"FE";
elsif pclock'event and pclock='1' then
if h_count(10 downto 1)<H_ACTIVE_VIDEO and h_count(1 downto 0)=2 then -- 水平の表示区間で4クロックに1回-2
v_data <= v_data - 2;
elsif h_count=0 and v_count=0 then -- 1フレーム描画の最初にリセット
v_data <= X"FE";
end if;
end if;
end process;
process(h_count, y_data, u_data, v_data) begin
if h_count(10 downto 1)<H_ACTIVE_VIDEO then -- 表示区間
case h_count(1 downto 0) is
when "00" =>
ydata_node <= std_logic_vector(u_data);
when "01" =>
ydata_node <= std_logic_vector(y_data);
when "10" =>
ydata_node <= std_logic_vector(v_data);
when others => -- "11"
ydata_node <= std_logic_vector(y_data);
end case;
else
ydata_node <= (others => '0');
end if;
end process;
ydata <= ydata_node after 1 ns;
end BEHAVIOR;
-- IS61LV25616_model.vhd
--
-- IS61LV25616のモデル。タイミング関係は全く考慮せずに動作だけをモデル化する
-- 256KB入れると厳しいので、1/4にした
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
library modelsim_lib;
use modelsim_lib.util.all;
entity IS61LV25616 is
port(
mem_data : inout std_logic_vector(15 downto 0); -- SRAMのmemory data
n_mem_we : in std_logic; -- SRAMのmemory write enable
n_mem_rd : in std_logic; -- SRAMのmemory read enable
n_mem_cs : in std_logic; -- SRAMのchip select 0
n_mem_lowerB : in std_logic; -- SRAMのmemory lower byte enable
n_mem_upperB : in std_logic; -- SRAMのmemory upper byte enable
mem_addr : in std_logic_vector(17 downto 0) -- SRAMのmemory address
);
end IS61LV25616;
architecture RTL of IS61LV25616 is
type SRAM256K is array (0 to 65535) of bit_vector(7 downto 0);
signal sram_upper : SRAM256K;
signal sram_lower : SRAM256K;
signal mem_addr_int : integer range 0 to 65535;
signal mem_data_node : std_logic_vector(15 downto 0);
signal mem_data_node2 : std_logic_vector(15 downto 0);
signal master_sync : std_logic;
begin
mem_addr_int <= CONV_INTEGER(mem_addr(15 downto 0));
-- Write Upper
process(n_mem_we, n_mem_cs, n_mem_upperB, mem_data, mem_addr_int) begin
if n_mem_we='0' and n_mem_cs='0' and n_mem_upperB='0' then
sram_upper(mem_addr_int) <= To_bitvector(mem_data(15 downto 8));
end if;
end process;
-- Write Lower
process(n_mem_we, n_mem_cs, n_mem_lowerB, mem_data, mem_addr_int) begin
if n_mem_we='0' and n_mem_cs='0' and n_mem_lowerB='0' then
sram_lower(mem_addr_int) <= To_bitvector(mem_data(7 downto 0));
end if;
end process;
-- -- Read Upper
-- process(n_mem_cs, n_mem_rd, n_mem_upperB, mem_addr_int) begin
-- if n_mem_cs='0' and n_mem_rd='0' and n_mem_upperB='0' then
-- mem_data_node(15 downto 8) <= To_stdlogicvector(sram_upper(mem_addr_int));
-- else
-- mem_data_node(15 downto 8) <= (others => 'Z');
-- end if;
-- end process;
-- -- Read Lower
-- process(n_mem_cs, n_mem_rd, n_mem_lowerB, mem_addr_int) begin
-- if n_mem_cs='0' and n_mem_rd='0' and n_mem_lowerB='0' then
-- mem_data_node(7 downto 0) <= To_stdlogicvector(sram_lower(mem_addr_int));
-- else
-- mem_data_node(7 downto 0) <= (others => 'Z');
-- end if;
-- end process;
-- init_signal_spy でIS61LV25616_instの下にmaster_syncを持ってくる
process begin
init_signal_spy("../camdispcntrl_sram_inst/master_sync", "master_sync", 1, -1);
wait;
end process;
-- データの流れを見やすいように上位のデータは55から+1, 下位のデータはAAから+1して、出力
process(master_sync, n_mem_we) begin -- Read Upper
if master_sync='1' then
mem_data_node2(15 downto 8) <= x"55";
elsif n_mem_we'event and n_mem_we='1' then
if n_mem_cs='0' and n_mem_upperB='0' then
mem_data_node2(15 downto 8) <= mem_data_node2(15 downto 8) + 1;
end if;
end if;
end process;
mem_data_node(15 downto 8) <= mem_data_node2(15 downto 8) when n_mem_cs='0' and n_mem_rd='0' and n_mem_upperB='0' else (others => 'Z');
process(master_sync, n_mem_we) begin -- Read Lower
if master_sync='1' then
mem_data_node2(7 downto 0) <= x"AA";
elsif n_mem_we'event and n_mem_we='1' then
if n_mem_cs='0' and n_mem_lowerB='0' then
mem_data_node2(7 downto 0) <= mem_data_node2(7 downto 0) + 1;
end if;
end if;
end process;
mem_data_node(7 downto 0) <= mem_data_node2(7 downto 0) when n_mem_cs='0' and n_mem_rd='0' and n_mem_lowerB='0' else (others => 'Z');
mem_data <= mem_data_node after 1 ns;
end RTL;
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | - | - | - | - | - | - |