From 15eb81c6daee1b663491ca1f7f4ecc1d464f2b0c Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sat, 30 Dec 2023 19:19:36 +0100 Subject: [PATCH] feat: add counter and register testing slave top levels --- src/mcu_slave/counter.vhd | 101 ++++++++++++++++++++++++++++ src/mcu_slave/regs.vhd | 136 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 src/mcu_slave/counter.vhd create mode 100644 src/mcu_slave/regs.vhd diff --git a/src/mcu_slave/counter.vhd b/src/mcu_slave/counter.vhd new file mode 100644 index 0000000..372e8ba --- /dev/null +++ b/src/mcu_slave/counter.vhd @@ -0,0 +1,101 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library utils; +library i2c; + +entity counter is + + generic ( + MAX : integer := 100); + + port ( + clk_i : in std_logic; + rst_i : in std_logic; + err_noack_o : out std_logic; + bus_busy_o : out std_logic; + dev_busy_o : out std_logic; + sda_io : inout std_logic; + scl_io : inout std_logic); + +end entity counter; + +architecture a1 of counter is + constant ADDRESS : std_logic_vector(6 downto 0) := "1110100"; + signal curr_count : unsigned(7 downto 0); + signal next_count : unsigned(7 downto 0); + + signal go_next : std_logic; + + signal rst_n : std_logic; + + signal sda, scl : std_logic; + signal sda_enable, scl_enable : std_logic; + + signal tx_valid, tx_ready : std_logic; + signal tx_data : std_logic_vector(7 downto 0); +begin + rst_n <= not rst_i; + + next_count <= (curr_count + 1) mod MAX when go_next = '1' else + curr_count; + + go_next <= tx_ready; + + tx_valid <= tx_ready; + tx_data <= std_logic_vector(curr_count); + + uut: entity i2c.slave + generic map ( + SCL_FALLING_DELAY => 1) + port map ( + clk_i => clk_i, + rst_in => rst_n, + address_i => ADDRESS, + generate_ack_i => '1', + expect_ack_i => '1', + + rx_valid_o => open, + rx_data_o => open, + rx_confirm_i => '1', + rx_stretch_i => '0', + + tx_ready_o => tx_ready, + tx_valid_i => tx_valid, + tx_data_i => tx_data, + tx_stretch_i => '0', + tx_clear_buffer_i => '0', + + err_noack_o => err_noack_o, + rw_o => open, + dev_busy_o => dev_busy_o, + bus_busy_o => bus_busy_o, + sda_i => sda, + scl_i => scl, + sda_enable_o => sda_enable, + scl_enable_o => scl_enable); + + sda_open_buffer: entity utils.open_drain_buffer + port map ( + pad_io => sda_io, + enable_i => sda_enable, + state_o => sda); + scl_open_buffer: entity utils.open_drain_buffer + port map ( + pad_io => scl_io, + enable_i => scl_enable, + state_o => scl); + + set_regs: process (clk_i) is + begin -- process set_regs + if rising_edge(clk_i) then -- rising clock edge + if rst_n = '0' then -- synchronous reset (active low) + curr_count <= "00000000"; + else + curr_count <= next_count; + end if; + end if; + end process set_regs; + +end architecture a1; diff --git a/src/mcu_slave/regs.vhd b/src/mcu_slave/regs.vhd new file mode 100644 index 0000000..9a8a009 --- /dev/null +++ b/src/mcu_slave/regs.vhd @@ -0,0 +1,136 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library utils; +library i2c; + +entity regs is + + generic ( + MAX : integer := 100); + + port ( + clk_i : in std_logic; + rst_i : in std_logic; + err_noack_o : out std_logic; + bus_busy_o : out std_logic; + dev_busy_o : out std_logic; + sda_io : inout std_logic; + scl_io : inout std_logic); + +end entity regs; + +architecture a1 of regs is + constant ADDRESS : std_logic_vector(6 downto 0) := "1110101"; + + constant REGS_COUNT : integer := 20; + type regs_t is array (0 to REGS_COUNT - 1) of std_logic_vector(7 downto 0); + signal curr_regs : regs_t; + signal next_regs : regs_t; + + signal rst_n : std_logic; + + signal sda, scl : std_logic; + signal sda_enable, scl_enable : std_logic; + + signal tx_valid, tx_ready, tx_clear_buffer : std_logic; + signal tx_data : std_logic_vector(7 downto 0); + + signal rx_valid, rx_confirm : std_logic; + signal rx_data : std_logic_vector(7 downto 0); + + signal curr_reg_address_filled : std_logic; + signal next_reg_address_filled : std_logic; + + signal curr_reg_address : unsigned(7 downto 0); + signal next_reg_address : unsigned(7 downto 0); + + signal dev_busy : std_logic; + + signal curr_dev_busy : std_logic; + signal next_dev_busy : std_logic; + + signal rw : std_logic; +begin + rst_n <= not rst_i; + dev_busy_o <= dev_busy; + + next_dev_busy <= dev_busy; + + next_reg_address_filled <= '0' when curr_dev_busy = '0' and dev_busy = '1' and rw = '0' else + '1' when curr_reg_address_filled = '0' and rx_valid = '1' else + curr_reg_address_filled; + + rx_confirm <= rx_valid; + + next_reg_address <= unsigned(rx_data) when rx_valid = '1' and curr_reg_address_filled = '0' else + (curr_reg_address + 1) mod REGS_COUNT when rx_valid = '1' else + (curr_reg_address + 1) mod REGS_COUNT when tx_valid = '1' and dev_busy = '1' and rw = '1' else + curr_reg_address; + + tx_clear_buffer <= not curr_reg_address_filled; + tx_data <= curr_regs(to_integer(curr_reg_address)); + tx_valid <= '1' when tx_ready = '1' and dev_busy = '1' and rw = '1' else + '0'; + + set_next_regs: process (all) is + begin -- process set_next_regs + next_regs <= curr_regs; + + if rx_valid = '1' and curr_reg_address_filled = '1' then + next_regs(to_integer(curr_reg_address)) <= rx_data; + end if; + end process set_next_regs; + + uut: entity i2c.slave + generic map ( + SCL_FALLING_DELAY => 1) + port map ( + clk_i => clk_i, + rst_in => rst_n, + address_i => ADDRESS, + generate_ack_i => '1', + expect_ack_i => '1', + + rx_valid_o => rx_valid, + rx_data_o => rx_data, + rx_confirm_i => rx_confirm, + rx_stretch_i => '0', + + tx_ready_o => tx_ready, + tx_valid_i => tx_valid, + tx_data_i => tx_data, + tx_stretch_i => '0', + tx_clear_buffer_i => tx_clear_buffer, + + err_noack_o => err_noack_o, + rw_o => rw, + dev_busy_o => dev_busy, + bus_busy_o => bus_busy_o, + sda_i => sda, + scl_i => scl, + sda_enable_o => sda_enable, + scl_enable_o => scl_enable); + + sda_open_buffer: entity utils.open_drain_buffer + port map ( + pad_io => sda_io, + enable_i => sda_enable, + state_o => sda); + scl_open_buffer: entity utils.open_drain_buffer + port map ( + pad_io => scl_io, + enable_i => scl_enable, + state_o => scl); + + set_regs: process (clk_i) is + begin -- process set_regs + if rising_edge(clk_i) then -- rising clock edge + if rst_n = '0' then -- synchronous reset (active low) + else + end if; + end if; + end process set_regs; + +end architecture a1; -- 2.48.1