library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.spi_pkg.all; entity spi_master 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_o : out std_logic; miso_i : in std_logic; mosi_o : out std_logic; csn_o : out std_logic; -- Control clk_i : in std_logic; rst_in : in std_logic; en_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_master; architecture a1 of spi_master is constant MAX_SIZE : natural := get_max_natural(SIZES); signal rst_n : std_logic; signal ctrl_rst : std_logic; signal latch_sample_data : std_logic; signal clock_rising : std_logic; signal latch_change_data_out : std_logic; signal latch_new_tx_data : std_logic; signal tx_serial_data : std_logic; signal sck : std_logic; signal csn : std_logic; signal mosi : std_logic_vector(0 downto 0); signal start_clock : std_logic; signal sck_mask : std_logic; signal sck_en : std_logic; signal csn_en : std_logic; signal mosi_en : std_logic; signal miso_en : std_logic; signal selected_size : natural; begin -- architecture a1 rst_n <= rst_in and ctrl_rst; selected_size <= SIZES(to_integer(unsigned(size_sel_i))); 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 => en_i, size_sel_i => size_sel_i, pulse_csn_i => pulse_csn_i, clock_rising_i => clock_rising, rx_block_on_full_i => rx_block_on_full_i, rx_en_i => rx_en_i, rx_ready_i => rx_ready_i, rx_valid_o => rx_valid_o, tx_en_i => tx_en_i, tx_valid_i => tx_valid_i, tx_ready_o => tx_ready_o, busy_o => busy_o, err_lost_rx_data_o => err_lost_rx_data_o, clear_lost_rx_data_i => clear_lost_rx_data_i, rst_on => ctrl_rst, csn_o => csn, csn_en_o => csn_en, mosi_en_o => mosi_en, miso_en_o => miso_en, sck_mask_o => sck_mask, sck_en_o => sck_en, gen_clk_en_o => start_clock, latch_tx_data_o => 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 => 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 => sck, sck_mask_i => sck_mask, clock_rising_o => clock_rising, sample_data_o => latch_sample_data, change_data_o => latch_change_data_out); 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 => miso_i, sd_o => open); tx_serial_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_serial_data), q_o => mosi, latch_i => latch_change_data_out); sck_o <= sck when sck_en = '1' else 'Z'; mosi_o <= mosi(0) when mosi_en = '1' else 'Z'; csn_o <= csn when csn_en = '1' else 'Z'; end architecture a1;