-----------------------------------------------
-- wrapper for the SPI master transmitter logic
--
library ieee;
use ieee.std_logic_1164.all;

library UNISIM;
use UNISIM.vcomponents.all;

library comm;

entity spi_transmitter_wrapper is
generic (
        G_DATA1 : std_logic_vector;
        G_DATA2 : std_logic_vector;
        G_NUM_BITS_PACKET : integer;
        G_NUM_PACKETS : integer;
        G_NUM_BITS_PAUSE : integer
);      
  port (
                
                -- input clock:
                i_clk125 : in std_logic;
                
                i_reset : in std_logic;
                
                i_data_selector : in std_logic;
                
                o_done : out std_logic;
                
                -- SPI output:
                OUT_SPI_N_CE : OUT std_logic_vector;
                OUT_SPI_DOUT : OUT std_logic;
                OUT_SPI_CLK  : OUT std_logic
                                
  );
                
end spi_transmitter_wrapper;

architecture behavioral of spi_transmitter_wrapper is

        component clk_125MHz_to_6MHz
        port
        (-- Clock in ports
                CLK_IN_125           : in     std_logic;
                -- Clock out ports
                CLK_OUT_6          : out    std_logic
        );
        end component;

        -- divided clock:
        signal s_spi_input_clk : std_logic;
        signal s_clk_6MHz : std_logic;
        signal s_clk_125kHz_tmp : std_logic;
        attribute clock_signal : string;
        attribute clock_signal of s_spi_input_clk : signal is "yes";
        
        -- SPI output pins registers:
        signal s_out_spi_n_ce_d : std_logic_vector( OUT_SPI_N_CE'range );
        signal s_out_spi_dout_d : std_logic;
        signal s_out_spi_clk_d  : std_logic;
        
        -- pack the OUT registers to IOB so that the timing is better:
        attribute iob : string;
        attribute iob of OUT_SPI_N_CE : signal is "FORCE";
        attribute iob of OUT_SPI_DOUT : signal is "FORCE";
        attribute iob of OUT_SPI_CLK  : signal is "FORCE";

begin

        -- IP Core clock wizard:
        clk_125MHz_to_6MHz_inst : clk_125MHz_to_6MHz
        port map ( CLK_IN_125 => i_clk125, CLK_OUT_6 => s_clk_6MHz );

        -- ~1MHz clock:
        BUFR_inst : BUFR
        generic map (
                BUFR_DIVIDE => "6", SIM_DEVICE => "VIRTEX6" )
        port map (
                O => s_clk_125kHz_tmp, -- s_spi_input_clk
                CE => '1',
                CLR => '0',
                I => s_clk_6MHz
        );
        
        BUFR2_inst : BUFR
        generic map (
                BUFR_DIVIDE => "8", SIM_DEVICE => "VIRTEX6" )
        port map (
                O => s_spi_input_clk,
                CE => '1',
                CLR => '0',
                I => s_clk_125kHz_tmp
        );

        -- SPI master transmitter:
        spi_transmit_inst : entity comm.spi_master_transmit
        generic map(
                G_DATA1 => G_DATA1,
                G_DATA2 => G_DATA2,
                G_NUM_BITS_PACKET => G_NUM_BITS_PACKET,
                G_NUM_PACKETS => G_NUM_PACKETS,
                G_NUM_BITS_PAUSE => G_NUM_BITS_PAUSE )  
        port map(
                i_clk => s_spi_input_clk, i_rst => i_reset, i_data_selector => i_data_selector,
                o_done => o_done,
                o_n_ce => s_out_spi_n_ce_d,
                o_dout => s_out_spi_dout_d,
                o_clk => s_out_spi_clk_d
        );
        
        -- registers:
        registered_spi_output : process( s_clk_6MHz )
        begin
                if( rising_edge( s_clk_6MHz ) ) then
                        OUT_SPI_N_CE <= s_out_spi_n_ce_d;
                        OUT_SPI_DOUT <= s_out_spi_dout_d;
                        OUT_SPI_CLK  <= s_out_spi_clk_d;
                end if;
        end process;
        
end architecture;