-----------------------------------------------
-- 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;

