------------------------------------------------------------------------
-- Unconstrained vectors, rather than generics, form the basis for
-- connecting together the various pieces of the puzzle.
------------------------------------------------------------------------
   
package spi_bus_pkg is

	-- Underlying types.  Masters use an unconstrained vector for
	-- chip selects; actual instantiations of the master interface
	-- will have to deal with making these concrete.

    type spi_master_r is record
        mosi : std_logic;                     -- Data from master to slave
        miso : std_logic;                     -- Data from slave to master
        sclk : std_logic;                     -- Serial clock
        ssel : std_logic_vector               -- Chip selects (active-low)
    end record spi_master_r;

    type spi_slave_r is record
        mosi : std_logic;                     -- Data from master to slave
        miso : std_logic;                     -- Data from slave to master
        sclk : std_logic;                     -- Serial clock
        ssel : std_logic;                     -- Chip select (active-low)
    end record spi_slave_r;

    port view master of spi_master_r is
        mosi => out;
        miso => in;
        sclk => out;
        ssel => out;
    end port view master;
    
    port view slave of spi_slave_r is
        mosi => in;
        miso => out;
        sclk => in;
        ssel => in;
    end port view slave;
    
end package spi_bus_pkg;

package body spi_bus_pkg is
end package body spi_bus_pkg;

------------------------------------------------------------------------
-- Using entities rather than mapfunctions to connect masters/slaves
-- to the physical wiring on the PCB, since they exist right now and
-- mapfunctions don't.
--
-- The use of the spaceship operator (<=>) below is intended to make
-- these connections without introducing delta cycles.
------------------------------------------------------------------------

-- Connect an SPI slave to an SPI bus.  Since the bus is of type
-- spi_master_r, but drives into us, we need to use the reverse of a
-- master interface (or an anti-master) on this entity, and an
-- anti-slave on the other side to connect to the slave.
--
--    FPGA              spi_slave_link        ADC
-- ----------       --------------------    ---------
--   Master |-------| Anti-      Anti- |----| Slave |
--          |       | Master     Slave |    |       |
-- ----------       --------------------    ---------
--

use work.spi_bus_pkg.all;
entity spi_slave_link is
    generic (
        CHIP_SELECT : natural
    );
    port (
        mst : bus spi_master_r(master)'reversed;
        slv : bus spi_slave_r(slave)'reversed;
    );
end entity spi_slave_link;

architecture Behavioral of spi_slave_link is
begin
    slv.mosi <=> slv.mosi;                --   <----
    slv.miso <=> slv.miso;                --   ---->
    slv.sclk <=> slv.sclk;                --   <----
    slv.ssel <=> mst.ssel(CHIP_SELECT);   --   <----
end architecture Behavioral;
