library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.spi_pkg.all; entity spi_clkgen is generic ( DIVISORS : natural_vector := (2, 4, 6, 8, 16, 32, 64, 128, 256); DIVISORS_LOG2 : natural := 3 ); port ( clk_i : in std_logic; rst_in : in std_logic; start_i : in std_logic; div_sel_i : in std_logic_vector(DIVISORS_LOG2 - 1 downto 0); clock_polarity_i : in std_logic; clock_phase_i : in std_logic; sck_o : out std_logic; sck_mask_i : in std_logic; clock_rising_o : out std_logic; sample_data_o : out std_logic; change_data_o : out std_logic); end entity spi_clkgen; architecture a1 of spi_clkgen is constant MAX : natural := get_max_natural(DIVISORS); signal curr_running : std_logic; signal next_running : std_logic; signal selected_divisor : natural range 0 to MAX - 1 := 1; signal changing : std_logic; signal curr_counter : integer range 0 to MAX - 1; signal next_counter : integer range 0 to MAX - 1; signal curr_sck : std_logic; signal next_sck : std_logic; signal next_sample_data : std_logic; signal curr_sample_data : std_logic; signal next_change_data : std_logic; signal curr_change_data : std_logic; begin -- architecture a1 set_data: process (clk_i) is begin -- process set_data if rising_edge(clk_i) then -- rising clock edge if rst_in = '0' then -- synchronous reset (active low) curr_running <= '0'; curr_sck <= '0'; curr_counter <= 0; curr_sample_data <= '0'; curr_change_data <= '0'; else curr_running <= next_running; curr_sck <= next_sck; curr_counter <= next_counter; curr_sample_data <= next_sample_data; curr_change_data <= next_change_data; end if; end if; end process set_data; selected_divisor <= DIVISORS(to_integer(unsigned(div_sel_i))); changing <= '1' when curr_counter = 0 and curr_running = '1' else '0'; next_counter <= selected_divisor - 1 when changing = '1' else 0 when curr_counter = 0 else curr_counter - 1 when curr_running = '1' else selected_divisor - 1; next_sample_data <= '1' when curr_sck = clock_phase_i and changing = '1' else '0'; next_change_data <= '1' when curr_sck /= clock_phase_i and changing = '1' else '0'; next_sck <= not curr_sck when changing = '1' else curr_sck when curr_running = '1' else clock_polarity_i; next_running <= start_i; sck_o <= clock_polarity_i when sck_mask_i = '0' else curr_sck when clock_polarity_i = '0' else not curr_sck; clock_rising_o <= curr_sample_data; sample_data_o <= curr_sample_data and sck_mask_i; change_data_o <= curr_change_data and sck_mask_i; end architecture a1;