---------------------------------------------------------------------------------- -- 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 ( -- MCU(C8051F340) side mcu_sysclk : in std_logic; -- 48MHz mcu_reset : in std_logic; mcu_data : inout std_logic_vector(7 downto 0); mcu_dclk : in std_logic; mcu_req : in std_logic; mcu_ready : out std_logic; mcu_int_n : out std_logic; -- Ext. Oscilator osc_sysclk : in std_logic; -- 80MHz -- 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 mcu_dclk_buf : std_logic; signal mcu_data_address : std_logic_vector(cam_data_address_width-1 downto 0) := (others => '0'); type state_type is ( CAM_DATA_RXING, CAM_DATA_RXED, MCU_DATA_TXING, MCU_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 mcu_data_buf : std_logic_vector(sdram_if_data_width-1 downto 0); signal mcu_ready_buf : std_logic; signal is_burst_first_mcu_address : boolean; signal is_burst_last_cam_address : boolean; signal mcu_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 mcu_data_buf_shifted : std_logic_vector(sdram_if_data_width-1 downto 0); component DividerN is generic ( divide_value : positive := 8); port ( clk, reset : in std_logic; clk_out, tc : out std_logic); end component; begin --sysclk <= osc_sysclk; sysclk <= mcu_sysclk; reset <= mcu_reset; div1 : DividerN generic map ( divide_value => 3) -- 48MHz => 16MHz port map ( clk => sysclk, reset => reset, clk_out => cam_extclk); 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 => 21, -- [ns] 48MHz 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); cam_reset <= not reset; -- state machine process(sysclk, reset) begin if reset = '1' then current_state <= CAM_DATA_RXING; 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 mcu_req = '1' and sdram_if_cs = '0' then current_state <= MCU_DATA_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 MCU_DATA_TXING => if mcu_req = '0' then current_state <= MCU_DATA_TXED; else current_state <= MCU_DATA_TXING; end if; when MCU_DATA_TXED => if cam_vblk_buf = '0' or cam_vblk = '0' then current_state <= CAM_DATA_RXING; else current_state <= MCU_DATA_TXED; end if; when others => null; 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 = MCU_DATA_TXING then cam_data_address <= cam_data_address; elsif current_state = MCU_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 MCU inputs process(sysclk) begin if sysclk'event and sysclk = '1' then mcu_dclk_buf <= mcu_dclk; if current_state = CAM_DATA_RXING or current_state = CAM_DATA_RXED then mcu_data_address <= (others => '0'); elsif (mcu_data_address < cam_data_address) and mcu_dclk_buf = '1' and mcu_dclk = '0' then mcu_data_address <= mcu_data_address + 1; else mcu_data_address <= mcu_data_address; end if; end if; end process; gen_with_burst : if sdram_if_burst_mask_length > 0 generate is_burst_first_mcu_address <= true when mcu_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; mcu_data_address_masked <= mcu_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); mcu_data_buf_shifted <= conv_std_logic_vector(0, 8) & mcu_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_mcu_address <= true; is_burst_last_cam_address <= true; mcu_data_address_masked <= mcu_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); mcu_data_buf_shifted <= mcu_data_buf; end generate; process(sysclk, reset, mcu_dclk) begin if reset = '1' or mcu_dclk = '0' then mcu_ready_buf <= '0'; elsif sysclk'event and sysclk = '1' then if (sdram_if_cs = '1' and sdram_if_done = '1') or (mcu_dclk_buf = '0' and mcu_dclk = '1' and (not is_burst_first_mcu_address)) then mcu_ready_buf <= '1'; else mcu_ready_buf <= mcu_ready_buf; end if; if sdram_if_cs = '1' and sdram_if_done = '1' then mcu_data_buf <= sdram_if_data_out; elsif mcu_dclk_buf = '0' and mcu_dclk = '1' and (not is_burst_first_mcu_address) then mcu_data_buf <= mcu_data_buf_shifted; else mcu_data_buf <= mcu_data_buf; end if; end if; end process; mcu_data <= mcu_data_buf(7 downto 0); mcu_ready <= '1' when current_state = MCU_DATA_TXING and ((mcu_dclk = '0' and mcu_data_address < cam_data_address) or (mcu_dclk = '1' and mcu_ready_buf = '1')) else '0'; -- 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 = MCU_DATA_TXING or current_state = MCU_DATA_TXED then if mcu_dclk_buf = '0' and mcu_dclk = '1' and is_burst_first_mcu_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) & mcu_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) <= '1' when is_burst_first_mcu_address else '0'; debug(1) <= mcu_ready_buf; end Behavioral;