M src/i2c/address_detector.vhd => src/i2c/address_detector.vhd +21 -12
@@ 4,18 4,19 @@ use ieee.std_logic_1164.all;
entity address_detector is
port (
- clk_i : in std_logic; -- Input clock
- rst_in : in std_logic; -- Reset the detection
- address_i : in std_logic_vector(6 downto 0);
- scl_rising : in std_logic;
+ clk_i : in std_logic; -- Input clock
+ rst_in : in std_logic; -- Reset the detection
+ address_i : in std_logic_vector(6 downto 0);
+ store_address_i : in std_logic;
+ scl_rising : in std_logic;
scl_falling_delayed_i : in std_logic;
- sda_enable_o : out std_logic;
- sda_i : in std_logic; -- The data that could contain the address
- start_i : in std_logic; -- When to start looking for the
- -- address. Will clear success_o
- rw_o : out std_logic;
- success_o : out std_logic; -- Whether full address matches
- fail_o : out std_logic); -- Whether matching failed. Will stay 0
+ sda_enable_o : out std_logic;
+ sda_i : in std_logic; -- The data that could contain the address
+ start_i : in std_logic; -- When to start looking for the
+ -- address. Will clear success_o
+ rw_o : out std_logic;
+ success_o : out std_logic; -- Whether full address matches
+ fail_o : out std_logic); -- Whether matching failed. Will stay 0
-- as long as bits are matching. Will
-- be set to 1 the first bit that does
-- not match the address
@@ 30,6 31,9 @@ architecture a1 of address_detector is
signal curr_index : integer range 0 to 7;
signal next_index : integer range 0 to 7;
+ signal curr_address : std_logic_vector(6 downto 0);
+ signal next_address : std_logic_vector(6 downto 0);
+
signal curr_read_rw : std_logic;
signal next_read_rw : std_logic;
@@ 40,6 44,9 @@ begin -- architecture a1
success_o <= '1' when curr_state = MATCH else '0';
rw_o <= curr_read_rw when curr_state = MATCH else '0';
+ next_address <= address_i when store_address_i = '1' else
+ curr_address;
+
next_read_rw <= sda_i when scl_rising = '1' and curr_index = 7 else
curr_read_rw;
@@ 47,7 54,7 @@ begin -- architecture a1
curr_index when curr_state = CHECKING else
0;
- mismatch <= '1' when curr_index <= 6 and address_i(6 - curr_index) /= sda_i and scl_rising = '1' else '0';
+ mismatch <= '1' when curr_index <= 6 and curr_address(6 - curr_index) /= sda_i and scl_rising = '1' else '0';
sda_enable_o <= '1' when curr_state = ACK_ON else '0';
@@ 89,10 96,12 @@ begin -- architecture a1
curr_state <= IDLE;
curr_index <= 0;
curr_read_rw <= '0';
+ curr_address <= (others => '0');
else
curr_state <= next_state;
curr_index <= next_index;
curr_read_rw <= next_read_rw;
+ curr_address <= next_address;
end if;
end if;
end process set_regs;
M src/i2c/address_generator.vhd => src/i2c/address_generator.vhd +10 -2
@@ 8,6 8,7 @@ entity address_generator is
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)
+ store_address_rw_i : in std_logic;
start_i : in std_logic; -- When to start sending the address.
-- A pulse. Every time it's '1',
-- address will be sent from beginning
@@ 26,6 27,9 @@ architecture a1 of address_generator is
signal curr_state : state_t;
signal next_state : state_t;
+ signal curr_data : std_logic_vector(7 downto 0);
+ signal next_data : std_logic_vector(7 downto 0);
+
signal curr_index : integer range 0 to 8;
signal next_index : integer range 0 to 8;
@@ 36,10 40,12 @@ architecture a1 of address_generator is
signal next_done : 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
+ sda_enable_o <= not curr_data(7 - curr_index) when curr_index <= 7 and curr_state = GEN else
'0';
+ next_data <= address_i & rw_i when store_address_rw_i = '1' else
+ curr_data;
+
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;
@@ 96,11 102,13 @@ begin -- architecture a1
curr_index <= 0;
curr_scl <= '1';
curr_done <= '0';
+ curr_data <= (others => '0');
else
curr_state <= next_state;
curr_index <= next_index;
curr_scl <= next_scl;
curr_done <= next_done;
+ curr_data <= next_data;
end if;
end if;
end process set_regs;
M src/i2c/master.vhd => src/i2c/master.vhd +3 -0
@@ 71,6 71,7 @@ architecture a1 of master is
signal adr_noack : std_logic;
signal adr_unexpected_sda : std_logic;
signal adr_done : std_logic;
+ signal adr_gen_store : std_logic;
signal adr_gen_start : std_logic;
signal cond_gen : std_logic;
@@ 223,6 224,7 @@ begin -- architecture a1
clk_i => clk_i,
rst_in => rst_in,
address_i => slave_address_i,
+ store_address_rw_i => adr_gen_store,
scl_rising_i => scl_rising,
scl_falling_delayed_i => scl_falling_delayed,
sda_enable_o => adr_sda_enable,
@@ 265,6 267,7 @@ begin -- architecture a1
--
address_gen_start_o => adr_gen_start,
address_gen_done_i => adr_done,
+ address_gen_store_o => adr_gen_store,
--
req_start_o => cond_gen_start,
req_stop_o => cond_gen_stop,
M src/i2c/master_state.vhd => src/i2c/master_state.vhd +2 -0
@@ 35,6 35,7 @@ entity master_state is
-- data for address_generator
address_gen_start_o : out std_logic;
address_gen_done_i : in std_logic;
+ address_gen_store_o : out std_logic;
-- data for cond generator
req_start_o : out std_logic;
req_stop_o : out std_logic;
@@ 106,6 107,7 @@ begin -- architecture a1
dev_busy_o <= '1' when curr_state /= IDLE and curr_state /= BUS_BUSY and curr_state /= ERR else '0';
address_gen_start_o <= '1' when curr_state = GENERATED_START and next_state = GENERATING_ADDRESS else '0';
+ address_gen_store_o <= start_i;
receive_o <= '1' when curr_state = RECEIVING else '0';
transmit_o <= '1' when curr_state = TRANSMITTING else '0';
M src/i2c/slave.vhd => src/i2c/slave.vhd +4 -1
@@ 69,6 69,7 @@ architecture a1 of slave is
signal address_detect_activate : std_logic;
signal address_detect_success : std_logic;
signal address_detect_fail : std_logic;
+ signal address_detect_store : std_logic;
signal address_detection : std_logic;
signal rw : std_logic;
@@ 168,7 169,8 @@ begin -- architecture a1
clk_i => clk_i,
rst_in => rst_in,
address_i => address_i,
- scl_rising => scl_rising,
+ store_address_i => address_detect_store,
+ scl_rising => scl_rising,
scl_falling_delayed_i => scl_falling_delayed,
sda_enable_o => address_detect_sda_enable,
sda_i => sync_sda,
@@ 193,6 195,7 @@ begin -- architecture a1
address_detect_success_i => address_detect_success,
address_detect_fail_i => address_detect_fail,
address_detect_start_o => address_detect_activate,
+ address_detect_store_o => address_detect_store,
address_detect_o => address_detection,
receive_o => receiving,
transmit_o => transmitting,
M src/i2c/slave_state.vhd => src/i2c/slave_state.vhd +12 -4
@@ 20,6 20,7 @@ entity i2c_slave_state is
address_detect_success_i : in std_logic;
address_detect_fail_i : in std_logic;
address_detect_start_o : out std_logic;
+ address_detect_store_o : out std_logic;
address_detect_o : out std_logic;
receive_o : out std_logic;
@@ 48,17 49,24 @@ architecture a1 of i2c_slave_state is
signal communicating_with_master : std_logic;
begin -- architecture a1
- communicating_with_master <= '1' when curr_state = BUS_ADDRESS or curr_state = RECEIVING or curr_state = TRANSMITTING else '0';
- address_detect_start_o <= '1' when start_condition_i = '1' else '0';
- address_detect_o <= '1' when curr_state = BUS_ADDRESS else '0';
+ rst_i2c_o <= curr_err_noack or curr_err_sda or start_condition_i or stop_condition_i;
+
+ address_detect_start_o <= start_condition_i;
+ address_detect_store_o <= start_condition_i;
+ address_detect_o <= '1' when curr_state = BUS_ADDRESS else '0';
+
err_noack_o <= curr_err_noack;
err_sda_o <= curr_err_sda;
- rst_i2c_o <= curr_err_noack or curr_err_sda or start_condition_i or stop_condition_i;
receive_o <= '1' when curr_state = RECEIVING else '0';
transmit_o <= '1' when curr_state = TRANSMITTING else '0';
bus_busy_o <= '1' when curr_state = BUS_BUSY else '0';
+ communicating_with_master <= '1' when curr_state = BUS_ADDRESS or
+ curr_state = RECEIVING or
+ curr_state = TRANSMITTING else
+ '0';
+
next_err_sda <= '0' when start_condition_i = '1' or stop_condition_i = '1' else
'1' when curr_err_sda = '1' else
'1' when unexpected_sda_i = '1' and curr_state = TRANSMITTING else
M tb/i2c/address_detector_tb.vhd => tb/i2c/address_detector_tb.vhd +2 -1
@@ 44,8 44,9 @@ begin -- architecture tb
port map (
clk_i => clk,
rst_in => rst_n,
+ store_address_i => '1',
address_i => address,
- scl_rising => scl_rising,
+ scl_rising => scl_rising,
scl_falling_delayed_i => scl_falling,
sda_i => sda,
sda_enable_o => sda_enable,
M tb/i2c/address_generator_tb.vhd => tb/i2c/address_generator_tb.vhd +1 -0
@@ 55,6 55,7 @@ begin -- architecture tb
clk_i => clk,
rst_in => rst_n,
start_i => start,
+ store_address_rw_i => '1',
address_i => address,
rw_i => rw,
sda_i => slave_sda,