From 6d75a001ae200cc54a782f8fa44ea84d79429bed Mon Sep 17 00:00:00 2001 From: Rutherther Date: Thu, 4 Jan 2024 22:25:07 +0100 Subject: [PATCH] fix: logic fixes master state --- src/i2c/address_detector.vhd | 2 -- src/i2c/address_generator.vhd | 2 -- src/i2c/master.vhd | 19 +++++++----- src/i2c/master_state.vhd | 26 +++++++---------- src/i2c/scl_generator.vhd | 55 +++++++++++++++++++++++++---------- 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/src/i2c/address_detector.vhd b/src/i2c/address_detector.vhd index e5ee03a..16855aa 100644 --- a/src/i2c/address_detector.vhd +++ b/src/i2c/address_detector.vhd @@ -1,8 +1,6 @@ library ieee; use ieee.std_logic_1164.all; -use work.i2c_pkg.all; - entity address_detector is port ( diff --git a/src/i2c/address_generator.vhd b/src/i2c/address_generator.vhd index 6add377..14b3df3 100644 --- a/src/i2c/address_generator.vhd +++ b/src/i2c/address_generator.vhd @@ -1,8 +1,6 @@ library ieee; use ieee.std_logic_1164.all; -use work.i2c_pkg.all; - entity address_generator is port ( diff --git a/src/i2c/master.vhd b/src/i2c/master.vhd index a17809b..beabd5c 100644 --- a/src/i2c/master.vhd +++ b/src/i2c/master.vhd @@ -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); diff --git a/src/i2c/master_state.vhd b/src/i2c/master_state.vhd index b9b380a..1a928ea 100644 --- a/src/i2c/master_state.vhd +++ b/src/i2c/master_state.vhd @@ -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; diff --git a/src/i2c/scl_generator.vhd b/src/i2c/scl_generator.vhd index 0414306..932f540 100644 --- a/src/i2c/scl_generator.vhd +++ b/src/i2c/scl_generator.vhd @@ -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; -- 2.49.0