library ieee; use ieee.std_logic_1164.all; entity scl_generator is generic ( MIN_STABLE_CYCLES : natural := 5); port ( clk_i : in std_logic; rst_in : in std_logic; scl_i : in std_logic; scl_rising_i : in std_logic; scl_falling_i : in std_logic; gen_continuous_i : in std_logic; gen_rising_i : in std_logic; gen_falling_i : in std_logic; scl_enable_o : out std_logic; cannot_comply_o : out std_logic); end entity scl_generator; architecture a1 of scl_generator is type state_t is (OBSERVE, CHANGING, CHANGED); signal curr_state : state_t; signal next_state : state_t; signal should_fall : std_logic; signal should_rise : std_logic; signal should_change : std_logic; signal can_change : std_logic; signal scl_changing : std_logic; signal curr_scl : std_logic; signal next_scl : std_logic; signal curr_stable_count : integer range 0 to MIN_STABLE_CYCLES; signal next_stable_count : integer range 0 to MIN_STABLE_CYCLES; signal curr_scl_enable : std_logic := '0'; signal next_scl_enable : std_logic; begin -- architecture a1 cannot_comply_o <= '1' when curr_state = CHANGING and scl_changing /= '1' else '0'; scl_enable_o <= curr_scl_enable; scl_changing <= scl_rising_i or scl_falling_i; should_rise <= (gen_rising_i or gen_continuous_i) and not gen_falling_i and not curr_scl; should_fall <= (gen_falling_i or gen_continuous_i) and not gen_rising_i and curr_scl; should_change <= should_rise or should_fall; can_change <= '1' when curr_stable_count = MIN_STABLE_CYCLES else '0'; next_scl <= scl_i; set_next_state: process (all) is begin -- process set_next_state next_state <= curr_state; next_scl_enable <= curr_scl_enable; if curr_state = CHANGING then if scl_changing = '1' then next_state <= OBSERVE; end if; elsif can_change = '1' and should_change = '1' then if should_fall = '1' then next_scl_enable <= '1'; next_state <= CHANGING; elsif should_rise = '1' then next_scl_enable <= '0'; next_state <= CHANGING; end if; end if; end process set_next_state; next_stable_count <= 0 when scl_changing = '1' else curr_stable_count + 1 when can_change = '0' and curr_stable_count < MIN_STABLE_CYCLES else curr_stable_count; set_regs: process (clk_i) is begin -- process set_regs if rising_edge(clk_i) then -- rising clock edge if rst_in = '0' then -- synchronous reset (active low) curr_stable_count <= 0; curr_scl_enable <= '0'; curr_state <= OBSERVE; curr_scl <= '1'; else curr_stable_count <= next_stable_count; curr_scl_enable <= next_scl_enable; curr_state <= next_state; curr_scl <= next_scl; end if; end if; end process set_regs; end architecture a1;