From 7f5a4fbbfa5998c60ef986d6aee724076cf16df8 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Fri, 5 Jan 2024 10:03:28 +0100 Subject: [PATCH] fix: issues in master logic --- src/i2c/master.vhd | 3 +++ src/i2c/master_state.vhd | 24 +++++++++++++++++------ src/i2c/startstop_condition_generator.vhd | 17 +++++++++++++++- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/i2c/master.vhd b/src/i2c/master.vhd index 7b34751a6d456e3a8e1dc948fe9e0df79ed2be02..38ae08650afbdbac2068687c0868340edfb96dbf 100644 --- a/src/i2c/master.vhd +++ b/src/i2c/master.vhd @@ -80,6 +80,7 @@ architecture a1 of master is signal cond_gen_req_scl_fall : std_logic; signal cond_gen_req_scl_rise : std_logic; signal cond_gen_done : std_logic; + signal cond_gen_early : std_logic; signal scl_gen_scl_enable : std_logic; signal scl_gen_req_continuous : std_logic; @@ -161,6 +162,7 @@ begin -- architecture a1 gen_stop_i => cond_gen_stop, req_scl_fall_o => cond_gen_req_scl_fall, req_scl_rise_o => cond_gen_req_scl_rise, + early_condition_o => cond_gen_early, done_o => cond_gen_done); scl_generator : entity work.scl_generator @@ -248,6 +250,7 @@ begin -- architecture a1 noack_data_i => tx_noack, unexpected_sda_address_i => adr_unexpected_sda, unexpected_sda_data_i => tx_unexpected_sda, + condition_early_i => cond_gen_early, -- err_noack_address_o => err_noack_address_o, err_noack_data_o => err_noack_data_o, diff --git a/src/i2c/master_state.vhd b/src/i2c/master_state.vhd index 97b25212f7e5b6851ec7d0fdd81c7bfa69a3e8ea..f16c8a7a39172fb4e26b8a11c5c5cb40617df0d8 100644 --- a/src/i2c/master_state.vhd +++ b/src/i2c/master_state.vhd @@ -18,6 +18,7 @@ entity master_state is noack_data_i : in std_logic; unexpected_sda_address_i : in std_logic; unexpected_sda_data_i : in std_logic; + condition_early_i : in std_logic; -- error outputs (reset on new run) err_noack_address_o : out std_logic; err_noack_data_o : out std_logic; @@ -86,17 +87,19 @@ architecture a1 of master_state is signal any_err, any_terminal_err : std_logic; signal control_over_bus : std_logic; signal can_gen_cond : std_logic; + signal cond_gen : std_logic; begin -- architecture a1 any_err <= curr_err_arbitration or curr_err_noack_data or curr_err_noack_address or curr_err_general; any_terminal_err <= curr_err_noack_data or curr_err_noack_address or curr_err_general; control_over_bus <= '1' when curr_state /= IDLE and curr_state /= BUS_BUSY; - can_gen_cond <= '1' when curr_state = IDLE or waiting_for_data_i = '1' or tx_done_i = '1' or rx_done_i = '1' else '0'; + can_gen_cond <= '1' when curr_state = IDLE or ((curr_state = TRANSMITTING or curr_state = RECEIVING) and (waiting_for_data_i = '1' or tx_done_i = '1' or rx_done_i = '1')) else '0'; req_scl_continuous_o <= '1' when curr_state = GENERATING_ADDRESS or curr_state = TRANSMITTING or curr_state = RECEIVING else '0'; req_start_o <= '1' when curr_state = GENERATING_START or curr_state = GENERATED_START else '0'; req_stop_o <= '1' when curr_state = GENERATING_STOP or curr_state = GENERATED_STOP else '0'; + cond_gen_o <= cond_gen; address_gen_start_o <= '1' when curr_state = GENERATED_START and next_state = GENERATING_ADDRESS else '0'; @@ -110,11 +113,11 @@ begin -- architecture a1 err_arbitration_o <= curr_err_arbitration; err_general_o <= curr_err_general; - cond_gen_o <= '1' when + cond_gen <= '1' when curr_state = GENERATING_STOP or curr_state = GENERATED_STOP or curr_state = GENERATING_START or curr_state = GENERATED_START else '0'; - rst_i2c_o <= any_err; + rst_i2c_o <= any_err or cond_gen; next_gen_start_req <= '1' when start_i = '1' and run_i = '1' else '0' when curr_state = GENERATING_START else @@ -124,7 +127,7 @@ begin -- architecture a1 '0' when curr_state = GENERATING_STOP else curr_gen_stop_req; - next_err_general <= '0' when start_condition_i = '1' else + next_err_general <= '0' when curr_state = GENERATING_START else '1' when curr_err_general = '1' else '1' when curr_state = GENERATING_STOP and start_condition_i = '1' else '1' when curr_state = GENERATING_START and stop_condition_i = '1' else @@ -137,6 +140,7 @@ begin -- architecture a1 '1' when curr_err_arbitration = '1' else '1' when unexpected_sda_data_i = '1' and curr_state = TRANSMITTING else '1' when unexpected_sda_address_i = '1' and curr_state = GENERATING_ADDRESS else + '1' when condition_early_i = '1' and curr_state = GENERATED_START else '0'; next_err_noack_data <= '0' when start_condition_i = '1' else @@ -146,7 +150,7 @@ begin -- architecture a1 next_err_noack_address <= '0' when start_condition_i = '1' else '1' when curr_err_noack_address = '1' else - '1' when noack_address_i = '1' and curr_state = TRANSMITTING and expect_ack_i = '1' else + '1' when noack_address_i = '1' and curr_state = GENERATING_ADDRESS and expect_ack_i = '1' else '0'; set_next_state: process (all) is @@ -170,6 +174,8 @@ begin -- architecture a1 next_state <= GENERATING_STOP; elsif req_cond_done_i = '1' then next_state <= GENERATING_ADDRESS; + elsif condition_early_i = '1' then + next_state <= IDLE; end if; elsif curr_state = GENERATING_ADDRESS then if any_terminal_err = '1' then @@ -193,7 +199,7 @@ begin -- architecture a1 end if; elsif curr_state = GENERATING_STOP then if stop_condition_i = '1' then - next_state <= GENERATING_STOP; + next_state <= GENERATED_STOP; elsif req_cond_done_i = '1' then -- done before cond generated? -- That's not right... @@ -202,6 +208,8 @@ begin -- architecture a1 elsif curr_state = GENERATED_STOP then if req_cond_done_i = '1' then next_state <= IDLE; + elsif condition_early_i = '1' then + next_state <= IDLE; end if; elsif curr_state = ERR then -- not much to do @@ -220,6 +228,10 @@ begin -- architecture a1 next_state <= GENERATING_STOP; end if; end if; + + if curr_err_arbitration = '1' then + next_state <= IDLE; + end if; end process set_next_state; set_regs: process (clk_i) is diff --git a/src/i2c/startstop_condition_generator.vhd b/src/i2c/startstop_condition_generator.vhd index 212c81d1781b2dffaaa43ace3673547163dd5091..e929bbf89b816ccf77ed5961c2843dfda60c5bc8 100644 --- a/src/i2c/startstop_condition_generator.vhd +++ b/src/i2c/startstop_condition_generator.vhd @@ -27,6 +27,8 @@ entity startstop_condition_generator is req_scl_fall_o : out std_logic; req_scl_rise_o : out std_logic; + early_condition_o : out std_logic; + done_o : out std_logic); end entity startstop_condition_generator; @@ -39,7 +41,7 @@ architecture a1 of startstop_condition_generator is -- and take it from another entity instead, without communicating the current -- level.), -- 5. done! - type state_t is (IDLE, PREREQ_SCL_FALL, PREPARE_SDA, REQ_SCL_RISE, GEN_COND, REQ_SCL_FALL, DONE); + type state_t is (IDLE, PREREQ_SCL_FALL, PREPARE_SDA, REQ_SCL_RISE, GEN_COND, REQ_SCL_FALL, EARLY_COND, DONE); signal curr_state : state_t := IDLE; signal next_state : state_t; @@ -61,6 +63,7 @@ begin -- architecture a1 'X'; done_o <= '1' when curr_state = DONE else '0'; + early_condition_o <= '1' when curr_state = EARLY_COND else '0'; req_scl_rise_o <= '1' when curr_state = REQ_SCL_RISE else '0'; req_scl_fall_o <= '1' when curr_state = REQ_SCL_FALL or curr_state = PREREQ_SCL_FALL else '0'; @@ -110,6 +113,7 @@ begin -- architecture a1 -- cannot do anything :( elsif curr_count = DELAY then next_state <= REQ_SCL_RISE; + next_count_en <= '0'; elsif curr_scl = '1' then next_state <= GEN_COND; next_count_en <= '0'; @@ -146,6 +150,17 @@ begin -- architecture a1 if any_request = '0' then next_state <= IDLE; end if; + elsif curr_state = EARLY_COND then + next_count_en <= '0'; + if any_request = '0' then + next_state <= IDLE; + end if; + end if; + + if start_condition_i = '1' or stop_condition_i = '1' then + if curr_state = PREREQ_SCL_FALL or curr_state = PREPARE_SDA or curr_state = REQ_SCL_RISE then + next_state <= EARLY_COND; + end if; end if; end process set_next_state;