~ruther/vhdl-i2c

6d75a001ae200cc54a782f8fa44ea84d79429bed — Rutherther 1 year, 5 months ago a413309
fix: logic fixes master state
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;

Do not follow this link