library ieee; library unisim; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; -- Xilinx primitives (???) use unisim.VComponents.all; entity init_ch7301c is port ( clk: in std_logic; reset: in std_logic; i2c_scl: inout std_logic; i2c_sda: inout std_logic; dvi_reset: out std_logic; dip: in std_logic_vector(7 downto 0); led: out std_logic_vector(7 downto 0); led_n: out std_logic; led_e: out std_logic; led_s: out std_logic; led_w: out std_logic; led_c: out std_logic ); end init_ch7301c; architecture Behavioral of init_ch7301c is constant i2c_ch7301c: std_logic_vector(6 downto 0) := "1110110"; -- 0x76 signal i2c_reset: std_logic := '1'; signal i2c_execute: std_logic := '0'; signal i2c_busy: std_logic; signal i2c_busy_old: std_logic; signal i2c_address: std_logic_vector(6 downto 0); signal i2c_write: std_logic; signal i2c_data_in: std_logic_vector(7 downto 0); signal i2c_data_out: std_logic_vector(7 downto 0); signal i2c_error: std_logic; type states is (start, init, finished, error); signal state: states := start; begin i2c_master: entity work.i2c_master generic map ( input_clk => 27_000_000, bus_clk => 100_000 ) port map ( clk => clk, reset_n => i2c_reset, ena => i2c_execute, addr => i2c_address, rw => not i2c_write, data_wr => i2c_data_in, busy => i2c_busy, data_rd => i2c_data_out, ack_error => i2c_error, scl => i2c_scl, sda => i2c_sda ); led_n <= '1' when state = start else '0'; led_e <= '1' when state = init else '0'; led_s <= '1' when state = finished else '0'; led_w <= '1' when state = error else '0'; led_c <= reset; main: process(clk, reset) variable delay_init: integer range 0 to 10_000 := 0; variable busy_count: integer range 0 to 2 := 0; begin if reset = '1' then busy_count := 0; delay_init := 0; state <= start; -- reset components dvi_reset <= '0'; i2c_reset <= '0'; elsif rising_edge(clk) then case state is when start => delay_init := delay_init + 1; if delay_init = 5_000 then -- start components dvi_reset <= '1'; i2c_reset <= '1'; elsif delay_init = 10_000 then delay_init := 0; -- start i2c init state <= init; busy_count := 0; end if; when init => i2c_busy_old <= i2c_busy; -- remember old value if i2c_busy_old = '0' and i2c_busy = '1' then -- count rising edges on i2c_busy: -- command was accepted, ready for new one busy_count := busy_count + 1; end if; if i2c_error = '1' then -- abort on error i2c_execute <= '0'; state <= error; end if; case busy_count is when 0 => -- no command accepted yet, insert first one i2c_execute <= '1'; i2c_write <= '1'; i2c_address <= i2c_ch7301c; i2c_data_in <= dip; when 1 => -- submit read command i2c_write <= '0'; when 2 => -- read submitted, wait for results, no more commands i2c_execute <= '0'; if i2c_busy = '0' then led <= i2c_data_out; busy_count := 0; state <= finished; end if; end case; when finished => null; when error => null; end case; end if; end process main; end Behavioral;