@@ 0,0 1,308 @@
+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, 6, 8, 16, 32, 64, 128, 256);
+ DIVISORS_LOG2 : natural := 3;
+ CSN_PULSE_CYCLES : natural := 1
+ );
+
+ port (
+ -- IOs
+ sck_io : inout std_logic;
+ miso_io : inout std_logic;
+ mosi_io : inout std_logic;
+ csn_io : inout 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;
+ -- 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 : out 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 : out 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_serial_data : std_logic_vector(0 downto 0);
+ signal rx_serial_data : std_logic;
+
+ signal start_clock : 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_clock_rising : 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_ctrl_rst : 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;
+
+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 (
+ 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 => master_clock_rising,
+ 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,
+ 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 => 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,
+ clock_rising_o => master_clock_rising,
+ 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_io,
+ csn_i => csn_io,
+ 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
+ -- Parallel
+ data_i => tx_data_i,
+ data_o => rx_data_o,
+ -- Serial
+ sd_i => rx_serial_data,
+ sd_o => open);
+
+ tx_input_data <= rx_data_o(selected_size - 1);
+
+ 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);
+
+ master_connection : entity work.spi_multiplexor
+ port map (
+ en_i => master_en,
+ mosi_en_i => master_mosi_en,
+ miso_en_i => master_miso_en,
+ sck_en_i => master_sck_en,
+ csn_en_i => master_csn_en,
+ mosi_i => tx_serial_data(0),
+ miso_i => '0',
+ sck_i => master_sck,
+ csn_i => master_csn,
+ mosi_o => mosi_io,
+ miso_o => miso_io,
+ sck_o => sck_io,
+ csn_o => csn_io,
+ rx_valid_i => master_rx_valid,
+ rx_valid_o => rx_valid_o,
+ tx_ready_i => master_tx_ready,
+ tx_ready_o => tx_ready_o,
+ busy_i => master_busy,
+ busy_o => busy_o,
+ err_lost_rx_data_i => master_err_lost_rx_data,
+ err_lost_rx_data_o => err_lost_rx_data_o,
+ rst_in => master_ctrl_rst,
+ rst_on => ctrl_rst_n,
+ latch_tx_data_i => master_latch_new_tx_data,
+ latch_tx_data_o => latch_new_tx_data,
+ latch_sample_data_i => master_latch_sample_data,
+ latch_sample_data_o => latch_sample_data,
+ latch_change_data_i => master_latch_change_data,
+ latch_change_data_o => latch_change_data_out,
+ rx_serial_i => miso_io,
+ rx_serial_o => rx_serial_data);
+
+ slave_connection : entity work.spi_multiplexor
+ port map (
+ en_i => slave_en,
+ mosi_en_i => slave_mosi_en,
+ miso_en_i => slave_miso_en,
+ sck_en_i => slave_sck_en,
+ csn_en_i => slave_csn_en,
+ mosi_i => '0',
+ miso_i => tx_serial_data(0),
+ sck_i => '0',
+ csn_i => '0',
+ mosi_o => mosi_io,
+ miso_o => miso_io,
+ sck_o => sck_io,
+ csn_o => csn_io,
+ rx_valid_i => slave_rx_valid,
+ rx_valid_o => rx_valid_o,
+ tx_ready_i => slave_tx_ready,
+ tx_ready_o => tx_ready_o,
+ busy_i => slave_busy,
+ busy_o => busy_o,
+ err_lost_rx_data_i => slave_err_lost_rx_data,
+ err_lost_rx_data_o => err_lost_rx_data_o,
+ rst_in => slave_ctrl_rst,
+ rst_on => ctrl_rst_n,
+ latch_tx_data_i => slave_latch_new_tx_data,
+ latch_tx_data_o => latch_new_tx_data,
+ latch_sample_data_i => slave_latch_sample_data,
+ latch_sample_data_o => latch_sample_data,
+ latch_change_data_i => slave_latch_change_data,
+ latch_change_data_o => latch_change_data_out,
+ rx_serial_i => mosi_io,
+ rx_serial_o => rx_serial_data);
+
+end architecture a1;