M src/i2c/address_detector.vhd => src/i2c/address_detector.vhd +0 -2
@@ 1,8 1,6 @@
library ieee;
use ieee.std_logic_1164.all;
-use work.i2c_pkg.all;
-
entity address_detector is
port (
M src/i2c/address_generator.vhd => src/i2c/address_generator.vhd +0 -2
@@ 1,8 1,6 @@
library ieee;
use ieee.std_logic_1164.all;
-use work.i2c_pkg.all;
-
entity address_generator is
port (
M src/i2c/master.vhd => src/i2c/master.vhd +11 -8
@@ 5,7 5,8 @@ library utils;
entity master is
generic (
- SCL_FALLING_DELAY : natural := 5);
+ SCL_FALLING_DELAY : natural := 5;
+ SCL_MIN_STABLE_CYCLES : natural := 10);
port (
clk_i : in std_logic; -- Synchronous clock
@@ 19,13 20,11 @@ entity master is
rx_valid_o : out std_logic; -- Data in rx_data are valid
rx_data_o : out std_logic_vector(7 downto 0); -- Received data
rx_confirm_i : in std_logic; -- Confirm data from rx_data are read
- rx_stretch_i : in std_logic;
-- tx
tx_ready_o : out std_logic; -- Transmitter ready for new data
tx_valid_i : in std_logic; -- Are data in tx_data valid? Should be
-- a pulse for one cycle only
tx_data_i : in std_logic_vector(7 downto 0); -- Data to transmit
- tx_stretch_i : in std_logic;
tx_clear_buffer_i : in std_logic;
-- errors
err_noack_data_o : out std_logic;
@@ 90,6 89,7 @@ architecture a1 of master is
signal scl_falling_delayed : std_logic;
signal waiting_for_data : std_logic;
+ signal scl_gen_falling : std_logic;
begin -- architecture a1
rw_o <= rw;
dev_busy_o <= transmitting or receiving;
@@ 97,9 97,12 @@ begin -- architecture a1
waiting_for_data <= tx_scl_stretch or rx_scl_stretch;
waiting_o <= waiting_for_data;
- scl_enable_o <= tx_scl_stretch when transmitting = '1' and tx_stretch_i = '1' and scl_i = '0' else
- rx_scl_stretch when receiving = '1' and rx_stretch_i = '1' and scl_i = '0' else
- scl_gen_scl_enable;
+ scl_enable_o <= scl_gen_scl_enable;
+
+ scl_gen_falling <= cond_gen_req_scl_fall when cond_gen = '1' else
+ tx_scl_stretch when transmitting = '1' else
+ rx_scl_stretch when transmitting = '1' else
+ '0';
sda_enable_o <= tx_sda_enable when transmitting = '1' else
rx_sda_enable when receiving = '1' else
@@ 164,7 167,7 @@ begin -- architecture a1
scl_generator : entity work.scl_generator
generic map (
- MIN_STABLE_CYCLES => SCL_FALLING_DELAY)
+ MIN_STABLE_CYCLES => SCL_MIN_STABLE_CYCLES)
port map (
clk_i => clk_i,
rst_in => rst_in,
@@ 173,7 176,7 @@ begin -- architecture a1
scl_falling_i => scl_falling,
gen_continuous_i => scl_gen_req_continuous,
gen_rising_i => cond_gen_req_scl_rise,
- gen_falling_i => cond_gen_req_scl_fall,
+ gen_falling_i => scl_gen_falling,
scl_enable_o => scl_gen_scl_enable,
cannot_comply_o => open);
M src/i2c/master_state.vhd => src/i2c/master_state.vhd +11 -15
@@ 32,7 32,7 @@ entity master_state is
tx_done_i : in std_logic;
-- data for address_generator
address_gen_start_o : out std_logic;
- address_gen_done_i : out std_logic;
+ address_gen_done_i : in std_logic;
-- data for cond generator
req_start_o : out std_logic;
req_stop_o : out std_logic;
@@ 116,12 116,12 @@ begin -- architecture a1
rst_i2c_o <= any_err;
- next_gen_start_req <= '1' when start_i = '1' else
- '0' when next_state = GENERATING_START else
+ next_gen_start_req <= '1' when start_i = '1' and run_i = '1' else
+ '0' when curr_state = GENERATING_START else
curr_gen_start_req;
next_gen_stop_req <= '1' when stop_i = '1' else
- '0' when next_state = GENERATING_STOP else
+ '0' when curr_state = GENERATING_STOP else
curr_gen_stop_req;
next_err_general <= '0' when start_condition_i = '1' else
@@ 220,10 220,6 @@ begin -- architecture a1
next_state <= GENERATING_STOP;
end if;
end if;
-
- if run_i = '0' then
- next_state <= IDLE;
- end if;
end process set_next_state;
set_regs: process (clk_i) is
@@ 238,13 234,13 @@ begin -- architecture a1
curr_gen_start_req <= '0';
curr_gen_stop_req <= '0';
else
- curr_state <= curr_state;
- curr_err_arbitration <= curr_err_arbitration;
- curr_err_noack_data <= curr_err_noack_data;
- curr_err_noack_address <= curr_err_noack_address;
- curr_err_general <= curr_err_general;
- curr_gen_start_req <= curr_gen_start_req;
- curr_gen_stop_req <= curr_gen_stop_req;
+ curr_state <= next_state;
+ curr_err_arbitration <= next_err_arbitration;
+ curr_err_noack_data <= next_err_noack_data;
+ curr_err_noack_address <= next_err_noack_address;
+ curr_err_general <= next_err_general;
+ curr_gen_start_req <= next_gen_start_req;
+ curr_gen_stop_req <= next_gen_stop_req;
end if;
end if;
end process set_regs;
M src/i2c/scl_generator.vhd => src/i2c/scl_generator.vhd +40 -15
@@ 23,43 23,62 @@ entity scl_generator is
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 req_change : std_logic;
-
signal scl_changing : std_logic;
- signal exp_scl : 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;
+ signal curr_scl_enable : std_logic := '0';
signal next_scl_enable : std_logic;
+
+ signal curr_requested_change : std_logic;
+ signal next_requested_change : 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;
- cannot_comply_o <= (scl_i xor (not curr_scl_enable)) and should_change;
+ scl_changing <= scl_rising_i or scl_falling_i;
- should_rise <= (gen_rising_i or gen_continuous_i) and not scl_i;
- should_fall <= (gen_falling_i or gen_continuous_i) and scl_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';
- -- requests a change of the SCL, not of SCL enable
- req_change <= '1' when (can_change and should_change) = '1' and next_stable_count /= 0 else '0';
+ next_scl <= scl_i;
- exp_scl <= '1' when should_rise = '1' and req_change = '1' else
- '0' when should_fall = '1' and req_change = '1' else
- not curr_scl_enable;
+ set_next_state: process (all) is
+ begin -- process set_next_state
+ next_state <= curr_state;
+ next_scl_enable <= curr_scl_enable;
- next_scl_enable <= not exp_scl;
-
- scl_changing <= scl_rising_i or scl_falling_i;
+ 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
@@ 71,9 90,15 @@ begin -- architecture a1
if rst_in = '0' then -- synchronous reset (active low)
curr_stable_count <= 0;
curr_scl_enable <= '0';
+ curr_requested_change <= '0';
+ curr_state <= OBSERVE;
+ curr_scl <= '1';
else
curr_stable_count <= next_stable_count;
curr_scl_enable <= next_scl_enable;
+ curr_requested_change <= next_requested_change;
+ curr_state <= next_state;
+ curr_scl <= next_scl;
end if;
end if;
end process set_regs;