library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.spi_pkg.all; entity spi_masterslave is generic ( SIZES : natural_vector := (8, 16); SIZES_2LOG : natural := 1; DIVISORS : natural_vector := (2, 4, 8, 16, 32, 64, 128, 256); DIVISORS_LOG2 : natural := 3; CSN_PULSE_CYCLES : natural := 1 ); port ( -- IOs sck_i : in std_logic; miso_i : in std_logic; mosi_i : in std_logic; csn_i : in std_logic; sck_o : out std_logic; miso_o : out std_logic; mosi_o : out std_logic; csn_o : out std_logic; sck_t : out std_logic; miso_t : out std_logic; mosi_t : out std_logic; csn_t : out std_logic; -- Control clk_i : in std_logic; rst_in : in std_logic; en_i : in std_logic; master_i : in std_logic; clock_polarity_i : in std_logic; clock_phase_i : in std_logic; size_sel_i : in std_logic_vector(SIZES_2LOG - 1 downto 0); div_sel_i : in std_logic_vector(DIVISORS_LOG2 - 1 downto 0); pulse_csn_i : in std_logic; rx_block_on_full_i : in std_logic; lsbfirst_i : in std_logic; -- Data -- Rx rx_en_i : in std_logic; rx_data_o : out std_logic_vector(get_max_natural(SIZES) - 1 downto 0); rx_valid_o : out std_logic; rx_ready_i : in std_logic; -- Tx tx_en_i : in std_logic; tx_data_i : in std_logic_vector(get_max_natural(SIZES) - 1 downto 0); tx_valid_i : in std_logic; tx_ready_o : out std_logic; -- State busy_o : out std_logic; err_lost_rx_data_o : out std_logic; clear_lost_rx_data_i : in std_logic); end entity spi_masterslave; architecture a1 of spi_masterslave is constant MAX_SIZE : natural := get_max_natural(SIZES); signal rst_n : std_logic; signal ctrl_rst_n : std_logic; signal master_ctrl_rst_n : std_logic; signal slave_ctrl_rst_n : std_logic; signal latch_sample_data : std_logic; signal latch_change_data_out : std_logic; signal latch_new_tx_data : std_logic; signal tx_input_data : std_logic; signal tx_input_index : natural range 0 to MAX_SIZE - 1; signal tx_serial_data : std_logic_vector(0 downto 0); signal rx_serial_data : std_logic; signal selected_size : natural; signal master_en : std_logic; signal slave_en : std_logic; signal slave_clock_rising : std_logic; signal slave_rx_valid : std_logic; signal slave_tx_ready : std_logic; signal slave_busy : std_logic; signal slave_err_lost_rx_data : std_logic; signal slave_ctrl_rst : std_logic; signal slave_csn_en : std_logic; signal slave_mosi_en : std_logic; signal slave_miso_en : std_logic; signal slave_sck_mask : std_logic; signal slave_sck_en : std_logic; signal slave_start_clock : std_logic; signal slave_latch_new_tx_data : std_logic; signal slave_latch_sample_data : std_logic; signal slave_latch_change_data : std_logic; signal master_sck : std_logic; signal master_counter_overflow : std_logic; signal master_rx_valid : std_logic; signal master_tx_ready : std_logic; signal master_busy : std_logic; signal master_err_lost_rx_data : std_logic; signal master_csn : std_logic; signal master_csn_en : std_logic; signal master_mosi_en : std_logic; signal master_miso_en : std_logic; signal master_sck_mask : std_logic; signal master_sck_en : std_logic; signal master_start_clock : std_logic; signal master_latch_new_tx_data : std_logic; signal master_latch_sample_data : std_logic; signal master_latch_change_data : std_logic; signal csn, sck, mosi, miso : std_logic; signal csn_en, sck_en, mosi_en, miso_en : std_logic; begin -- architecture a1 master_en <= en_i and master_i; slave_en <= en_i and not master_i; rst_n <= rst_in and ctrl_rst_n; selected_size <= SIZES(to_integer(unsigned(size_sel_i))); master_ctrl : entity work.spi_master_ctrl generic map ( DIVISORS => DIVISORS, DIVISORS_LOG2 => DIVISORS_LOG2, SIZES => SIZES, SIZES_2LOG => SIZES_2LOG, CSN_PULSE_CYCLES => CSN_PULSE_CYCLES) port map ( clk_i => clk_i, rst_in => rst_in, en_i => master_en, size_sel_i => size_sel_i, div_sel_i => div_sel_i, pulse_csn_i => pulse_csn_i, clock_phase_i => clock_phase_i, rx_block_on_full_i => rx_block_on_full_i, rx_en_i => rx_en_i, rx_ready_i => rx_ready_i, tx_en_i => tx_en_i, tx_valid_i => tx_valid_i, clear_lost_rx_data_i => clear_lost_rx_data_i, counter_overflow_i => master_counter_overflow, rx_valid_o => master_rx_valid, tx_ready_o => master_tx_ready, busy_o => master_busy, err_lost_rx_data_o => master_err_lost_rx_data, rst_on => master_ctrl_rst_n, csn_o => master_csn, csn_en_o => master_csn_en, mosi_en_o => master_mosi_en, miso_en_o => master_miso_en, sck_mask_o => master_sck_mask, sck_en_o => master_sck_en, gen_clk_en_o => master_start_clock, latch_tx_data_o => master_latch_new_tx_data); slave_ctrl : entity work.spi_slave_ctrl generic map ( SIZES => SIZES, SIZES_2LOG => SIZES_2LOG, CSN_PULSE_CYCLES => CSN_PULSE_CYCLES) port map ( clk_i => clk_i, rst_in => rst_in, en_i => master_en, size_sel_i => size_sel_i, pulse_csn_i => pulse_csn_i, rx_block_on_full_i => rx_block_on_full_i, rx_en_i => rx_en_i, rx_ready_i => rx_ready_i, tx_en_i => tx_en_i, tx_valid_i => tx_valid_i, clear_lost_rx_data_i => clear_lost_rx_data_i, clock_rising_i => slave_clock_rising, rx_valid_o => slave_rx_valid, tx_ready_o => slave_tx_ready, busy_o => slave_busy, err_lost_rx_data_o => slave_err_lost_rx_data, rst_on => slave_ctrl_rst, csn_en_o => slave_csn_en, mosi_en_o => slave_mosi_en, miso_en_o => slave_miso_en, sck_mask_o => slave_sck_mask, sck_en_o => slave_sck_en, gen_clk_en_o => slave_start_clock, latch_tx_data_o => slave_latch_new_tx_data); clkgen : entity work.spi_clkgen generic map ( DIVISORS => DIVISORS, DIVISORS_LOG2 => DIVISORS_LOG2) port map ( clk_i => clk_i, rst_in => master_ctrl_rst_n, start_i => master_start_clock, div_sel_i => div_sel_i, clock_polarity_i => clock_polarity_i, clock_phase_i => clock_phase_i, sck_o => master_sck, sck_mask_i => master_sck_mask, counter_overflow_o => master_counter_overflow, sample_data_o => master_latch_sample_data, change_data_o => master_latch_change_data); clkmon : entity work.spi_clkmon port map ( clk_i => clk_i, rst_in => slave_ctrl_rst_n, clock_polarity_i => clock_polarity_i, clock_phase_i => clock_phase_i, sck_i => sck_i, csn_i => csn_i, clock_rising_o => slave_clock_rising, sample_data_o => slave_latch_sample_data, change_data_o => slave_latch_change_data); shift_register : entity work.shift_register generic map ( SIZE => MAX_SIZE) port map ( clk_i => clk_i, rst_in => rst_n, -- Control shift_i => latch_sample_data, -- sampling latch_i => latch_new_tx_data, -- latching tx data lsbfirst_i => lsbfirst_i, -- Parallel data_i => tx_data_i, data_o => rx_data_o, -- Serial sd_i => rx_serial_data, sd_o => open); tx_input_index <= 0 when selected_size = 0 else selected_size - 1 when lsbfirst_i = '0' else 0; tx_input_data <= tx_data_i(tx_input_index) when latch_new_tx_data = '1' and latch_change_data_out = '1' else rx_data_o(tx_input_index); mosi_reg : entity work.reg generic map ( SIZE => 1) port map ( -- outputting different bit on mosi clk_i => clk_i, rst_in => rst_n, d_i => (0 => tx_input_data), q_o => tx_serial_data, latch_i => latch_change_data_out); mosi_t <= not slave_mosi_en when slave_en = '1' else not master_mosi_en when master_en = '1' else '0'; miso_t <= not slave_miso_en when slave_en = '1' else not master_miso_en when master_en = '1' else '0'; sck_t <= not slave_sck_en when slave_en = '1' else not master_sck_en when master_en = '1' else '0'; csn_t <= not slave_csn_en when slave_en = '1' else not master_csn_en when master_en = '1' else '0'; mosi_o <= tx_serial_data(0) when master_en = '1' else '0' when slave_en = '1' else '0'; miso_o <= '0' when master_en = '1' else tx_serial_data(0) when slave_en = '1' else '0'; sck_o <= master_sck when master_en = '1' else '0'; csn_o <= master_csn when master_en = '1' else '0'; rx_valid_o <= master_rx_valid when master_en = '1' else slave_rx_valid when slave_en = '1' else '0'; tx_ready_o <= master_tx_ready when master_en = '1' else slave_tx_ready when slave_en = '1' else '0'; busy_o <= master_busy when master_en = '1' else slave_busy when slave_en = '1' else '0'; err_lost_rx_data_o <= master_err_lost_rx_data when master_en = '1' else slave_err_lost_rx_data when slave_en = '1' else '0'; ctrl_rst_n <= master_ctrl_rst_n when master_en = '1' else slave_ctrl_rst_n when slave_en = '1' else '0'; latch_new_tx_data <= master_latch_new_tx_data when master_en = '1' else slave_latch_new_tx_data when slave_en = '1' else '0'; rx_serial_data <= miso_i when master_en = '1' else mosi_i when slave_en = '1' else '0'; latch_sample_data <= master_latch_sample_data when master_en = '1' else slave_latch_sample_data when slave_en = '1' else '0'; latch_change_data_out <= master_latch_change_data when master_en = '1' else slave_latch_change_data when slave_en = '1' else '0'; end architecture a1;