Okay, you ain't going to like VHDL, but here is a solution based on a Johns on ring divider:
---------------------------------------------------------------------------
---------------------------------------------------------------------------
----------
-- File : wrapper_SPI_Master.vhd
-- Author : David Greig (email : snipped-for-privacy@ieee.org)
-- Revision :
-- Description :
---------------------------------------------------------------------------
---------------------------------------------
-- Notes :
--======================== ========================= ========================= ========================= ========================= ========================= =======-- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all;
--======================== ========================= ========================= ========================= ========================= ========================= =======-- entity wrapper_SPI_Master is port( arstn : in std_logic; clk : in std_logic; spi_rst_i : in std_logic; clken : in std_logic;
cpol_i : in std_logic; cpha_i : in std_logic;
spi_wr_i : in std_logic;-----------------------------------------------
---------------------------------------------------------------------------
--------------------------------------
-- File : wrapper_SPI_Master.vhd
-- Author : David Greig (email : snipped-for-privacy@ieee.org)
-- Revision :
-- Description :
---------------------------------------------------------------------------
---------------------------------------------
-- Notes :
--======================== ========================= ========================= ========================= ========================= ========================= =======-- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all;
--======================== ========================= ========================= ========================= ========================= ========================= =======-- entity wrapper_SPI_Master is port( arstn : in std_logic; clk : in std_logic; spi_rst_i : in std_logic; clken : in std_logic;
cpol_i : in std_logic; cpha_i : in std_logic;
spi_wr_i : in std_logic; spi_tx_data_i : in std_logic_vector(16-1 downto 0); spi_tx_empty_o : out std_logic; spi_tx_full_o : out std_logic; spi_tx_ovf_o : out std_logic; spi_tx_unf_o : out std_logic; spi_tx_done_o : out std_logic;
spi_rd_i : in std_logic; spi_rx_data_o : out std_logic_vector(16-1 downto 0); spi_rx_empty_o : out std_logic; spi_rx_full_o : out std_logic; spi_rx_ovf_o : out std_logic; spi_rx_unf_o : out std_logic;
sck_o : out std_logic; ssn_o : out std_logic; mosi_o : out std_logic; miso_i : in std_logic ); end entity wrapper_SPI_Master;
--======================== ========================= ========================= ========================= ========================= ========================= =======--
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~-- architecture rtl of wrapper_SPI_Master is
---------------------------------------------------------------------------
--------------------------------------------- component SPI_Master generic( Gram_pref : string; Gfifo_depth : natural; Gdwidth : natural; Gspi_clk_div : natural ); port( arstn : in std_logic; clk : in std_logic; spi_rst_i : in std_logic; clken : in std_logic;
cpol_i : in std_logic; cpha_i : in std_logic;
spi_wr_i : in std_logic; spi_tx_data_i : in std_logic_vector(Gdwidth-1 downto 0); spi_tx_empty_o : out std_logic; spi_tx_full_o : out std_logic; spi_tx_ovf_o : out std_logic; spi_tx_unf_o : out std_logic; spi_tx_done_o : out std_logic;
spi_rd_i : in std_logic; spi_rx_data_o : out std_logic_vector(Gdwidth-1 downto 0); spi_rx_empty_o : out std_logic; spi_rx_full_o : out std_logic; spi_rx_ovf_o : out std_logic; spi_rx_unf_o : out std_logic;
sck_o : out std_logic; ssn_o : out std_logic; mosi_o : out std_logic; miso_i : in std_logic ); end component SPI_Master;
---------------------------------------------------------------------------
--------------------------------------------- begin
---------------------------------------------------------------------------
--------------------------------------------- inst_SPI_Master : SPI_Master generic map( Gram_pref => "logic", Gfifo_depth => 2, Gdwidth => 16, Gspi_clk_div => 4 ) port map( arstn => arstn , clk => clk , spi_rst_i => spi_rst_i , clken => clken ,
cpol_i => cpol_i , cpha_i => cpha_i ,
spi_wr_i => spi_wr_i , spi_tx_data_i => spi_tx_data_i , spi_tx_empty_o => spi_tx_empty_o , spi_tx_full_o => spi_tx_full_o , spi_tx_ovf_o => spi_tx_ovf_o , spi_tx_unf_o => spi_tx_unf_o , spi_tx_done_o => spi_tx_done_o ,
spi_rd_i => spi_rd_i , spi_rx_data_o => spi_rx_data_o , spi_rx_empty_o => spi_rx_empty_o , spi_rx_full_o => spi_rx_full_o , spi_rx_ovf_o => spi_rx_ovf_o , spi_rx_unf_o => spi_rx_unf_o ,
sck_o => sck_o , ssn_o => ssn_o , mosi_o => mosi_o , miso_i => miso_i );
---------------------------------------------------------------------------
--------------------------------------------- end architecture rtl;
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~--
spi_tx_data_i : in std_logic_vector(16-1 downto 0); spi_tx_empty_o : out std_logic; spi_tx_full_o : out std_logic; spi_tx_ovf_o : out std_logic; spi_tx_unf_o : out std_logic; spi_tx_done_o : out std_logic;
spi_rd_i : in std_logic; spi_rx_data_o : out std_logic_vector(16-1 downto 0); spi_rx_empty_o : out std_logic; spi_rx_full_o : out std_logic; spi_rx_ovf_o : out std_logic; spi_rx_unf_o : out std_logic;
sck_o : out std_logic; ssn_o : out std_logic; mosi_o : out std_logic; miso_i : in std_logic ); end entity wrapper_SPI_Master;
--======================== ========================= ========================= ========================= ========================= ========================= =======--
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~-- architecture rtl of wrapper_SPI_Master is
---------------------------------------------------------------------------
--------------------------------------------- component SPI_Master generic( Gram_pref : string; Gfifo_depth : natural; Gdwidth : natural; Gspi_clk_div : natural ); port( arstn : in std_logic; clk : in std_logic; spi_rst_i : in std_logic; clken : in std_logic;
cpol_i : in std_logic; cpha_i : in std_logic;
spi_wr_i : in std_logic; spi_tx_data_i : in std_logic_vector(Gdwidth-1 downto 0); spi_tx_empty_o : out std_logic; spi_tx_full_o : out std_logic; spi_tx_ovf_o : out std_logic; spi_tx_unf_o : out std_logic; spi_tx_done_o : out std_logic;
spi_rd_i : in std_logic; spi_rx_data_o : out std_logic_vector(Gdwidth-1 downto 0); spi_rx_empty_o : out std_logic; spi_rx_full_o : out std_logic; spi_rx_ovf_o : out std_logic; spi_rx_unf_o : out std_logic;
sck_o : out std_logic; ssn_o : out std_logic; mosi_o : out std_logic; miso_i : in std_logic ); end component SPI_Master;
---------------------------------------------------------------------------
--------------------------------------------- begin
---------------------------------------------------------------------------
--------------------------------------------- inst_SPI_Master : SPI_Master generic map( Gram_pref => "logic", Gfifo_depth => 2, Gdwidth => 16, Gspi_clk_div => 4 ) port map( arstn => arstn , clk => clk , spi_rst_i => spi_rst_i , clken => clken ,
cpol_i => cpol_i , cpha_i => cpha_i ,
spi_wr_i => spi_wr_i , spi_tx_data_i => spi_tx_data_i , spi_tx_empty_o => spi_tx_empty_o , spi_tx_full_o => spi_tx_full_o , spi_tx_ovf_o => spi_tx_ovf_o , spi_tx_unf_o => spi_tx_unf_o , spi_tx_done_o => spi_tx_done_o ,
spi_rd_i => spi_rd_i , spi_rx_data_o => spi_rx_data_o , spi_rx_empty_o => spi_rx_empty_o , spi_rx_full_o => spi_rx_full_o , spi_rx_ovf_o => spi_rx_ovf_o , spi_rx_unf_o => spi_rx_unf_o ,
sck_o => sck_o , ssn_o => ssn_o , mosi_o => mosi_o , miso_i => miso_i );
---------------------------------------------------------------------------
--------------------------------------------- end architecture rtl;
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~--
---------------------------------------------------------------------------
---------------------------------------------------------------------------
----------
-- File : SPI_Master.vhd
-- Author : David Greig (email : snipped-for-privacy@ieee.org)
-- Revision :
-- Description : SPI master with individual fifo buffers on RX and TX
---------------------------------------------------------------------------
---------------------------------------------
-- Notes :
-- Verified conforming with "Freescale Semiconductor, Inc." SPI Block Guide V4 S12SPIV4.pdf
-- cpha 0 means "sample on 1st edge", cpha = 1 means "sample on 2nd edge" .
-- cpol simply changes the effective polarity of the clock
-- Tranfer latency - ssn goes low 2 clk cycles after first spi_wr
-- One complete sck period is inserted between ssn falling edge to data sta rt, and again from data end to ssn rising edge, and again at the end to giv e minimum
-- ssn high of one sck period
-- Illustration for 8 bit data :- overall time = (nbits + 3) * sck period s
____________~
-- cpha=0 sdo ~-------------------X=======X==== ===X=======X=======X======= X=======X=======X=======X--------
-----~
-- cpha=0 sdo ~-------------------X=======X==== ===X=======X=======X======= X=======X=======X=======X--------
-----~