From 68fab355c8db62ec484c95d0e90f2ac6de035ed8 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Thu, 28 Dec 2023 15:38:57 +0100 Subject: [PATCH] feat: add i2c misc entities --- src/i2c/address_detector.vhd | 87 ++++++++++++++++++++++++ src/i2c/startstop_condition_detector.vhd | 41 +++++++++++ 2 files changed, 128 insertions(+) create mode 100644 src/i2c/address_detector.vhd create mode 100644 src/i2c/startstop_condition_detector.vhd diff --git a/src/i2c/address_detector.vhd b/src/i2c/address_detector.vhd new file mode 100644 index 0000000..c960ca8 --- /dev/null +++ b/src/i2c/address_detector.vhd @@ -0,0 +1,87 @@ +library ieee; +use ieee.std_logic_1164.all; + +use work.i2c_pkg.all; + +entity address_detector is + + port ( + clk_i : in std_logic; -- Input clock + rst_in : in std_logic; -- Reset the detection + address_i : in std_logic_vector(6 downto 0); + scl_pulse_i : in std_logic; + sda_i : in std_logic; -- The data that could contain the address + start_i : in std_logic; -- When to start looking for the + -- address. Will clear success_o + rw_o : out std_logic; + success_o : out std_logic; -- Whether full address matches + fail_o : out std_logic); -- Whether matching failed. Will stay 0 + -- as long as bits are matching. Will + -- be set to 1 the first bit that does + -- not match the address + +end entity address_detector; + +architecture a1 of address_detector is + type state_t is (IDLE, CHECKING_START, CHECKING, MATCH, FAIL); + signal curr_state : state_t; + signal next_state : state_t; + + signal curr_index : natural range 0 to 7; + signal next_index : natural range 0 to 7; + + signal curr_read_rw : std_logic; + signal next_read_rw : std_logic; + + signal mismatch : std_logic; +begin -- architecture a1 + + fail_o <= '1' when curr_state = FAIL else '0'; + success_o <= '1' when curr_state = MATCH else '0'; + rw_o <= curr_read_rw when curr_state = MATCH else '0'; + + next_read_rw <= sda_i when scl_pulse_i = '1' and curr_index = 7 else + curr_read_rw; + + next_index <= (curr_index + 1) when curr_state = CHECKING and scl_pulse_i = '1' and curr_index < 7 else + 0; + + mismatch <= '1' when address_i(6 - curr_index) /= sda_i and curr_index <= 6 and scl_pulse_i = '1' else '0'; + + set_next_state: process (start_i, curr_state, mismatch, scl_pulse_i) is + begin -- process set_next_state + next_state <= curr_state; + + if curr_state = CHECKING_START then + next_state <= CHECKING; + end if; + + if curr_state = CHECKING then + if mismatch = '1' then + next_state <= FAIL; + elsif curr_index = 7 and scl_pulse_i = '1' then + next_state <= MATCH; + end if; + end if; + + if start_i = '1' then + next_state <= CHECKING_START; + end if; + end process set_next_state; + + set_regs: process (clk_i) is + begin -- process set_regs + if rising_edge(clk_i) then -- rising clock edge + if rst_in = '0' then -- synchronous reset (active low) + curr_state <= IDLE; + curr_index <= 0; + curr_read_rw <= '0'; + else + curr_state <= next_state; + curr_index <= next_index; + curr_read_rw <= next_read_rw; + end if; + end if; + end process set_regs; + +end architecture a1; diff --git a/src/i2c/startstop_condition_detector.vhd b/src/i2c/startstop_condition_detector.vhd new file mode 100644 index 0000000..1c18cbf --- /dev/null +++ b/src/i2c/startstop_condition_detector.vhd @@ -0,0 +1,41 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity startstop_condition_detector is + + port ( + clk_i : in std_logic; + sda_i : in std_logic; + scl_i : in std_logic; + start_o : out std_logic; + stop_o : out std_logic); + +end entity startstop_condition_detector; + +architecture a1 of startstop_condition_detector is + signal reg_start, reg_stop : std_logic; + signal next_start, next_stop : std_logic; + + signal reg_prev_sda : std_logic; + signal next_prev_sda : std_logic; +begin -- architecture a1 + + next_prev_sda <= sda_i; + + next_start <= '0' when reg_start = '1' else + '1' when reg_prev_sda = '0' and sda_i = '1' and scl_i = '1' else + '0'; + next_stop <= '0' when reg_stop = '1' else + '1' when reg_prev_sda = '1' and sda_i = '0' and scl_i = '1' else + '0'; + + set_next: process (clk_i) is + begin -- process set_next + if rising_edge(clk_i) then -- rising clock edge + reg_prev_sda <= next_prev_sda; + reg_start <= next_start; + reg_stop <= next_stop; + end if; + end process set_next; + +end architecture a1; -- 2.49.0