From db21902791769b9c46f054a1923b33ca0f64d1b8 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Wed, 3 Jan 2024 21:52:19 +0100 Subject: [PATCH] feat: add master top entity --- src/i2c/master.vhd | 278 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 src/i2c/master.vhd diff --git a/src/i2c/master.vhd b/src/i2c/master.vhd new file mode 100644 index 0000000..a17809b --- /dev/null +++ b/src/i2c/master.vhd @@ -0,0 +1,278 @@ +library ieee; +use ieee.std_logic_1164.all; + +library utils; + +entity master is + generic ( + SCL_FALLING_DELAY : natural := 5); + + port ( + clk_i : in std_logic; -- Synchronous clock + rst_in : in std_logic; -- Synchronous reset (active low) + -- address + slave_address_i : in std_logic_vector(6 downto 0); -- Address of the + -- ack control + generate_ack_i : in std_logic; + expect_ack_i : in std_logic; + -- rx + 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; + err_noack_address_o : out std_logic; + err_arbitration_o : out std_logic; + err_general_o : out std_logic; + -- state + stop_i : in std_logic; + start_i : in std_logic; + run_i : in std_logic; + rw_o : out std_logic; -- 1 - read, 0 - write + dev_busy_o : out std_logic; -- Communicating with master + bus_busy_o : out std_logic; -- Bus is busy, someone else is communicating + waiting_o : out std_logic; -- Waiting for data or read data + + -- i2c + sda_i : in std_logic; -- I2C SDA line + scl_i : in std_logic; -- I2C SCL line + sda_enable_o : out std_logic; -- Pull down sda + scl_enable_o : out std_logic); -- Pull down scl + +end entity master; + +architecture a1 of master is + signal sync_sda, sync_scl : std_logic; + signal start_condition, stop_condition : std_logic; + signal scl_rising, scl_falling : std_logic; + + signal transmitting, receiving : std_logic; + + signal tx_sda_enable : std_logic; + signal tx_scl_stretch : std_logic; + signal tx_noack, tx_unexpected_sda : std_logic; + signal tx_done : std_logic; + + signal rx_sda_enable : std_logic; + signal rx_scl_stretch : std_logic; + signal rx_done : std_logic; + + signal bus_busy : std_logic; + + signal adr_gen : std_logic; + signal adr_sda_enable : std_logic; + signal adr_noack : std_logic; + signal adr_unexpected_sda : std_logic; + signal adr_done : std_logic; + signal adr_gen_start : std_logic; + + signal cond_gen : std_logic; + signal cond_gen_sda_enable : std_logic; + signal cond_gen_start : std_logic; + signal cond_gen_stop : std_logic; + signal cond_gen_req_scl_fall : std_logic; + signal cond_gen_req_scl_rise : std_logic; + signal cond_gen_done : std_logic; + + signal scl_gen_scl_enable : std_logic; + signal scl_gen_req_continuous : std_logic; + + signal rw : std_logic; + signal rst_i2c : std_logic; + + signal scl_falling_delayed : std_logic; + signal waiting_for_data : std_logic; +begin -- architecture a1 + rw_o <= rw; + dev_busy_o <= transmitting or receiving; + bus_busy_o <= bus_busy; + 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; + + sda_enable_o <= tx_sda_enable when transmitting = '1' else + rx_sda_enable when receiving = '1' else + cond_gen_sda_enable when cond_gen = '1' else + adr_sda_enable when adr_gen = '1' else + '0'; + + scl_falling_delayer: entity utils.delay + generic map ( + DELAY => SCL_FALLING_DELAY) + port map ( + clk_i => clk_i, + rst_in => rst_in, + signal_i => scl_falling, + signal_o => scl_falling_delayed); + + scl_edge_detector: entity utils.sync_edge_detector + port map ( + clk_i => clk_i, + signal_i => sync_scl, + rising_edge_o => scl_rising, + falling_edge_o => scl_falling); + + sda_sync: entity utils.metastability_filter + port map ( + clk_i => clk_i, + signal_i => sda_i, + signal_o => sync_sda); + + scl_sync: entity utils.metastability_filter + port map ( + clk_i => clk_i, + signal_i => scl_i, + signal_o => sync_scl); + + condition_detector: entity work.startstop_condition_detector + port map ( + clk_i => clk_i, + sda_i => sync_sda, + scl_i => sync_scl, + start_o => start_condition, + stop_o => stop_condition); + + condition_generator : entity work.startstop_condition_generator + generic map ( + DELAY => SCL_FALLING_DELAY) + port map ( + clk_i => clk_i, + rst_in => rst_in, + sda_i => sda_i, + scl_rising_i => scl_rising, + scl_falling_i => scl_falling, + scl_falling_delayed_i => scl_falling_delayed, + sda_enable_o => cond_gen_sda_enable, + start_condition_i => start_condition, + stop_condition_i => stop_condition, + gen_start_i => cond_gen_start, + gen_stop_i => cond_gen_stop, + req_scl_fall_o => cond_gen_req_scl_fall, + req_scl_rise_o => cond_gen_req_scl_rise, + done_o => cond_gen_done); + + scl_generator : entity work.scl_generator + generic map ( + MIN_STABLE_CYCLES => SCL_FALLING_DELAY) + port map ( + clk_i => clk_i, + rst_in => rst_in, + scl_i => scl_i, + scl_rising_i => scl_rising, + 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, + scl_enable_o => scl_gen_scl_enable, + cannot_comply_o => open); + + -- rx + rx : entity work.rx + port map ( + clk_i => clk_i, + rst_in => rst_in, + start_read_i => receiving, + generate_ack_i => generate_ack_i, + rst_i2c_i => rst_i2c, + scl_rising => scl_rising, + scl_falling_delayed_i => scl_falling_delayed, + scl_stretch_o => rx_scl_stretch, + sda_i => sda_i, + sda_enable_o => rx_sda_enable, + read_valid_o => rx_valid_o, + read_ready_o => open, + read_data_o => rx_data_o, + done_o => rx_done, + confirm_read_i => rx_confirm_i); + + -- tx + tx : entity work.tx + port map ( + clk_i => clk_i, + rst_in => rst_in, + clear_buffer_i => tx_clear_buffer_i, + start_write_i => transmitting, + rst_i2c_i => rst_i2c, + scl_rising_i => scl_rising, + scl_falling_delayed_i => scl_falling_delayed, + scl_stretch_o => tx_scl_stretch, + sda_i => sda_i, + sda_enable_o => tx_sda_enable, + unexpected_sda_o => tx_unexpected_sda, + noack_o => tx_noack, + ready_o => tx_ready_o, + valid_i => tx_valid_i, + done_o => tx_done, + write_data_i => tx_data_i); + + address_generator : entity work.address_generator + port map ( + clk_i => clk_i, + rst_in => rst_in, + address_i => slave_address_i, + scl_rising_i => scl_rising, + scl_falling_delayed_i => scl_falling_delayed, + sda_enable_o => adr_sda_enable, + sda_i => sync_sda, + noack_o => adr_noack, + unexpected_sda_o => adr_unexpected_sda, + done_o => adr_done, + start_i => adr_gen_start, + rw_i => rw); + + state_machine : entity work.master_state + port map ( + clk_i => clk_i, + rst_in => rst_in, + rst_i2c_o => rst_i2c, +-- + start_i => start_i, + stop_i => stop_i, + run_i => run_i, + rw_i => rw, +-- + expect_ack_i => expect_ack_i, + noack_address_i => adr_noack, + noack_data_i => tx_noack, + unexpected_sda_address_i => adr_unexpected_sda, + unexpected_sda_data_i => tx_unexpected_sda, +-- + err_noack_address_o => err_noack_address_o, + err_noack_data_o => err_noack_data_o, + err_arbitration_o => err_arbitration_o, + err_general_o => err_general_o, +-- + start_condition_i => start_condition, + stop_condition_i => stop_condition, +-- + waiting_for_data_i => waiting_for_data, + rx_done_i => rx_done, + tx_done_i => tx_done, +-- + address_gen_start_o => adr_gen_start, + address_gen_done_i => adr_done, +-- + req_start_o => cond_gen_start, + req_stop_o => cond_gen_stop, + req_cond_done_i => cond_gen_done, +-- + req_scl_continuous_o => scl_gen_req_continuous, +-- + cond_gen_o => cond_gen, + address_gen_o => adr_gen, + receive_o => receiving, + transmit_o => transmitting, + bus_busy_o => bus_busy); + +end architecture a1; -- 2.48.1