---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 21:49:24 05/26/2008 -- Design Name: -- Module Name: top - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library work; use work.usefuls.all; entity top is port ( -- i2c i2c_sda : inout std_logic; i2c_scl : inout std_logic; -- Ext. bus ext_bus0 : inout std_logic_vector(7 downto 0); ext_bus1 : inout std_logic_vector(7 downto 0); -- Ext. Oscilator osc_sysclk : in std_logic; -- 60MHz -- Camera side cam_extclk : out std_logic; cam_reset : out std_logic; cam_strobe : in std_logic; cam_dclk : in std_logic; cam_data : in std_logic_vector(7 downto 0); cam_hblk : in std_logic; cam_vblk : in std_logic; -- SDRAM side sdram_clk : out std_logic; sdram_cke : out std_logic; sdram_cs_n : out std_logic; sdram_we_n : out std_logic; sdram_cas_n : out std_logic; sdram_ras_n : out std_logic; sdram_dqm : out std_logic_vector(0 downto 0); sdram_bank_addr : out std_logic_vector(1 downto 0); sdram_addr : out std_logic_vector(11 downto 0); sdram_data : inout std_logic_vector(7 downto 0); -- Debug debug : out std_logic_vector(1 downto 0)); end top; architecture Behavioral of top is signal sysclk : std_logic; signal reset : std_logic; signal cam_dclk_buf1 : std_logic; signal cam_dclk_buf2 : std_logic; signal cam_vblk_buf : std_logic; signal cam_hblk_buf : std_logic; constant cam_data_address_width : integer := min_bits(1280 * 2 * 1024); -- SXGA (color:16bits/pixel) signal cam_data_address : std_logic_vector(cam_data_address_width-1 downto 0) := (others => '0'); signal ext_dclk_buf : std_logic; signal ext_data_address : std_logic_vector(cam_data_address_width-1 downto 0) := (others => '0'); type state_type is ( CAM_DATA_RXING, CAM_DATA_RXED, EXT_HEADER_TXING, EXT_DATA_TXING, EXT_DATA_TXED); signal current_state : state_type; component SDRAM is generic ( address_width : integer := 24; data_width : integer := 16; sdram_dqm_width : integer := 2; sdram_bank_addr_width : integer := 2; sdram_addr_width : integer := 12; sdram_data_width : integer := 16; clk_period : integer := 21; -- [ns] 48MHz sdram_refresh_cycle : integer := 15625; -- [ns] 64 ms / 4096 sdram_tRCD : integer := 18; -- [ns] sdram_tRFC : integer := 60; -- [ns] sdram_tRP : integer := 18; -- [ns] sdram_tWR : integer := 31; -- [ns] sdram_tMRD_clock : integer := 2; sdram_cas_latency : integer := 3); port ( clk : in std_logic; -- Control side reset : in std_logic; cs : in std_logic; dir : in std_logic; -- W => '1', R=> '0' done : out std_logic; -- complete write / data valid address : in std_logic_vector( address_width-1 downto 0); data_in : in std_logic_vector( data_width-1 downto 0); data_out : out std_logic_vector( data_width-1 downto 0); -- SDRAM side sdram_clk : out std_logic; sdram_cke : out std_logic; sdram_cs_n : out std_logic; sdram_we_n : out std_logic; sdram_cas_n : out std_logic; sdram_ras_n : out std_logic; sdram_dqm : out std_logic_vector( sdram_dqm_width-1 downto 0); sdram_bank_addr : out std_logic_vector( sdram_bank_addr_width-1 downto 0); sdram_addr : out std_logic_vector( sdram_addr_width-1 downto 0); sdram_data : inout std_logic_vector( sdram_data_width-1 downto 0)); end component; constant sdram_data_width : integer := 8; signal sdram_if_cs : std_logic := '0'; signal sdram_if_dir : std_logic; -- W => '1', R=> '0' signal sdram_if_done : std_logic; -- complete write / data valid constant sdram_if_addr_width : integer := 23; -- 2^23 = 8M signal sdram_if_addr : std_logic_vector(sdram_if_addr_width-1 downto 0); constant sdram_if_burst_length : integer := 4; constant sdram_if_burst_mask_length : integer := log2_ceil(sdram_if_burst_length); constant sdram_if_data_width : integer := 8 * sdram_if_burst_length; signal sdram_if_data_in : std_logic_vector(sdram_if_data_width-1 downto 0); signal sdram_if_data_out : std_logic_vector(sdram_if_data_width-1 downto 0); signal ext_data_buf : std_logic_vector(sdram_if_data_width-1 downto 0); signal ext_ready_buf : std_logic; signal is_burst_first_ext_address : boolean; signal is_burst_last_cam_address : boolean; signal ext_data_address_masked : std_logic_vector(cam_data_address_width-1 downto 0) := (others => '0'); signal cam_data_address_masked : std_logic_vector(cam_data_address_width-1 downto 0) := (others => '0'); signal sdram_if_data_in_shifted : std_logic_vector(sdram_if_data_width-1 downto 0); signal ext_data_buf_shifted : std_logic_vector(sdram_if_data_width-1 downto 0); -- intermidiate transaction signal ext_reset : std_logic := '1'; signal ext_data : std_logic_vector(7 downto 0); signal ext_data_size : std_logic_vector(31 downto 0); type ext_data_size_in_byte_type is array(((ext_data_size'length / 8) - 1) downto 0) of std_logic_vector(7 downto 0); signal ext_data_size_in_byte : ext_data_size_in_byte_type; signal ext_dclk : std_logic; signal ext_req : std_logic; signal ext_ready : std_logic; signal header_index : std_logic_vector((log2_ceil(ext_data_size_in_byte'length - 1) - 1) downto 0) := (others => '0'); component DividerN is generic ( divide_value : positive := 8); port ( clk, reset : in std_logic; clk_out, tc : out std_logic); end component; component i2c is port( scl : inout std_logic; sda : inout std_logic; clk : in std_logic; reset : in std_logic; address : out std_logic_vector(6 downto 0); valid_address : in std_logic; data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(7 downto 0); transaction : out std_logic; -- keep '1' in the same transaction dir : out std_logic; -- OUT => '0', IN => '1' request : out std_logic; -- request to client ready : in std_logic); -- client ready end component; signal i2c_address : std_logic_vector(6 downto 0); signal i2c_valid_address : std_logic; signal i2c_transaction : std_logic; signal i2c_dir : std_logic; signal i2c_request : std_logic; signal i2c_ready : std_logic; constant i2c_address_mine : integer := 16#3E#; -- TCM8240MD(0b0111101 = 0x3D) + 1 signal clk_1Khz : std_logic; signal clk_1hz : std_logic; signal por_counter : std_logic_vector(5 downto 0) := (others => '1'); begin ext_bus0 <= (others => 'Z'); ext_bus1 <= (others => 'Z'); sysclk <= osc_sysclk; reset <= ext_reset; div1 : DividerN generic map ( divide_value => 6) -- 60MHz => 10MHz port map ( clk => sysclk, reset => reset, clk_out => cam_extclk); div2: DividerN generic map ( divide_value => 60000) -- 60MHz => 1KHz port map ( clk => sysclk, reset => '0', clk_out => clk_1Khz); div3: DividerN generic map ( divide_value => 1000) -- 1KHz => 1Hz port map ( clk => clk_1Khz, reset => reset, clk_out => clk_1hz); --ext_reset <= '0'; process(clk_1Khz) begin if clk_1Khz'event and clk_1Khz = '1' then if por_counter > conv_std_logic_vector(0, por_counter'length) then -- 2^6=64ms @ 1Khz por_counter <= por_counter - 1; ext_reset <= '1'; else por_counter <= por_counter; ext_reset <= '0'; end if; end if; end process; sdram_if : SDRAM generic map ( address_width => sdram_if_addr_width, data_width => sdram_if_data_width, sdram_dqm_width => 1, sdram_bank_addr_width => 2, sdram_addr_width => 12, sdram_data_width => sdram_data_width, clk_period => 17, -- [ns] 60MHz sdram_refresh_cycle => 15625, -- [ns] sdram_tRCD => 18, -- [ns] sdram_tRFC => 60, -- [ns] sdram_tRP => 18, -- [ns] sdram_tWR => 31, -- [ns] sdram_tMRD_clock => 2, sdram_cas_latency => 2) port map ( clk => sysclk, -- Control side reset => reset, cs => sdram_if_cs, dir => sdram_if_dir, done => sdram_if_done, address => sdram_if_addr, data_in => sdram_if_data_in, data_out => sdram_if_data_out, -- SDRAM side sdram_clk => sdram_clk, sdram_cke => sdram_cke, sdram_cs_n => sdram_cs_n, sdram_we_n => sdram_we_n, sdram_cas_n => sdram_cas_n, sdram_ras_n => sdram_ras_n, sdram_dqm => sdram_dqm, sdram_bank_addr => sdram_bank_addr, sdram_addr => sdram_addr, sdram_data => sdram_data); i2c_if : i2c port map( scl => i2c_scl, sda => i2c_sda, clk => sysclk, reset => reset, address => i2c_address, valid_address => i2c_valid_address, data_in => ext_data, --data_out : out std_logic_vector(7 downto 0); transaction => i2c_transaction, -- keep '1' in the same transaction dir => i2c_dir, -- OUT => '0', IN => '1' request => i2c_request, -- request to client ready => i2c_ready); -- client ready i2c_valid_address <= '1' when (i2c_address = conv_std_logic_vector(i2c_address_mine, 7)) and i2c_dir = '1' else '0'; ext_req <= '1' when i2c_valid_address = '1' and i2c_transaction = '1' else '0'; ext_dclk <= i2c_request when ext_req = '1' else '0'; cam_reset <= not reset; -- state machine process(sysclk, reset) begin if reset = '1' then current_state <= EXT_DATA_TXED; elsif sysclk'event and sysclk = '1' then case current_state is when CAM_DATA_RXING => if cam_vblk_buf = '1' and cam_vblk = '0' then current_state <= CAM_DATA_RXED; else current_state <= CAM_DATA_RXING; end if; when CAM_DATA_RXED => if ext_req = '1' and sdram_if_cs = '0' then current_state <= EXT_HEADER_TXING; elsif cam_vblk_buf = '0' and cam_vblk = '1' then current_state <= CAM_DATA_RXING; else current_state <= CAM_DATA_RXED; end if; when EXT_HEADER_TXING => if ext_req = '0' then current_state <= EXT_DATA_TXED; elsif header_index = (header_index'range => '1') and ext_dclk_buf = '1' and ext_dclk = '0' then current_state <= EXT_DATA_TXING; else current_state <= EXT_HEADER_TXING; end if; when EXT_DATA_TXING => if ext_req = '0' then current_state <= EXT_DATA_TXED; else current_state <= EXT_DATA_TXING; end if; when EXT_DATA_TXED => if cam_vblk_buf = '0' or cam_vblk = '0' then current_state <= CAM_DATA_RXING; else current_state <= EXT_DATA_TXED; end if; when others => current_state <= current_state; end case; end if; end process; -- assign CAM inputs to SDRAM data inputs process(sysclk) begin if sysclk'event and sysclk = '1' then cam_dclk_buf1 <= cam_dclk; cam_dclk_buf2 <= cam_dclk_buf1; cam_vblk_buf <= cam_vblk; cam_hblk_buf <= cam_hblk; if current_state = EXT_DATA_TXING then cam_data_address <= cam_data_address; elsif current_state = EXT_DATA_TXED or (cam_vblk_buf = '0' and cam_vblk = '1') then cam_data_address <= (others => '0'); elsif cam_hblk_buf = '1' and cam_dclk_buf1 = '1' and cam_dclk = '0' then cam_data_address <= cam_data_address + 1; else cam_data_address <= cam_data_address; end if; if cam_hblk = '1' and cam_dclk_buf1 = '0' and cam_dclk = '1' then sdram_if_data_in <= sdram_if_data_in_shifted; else sdram_if_data_in <= sdram_if_data_in; end if; end if; end process; -- assign SDRAM data outputs to EXT inputs process(sysclk) begin if sysclk'event and sysclk = '1' then ext_dclk_buf <= ext_dclk; if current_state /= EXT_DATA_TXING then ext_data_address <= (others => '0'); elsif (ext_data_address < cam_data_address) and ext_dclk_buf = '1' and ext_dclk = '0' then ext_data_address <= ext_data_address + 1; else ext_data_address <= ext_data_address; end if; end if; end process; gen_with_burst : if sdram_if_burst_mask_length > 0 generate is_burst_first_ext_address <= true when ext_data_address(sdram_if_burst_mask_length-1 downto 0) = conv_std_logic_vector(0, sdram_if_burst_mask_length) else false; is_burst_last_cam_address <= true when cam_data_address(sdram_if_burst_mask_length-1 downto 0) = (not conv_std_logic_vector(0, sdram_if_burst_mask_length)) else false; ext_data_address_masked <= ext_data_address(cam_data_address_width-1 downto sdram_if_burst_mask_length) & conv_std_logic_vector(0, sdram_if_burst_mask_length); cam_data_address_masked <= cam_data_address(cam_data_address_width-1 downto sdram_if_burst_mask_length) & conv_std_logic_vector(0, sdram_if_burst_mask_length); sdram_if_data_in_shifted <= cam_data & sdram_if_data_in(sdram_if_data_width-1 downto 8); ext_data_buf_shifted <= conv_std_logic_vector(0, 8) & ext_data_buf(sdram_if_data_width-1 downto 8); end generate; gen_without_burst : if sdram_if_burst_mask_length = 0 generate is_burst_first_ext_address <= true; is_burst_last_cam_address <= true; ext_data_address_masked <= ext_data_address; cam_data_address_masked <= cam_data_address; sdram_if_data_in_shifted <= cam_data & conv_std_logic_vector(0, sdram_if_data_width-8); ext_data_buf_shifted <= ext_data_buf; end generate; process(sysclk, reset) begin if reset = '1' then ext_ready_buf <= '0'; elsif sysclk'event and sysclk = '1' then if ext_dclk = '0' then ext_ready_buf <= '0'; elsif (sdram_if_cs = '1' and sdram_if_done = '1') or (ext_dclk_buf = '0' and ext_dclk = '1' and ((not is_burst_first_ext_address) or (current_state = EXT_HEADER_TXING))) then ext_ready_buf <= '1'; else ext_ready_buf <= ext_ready_buf; end if; if sdram_if_cs = '1' and sdram_if_done = '1' then ext_data_buf <= sdram_if_data_out; elsif ext_dclk_buf = '0' and ext_dclk = '1' and (not is_burst_first_ext_address) then ext_data_buf <= ext_data_buf_shifted; else ext_data_buf <= ext_data_buf; end if; if current_state /= EXT_HEADER_TXING then header_index <= (others => '0'); elsif ext_dclk_buf = '1' and ext_dclk = '0' then header_index <= header_index + 1; else header_index <= header_index; end if; end if; end process; ext_data <= ext_data_size_in_byte(conv_integer(header_index)) when current_state = EXT_HEADER_TXING else ext_data_buf(7 downto 0); ext_ready <= '1' when (current_state = EXT_DATA_TXING or current_state = EXT_HEADER_TXING) and ((ext_dclk = '0' and ext_data_address < cam_data_address) or (ext_dclk = '1' and ext_ready_buf = '1')) else '0'; i2c_ready <= ext_ready_buf when (current_state = EXT_DATA_TXING or current_state = EXT_HEADER_TXING) else '0'; ext_data_size <= conv_std_logic_vector(0, ext_data_size'length - cam_data_address'length) & cam_data_address; gen_ext_data_size_in_byte : for i in 0 to ext_data_size_in_byte'length - 1 generate ext_data_size_in_byte(i) <= ext_data_size(((i * 8) + 7) downto (i * 8)); end generate; -- push/pop SDRAM data process(sysclk, reset) begin if reset = '1' then sdram_if_cs <= '0'; elsif sysclk'event and sysclk = '1' then if current_state = EXT_DATA_TXING or current_state = EXT_DATA_TXED then if ext_dclk_buf = '0' and ext_dclk = '1' and is_burst_first_ext_address then sdram_if_cs <= '1'; elsif sdram_if_cs = '1' and sdram_if_done = '1' then sdram_if_cs <= '0'; else sdram_if_cs <= sdram_if_cs; end if; sdram_if_dir <= '0'; sdram_if_addr <= conv_std_logic_vector(0, sdram_if_addr_width - cam_data_address_width) & ext_data_address_masked; else if sdram_if_cs = '0' and ((is_burst_last_cam_address and cam_dclk_buf2 = '0' and cam_dclk_buf1 = '1' and cam_hblk_buf = '1') or (cam_vblk_buf = '1' and cam_vblk = '0')) then sdram_if_cs <= '1'; elsif sdram_if_cs = '1' and sdram_if_done = '1' then sdram_if_cs <= '0'; else sdram_if_cs <= sdram_if_cs; end if; sdram_if_dir <= '1'; sdram_if_addr <= conv_std_logic_vector(0, sdram_if_addr_width - cam_data_address_width) & cam_data_address_masked; end if; end if; end process; --debug(0) <= clk_1hz; --debug(0) <= reset; --debug(0) <= '1' when is_burst_first_ext_address else '0'; debug(0) <= not i2c_transaction; --debug(0) <= not i2c_request; --debug(0) <= not i2c_ready; --debug(0) <= i2c_scl; debug(1) <= ext_ready_buf; end Behavioral;