@@ 0,0 1,100 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i2c_pkg.all;
+
+entity address_generator is
+
+ port (
+ clk_i : in std_logic; -- Clock
+ rst_in : in std_logic; -- Synchronous reset (active low)
+ address_i : in std_logic_vector(6 downto 0);
+ rw_i : in std_logic; -- Read (not write)
+ start_i : in std_logic; -- When to start sending the address.
+ -- A pulse. Every time it's '1',
+ -- address will be sent from beginning
+ -- First bit on rising edge
+ scl_rising_i : in std_logic;
+ scl_falling_delayed_i : in std_logic;
+ sda_enable_o : out std_logic; -- Data of the address to send.
+ sda_i : out std_logic;
+ noack_o : out std_logic;
+ unexpected_sda_o : out std_logic;
+ done_o : out std_logic);
+end entity address_generator;
+
+architecture a1 of address_generator is
+ type state_t is (IDLE, WAITING_FOR_FALLING, GEN, ACK, DONE);
+ signal curr_state : state_t;
+ signal next_state : state_t;
+
+ signal curr_index : integer range 0 to 8;
+ signal next_index : integer range 0 to 8;
+
+ signal curr_scl : std_logic;
+ signal next_scl : std_logic;
+begin -- architecture a1
+
+ sda_enable_o <= not address_i(6 - curr_index) when curr_index <= 6 and curr_state = GEN else
+ not rw_i when curr_index = 7 and curr_state = GEN else
+ '0';
+
+ next_index <= 0 when start_i = '1' else
+ curr_index + 1 when curr_index < 8 and scl_falling_delayed_i = '1' and curr_state = GEN else
+ curr_index;
+
+ unexpected_sda_o <= '1' when curr_state = GEN and sda_i /= address_i(6 - curr_index) and scl_rising_i = '1' else '0';
+ noack_o <= '1' when curr_state = ACK and scl_rising_i = '1' and sda_i = '1' else '0';
+ done_o <= '1' when curr_state = DONE else '0';
+
+ next_scl <= '1' when scl_rising_i = '1' else
+ '0' when scl_falling_delayed_i = '1' else
+ curr_scl;
+
+ set_next_state: process (all) is
+ variable start_gen : std_logic;
+ begin -- process set_next_state
+ next_state <= curr_state;
+ start_gen := '0';
+
+ if curr_state = IDLE then
+ if start_i = '1' then
+ start_gen := '1';
+ end if;
+ elsif curr_state = WAITING_FOR_FALLING then
+ if scl_falling_delayed_i = '1' then
+ next_state <= GEN;
+ end if;
+ elsif curr_state = GEN then
+ if curr_index = 8 then
+ next_state <= ACK;
+ end if;
+ elsif curr_state = ACK and scl_rising_i = '1' then
+ next_state <= DONE;
+ end if;
+
+ if start_gen = '1' then
+ if curr_scl = '1' then
+ next_state <= WAITING_FOR_FALLING;
+ else
+ next_state <= GEN;
+ end if;
+ end if;
+ end process set_next_state;
+
+ set_regs: process (clk_i) is
+ begin -- process set_next
+ if rising_edge(clk_i) then -- rising clock edge
+ if rst_in = '0' then -- synchronous reset (active low)
+ curr_state <= IDLE;
+ curr_index <= 0;
+ curr_scl <= '1';
+ else
+ curr_state <= next_state;
+ curr_index <= next_index;
+ curr_scl <= next_scl;
+ end if;
+ end if;
+ end process set_regs;
+
+end architecture a1;