~ruther/vhdl-i2c

7f5a4fbbfa5998c60ef986d6aee724076cf16df8 — Rutherther 1 year, 3 months ago cc661c4
fix: issues in master logic
3 files changed, 37 insertions(+), 7 deletions(-)

M src/i2c/master.vhd
M src/i2c/master_state.vhd
M src/i2c/startstop_condition_generator.vhd
M src/i2c/master.vhd => src/i2c/master.vhd +3 -0
@@ 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,

M src/i2c/master_state.vhd => src/i2c/master_state.vhd +18 -6
@@ 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

M src/i2c/startstop_condition_generator.vhd => src/i2c/startstop_condition_generator.vhd +16 -1
@@ 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;


Do not follow this link