SPI Interface Use Case
Introduction
Working through the SPI bus using
LCS 2016 45 Port Views plus
LCS 2016 70 Space Ship
Use case has
- One QSPI bus master
- 8 QSPI Slaves
- 8 SPI Slaves
After this version, for looking forward see:
SPI exploring what is next Use Cases
SPI package
library IEEE ;
use ieee.std_logic_1164.all ;
package SpiPkg is
type qspi_master_r is record
mosi : std_logic_vector(3 downto 0); -- Data from master to slave
miso : std_logic_vector(3 downto 0); -- Data from slave to master
sclk : std_logic; -- Serial clock
ssel : std_logic_vector(15 downto 0); -- Chip selects
end record qspi_master_r;
view qspi_master_view of qspi_master_r is
mosi : out;
miso : in;
sclk : out;
ssel : out;
end view qspi_master_view;
type qspi_master_vector is array(integer range <>) of qspi_master_r ;
type qspi_slave_r is record
mosi : std_logic_vector(3 downto 0); -- Data from master to slave
miso : std_logic_vector(3 downto 0); -- Data from slave to master
sclk : std_logic; -- Serial clock
ssel : std_logic; -- Chip select
end record qspi_slave_r;
type qspi_slave_vector is array(integer range <>) of qspi_slave_r;
view qspi_slave_view of qspi_slave_r is
mosi : in;
miso : out;
sclk : in;
ssel : in;
end view qspi_slave_view;
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
end record spi_slave_r;
type spi_slave_vector is array(integer range <>) of spi_slave_r;
view spi_slave_view of spi_slave_r is
mosi : in;
miso : out;
sclk : in;
ssel : in;
end view spi_slave_view;
end package SpiPkg ;
Chipper Basic: Connecting the Master and Slaves
Issues?
- Verbose but capable.
- Details of the connectivity exposed in the top level netlist
---------------------------------------------------------
-- chipper_basic
-- connect a quad SPI master to
-- 8 qspi slaves and
-- 8 spi slaves
-- ssel has one bit per slave
--
library IEEE ;
use ieee.std_logic_1164.all ;
use work.SpiPkg.all ;
entity chipper_basic is
port (
..
) ;
end entity chipper_basic ;
architecture structural of chipper_basic is
-- connections for the SPI intefaces
signal qspi_master_bus : qspi_master_r;
signal qspi_slave_bus : qspi_slave_vector(7 downto 0);
signal spi_slave_bus : spi_slave_vector (7 downto 0);
-- SPI Components
component qspi_master (qspi_master_bus : view qspi_master_view ) ;
component qspi_slave (qspi_slave_bus : view qspi_slave_view ) ;
component spi_slave (spi_slave_bus : view spi_slave_view ) ;
begin
-- create the interconnect. ssel has one bit per slave
gen_qspi_slave_bus : for i in qspi_slave_bus'range generate
begin
qspi_slave_bus(i).mosi <=> qspi_master_bus.mosi;
qspi_slave_bus(i).miso <=> qspi_master_bus.miso;
qspi_slave_bus(i).sclk <=> qspi_master_bus.sclk;
qspi_slave_bus(i).ssel <=> qspi_master_bus.ssel(i);
end generate gen_qspi_slave_bus ;
gen_spi_slave_bus : for i in spi_slave_bus'range generate
begin
spi_slave_bus(i).mosi <=> qspi_master_bus.mosi(0);
spi_slave_bus(i).miso <=> qspi_master_bus.miso(0);
spi_slave_bus(i).sclk <=> qspi_master_bus.sclk;
spi_slave_bus(i).ssel <=> qspi_master_bus.ssel(i+8);
end generate gen_spi_slave_bus ;
-- instantiate the components
qspi_master_1 : qspi_master port map (qspi_master_bus => qspi_master_bus) ;
gen_qspi_slaves : for i in qspi_slave_bus'range generate
begin
qspi_slave_1 : qspi_slave port map (qspi_slave_bus => qspi_slave_bus(i)) ;
end generate gen_spi_slaves ;
gen_spi_slaves : for i in spi_slave_bus'range generate
begin
spi_slave_1 : spi_slave port map (spi_slave_bus => spi_slave_bus(i)) ;
end generate gen_spi_slaves ;
end architecture structural ;
Chipper Basic, except SSEL specifies an address
- Has decode logic in the interface
---------------------------------------------------------
-- chipper_basic_decode
-- connect a quad SPI master to
-- 8 qspi slaves and
-- 8 spi slaves
-- ssel is the address for each slave
--
library IEEE ;
use ieee.std_logic_1164.all ;
use work.SpiPkg.all ;
entity chipper_basic_decode is
port (
..
) ;
end entity chipper_basic_decode ;
architecture structural of chipper_basic_decode is
-- ... unchanged
begin
-- create the interconnect. ssel is the address for each slave
gen_qspi_slave_bus : for i in qspi_slave_bus'range generate
signal ssel : std_logic ;
begin
ssel <= qspi_master_bus.ssel ?= i ;
qspi_slave_bus(i).mosi <=> qspi_master_bus.mosi;
qspi_slave_bus(i).miso <=> qspi_master_bus.miso;
qspi_slave_bus(i).sclk <=> qspi_master_bus.sclk;
qspi_slave_bus(i).ssel <= ssel;
end generate gen_qspi_slave_bus ;
gen_spi_slave_bus : for i in spi_slave_bus'range generate
begin
spi_slave_bus(i).mosi <=> qspi_master_bus.mosi(0);
spi_slave_bus(i).miso <=> qspi_master_bus.miso(0);
spi_slave_bus(i).sclk <=> qspi_master_bus.sclk;
spi_slave_bus(i).ssel <= qspi_master_bus.ssel ?= i+8;
end generate gen_spi_slave_bus ;
-- instantiate the components
-- ... unchanged
end architecture structural ;
Abstracting connections with entities - today
Comments
* capable but verbose
* good enough? probably for now.
---------------------------------------------------------
-- qspi_master_qspi_slave_exchange
-- connect qspi master to qspi slave
--
library IEEE ;
use ieee.std_logic_1164.all ;
use work.SpiPkg.all ;
entity qspi_master_qspi_slave_exchange is
generic (index : integer ) ;
port (
master : view qspi_master_view;
slave : view qspi_slave_view
) ;
end entity qspi_master_spi_slave_exchange ;
architecture exchange of qspi_master_spi_slave_exchange is
begin
slave.mosi <=> master.mosi;
slave.miso <=> master.miso;
slave.sclk <=> master.sclk;
slave.ssel <=> master.ssel(index);
end architecture exchange ;
---------------------------------------------------------
-- qspi_master_spi_slave_exchange
-- connect qspi master to spi slave
--
library IEEE ;
use ieee.std_logic_1164.all ;
use work.SpiPkg.all ;
entity qspi_master_spi_slave_exchange is
generic (index : integer ) ;
port (
master : view qspi_master_view;
slave : view spi_slave_view
) ;
end entity qspi_master_spi_slave_exchange ;
architecture exchange of qspi_master_spi_slave_exchange is
begin
slave.mosi <=> master.mosi(0);
slave.miso <=> master.miso(0);
slave.sclk <=> master.sclk;
slave.ssel <=> master.ssel(index);
end architecture exchange ;
---------------------------------------------------------
-- chipper_entity_connect
-- connect a quad SPI master to
-- 8 qspi slaves and
-- 8 spi slaves
-- ssel is the address for each slave
--
library IEEE ;
use ieee.std_logic_1164.all ;
use work.SpiPkg.all ;
entity chipper_entity_connect is
port (
..
) ;
end entity chipper_entity_connect ;
architecture structural of chipper_entity_connect is
-- ... unchanged
begin
-- create the interconnect. ssel is the address for each slave
gen_qspi_slave_bus : for i in qspi_slave_bus'range generate
begin
qspi_master_qspi_slave_exchange_1 : qspi_master_qspi_slave_exchange
generic map (index => i)
port map (
master => qspi_master_bus,
slave => qspi_slave_bus(i)
) ;
end generate gen_qspi_slave_bus ;
gen_spi_slave_bus : for i in spi_slave_bus'range generate
begin
qspi_master_spi_slave_exchange_1 : qspi_master_spi_slave_exchange
generic map (index => i+8)
port map (
master => qspi_master_bus,
slave => spi_slave_bus(i)
) ;
end generate gen_spi_slave_bus ;
-- instantiate the components
-- ... unchanged
end architecture structural ;