SPI Interface - exploring what is next Use Cases
Introduction
Continuing with the SPI interface with
- One QSPI bus master
- 8 QSPI Slaves
- 8 SPI Slaves
Explore what additional syntax we may need to add in a future revision.
Based on:
SPI with Port View and Space ship
Based on LCS:
LCS 2016 45a Port Views plus
LCS 2016 70 Space Ship
Alternative 1: Abstracting connections with map procedures
* A map procedure is a callable container of concurrent code.
* Issues: cannot be used on interface
* A little better than an entity, but not a lot
map procedure qspi_master_spi_slave_exch is
parameter (
index : integer ;
signal slave : view spi_slave_view;
signal master : view qspi_master_view
) is
begin
slave.mosi <=> master.mosi(0);
slave.miso <=> master.miso(0);
slave.sclk <=> master.sclk;
slave.ssel <=> master.ssel(index);
end map procedure qspi_master_spi_slave_exch ;
gen_spi_slave_bus : for i in spi_slave_bus'range generate
begin
qspi_master_spi_slave_exch (
index => i+8,
slave => spi_slave_bus(i),
master => qspi_master_bus
) ;
end generate gen_spi_slave_bus ;
Alternative 2: Abstracting connections with conversion like map function
- Create a map function that works like a conversion.
- Potentially usable in a port map.
- Issues: 2 functions
package SpiPkg is
-- . . .
map function s_to_qm (signal slave : view spi_slave_view) return qspi_master_view is
begin
return (
mosi => unaffected,
miso(0) => slave.miso,
miso(3 downto 1) => unaffected,
sclk => unaffected,
ssel => unaffected
) ;
end map function s_to_qm ;
map function qm_to_s(signal master : view qspi_master_view; i : integer ) return spi_slave_view is
return (
mosi => master.mosi(0),
miso => unaffected,
sclk => master.sclk,
ssel => master.ssel(i)
) ;
end map function qm_to_s ;
end package SpiPkg ;
-- creating connections
gen_spi_slave_bus : for i in spi_slave_bus'range generate
s_to_qm(spi_slave_bus(i)) <=> qm_to_s(qspi_master_bus, i) ;
end generate gen_spi_slave_bus ;
Alternative 2b: Using the conversion like map function on a component instance
-- Alternately no need to create connections, do mapping on component instances
qspi_master_1 : qspi_master port map (qspi_master_bus => qspi_master_bus) ;
gen_qspi_slaves : for i in qspi_slave_bus'range generate
qspi_slave_1 : qspi_slave port map (qs_to_qm(qspi_slave_bus) => qm_to_s(qspi_master_bus, i)) ;
end generate gen_spi_slaves ;
gen_spi_slaves : for i in spi_slave_bus'range generate
spi_slave_1 : spi_slave port map (s_to_qm(spi_slave_bus) => qm_to_s(qspi_master_bus, i)) ;
end generate gen_spi_slaves ;
Alternative 2c: Does a map conversion require a designation on the interface since it is different
-- Alternately no need to create connections, do mapping on component instances
...
gen_qspi_slaves : for i in qspi_slave_bus'range generate
qspi_slave_1 : qspi_slave port map (map qs_to_qm(qspi_slave_bus) => map qm_to_s(qspi_master_bus, i)) ;
end generate gen_spi_slaves ;
...
Alternative 2d: Allowing others in a map function
package SpiPkg is
-- . . .
map function s_to_qm (signal slave : view spi_slave_view) return qspi_master_view is
begin
return (
miso(0) => slave.miso,
miso(3 downto 1) => unaffected,
others => unaffected
) ;
end map function s_to_qm ;
map function qm_to_s(signal master : view qspi_master_view ; i : integer) return spi_slave_view is
begin
return (
mosi => master.mosi(0),
miso => unaffected,
sclk => master.sclk,
ssel => master.ssel(i)
) ;
end map function qm_to_s ;
end package SpiPkg ;
Alternative 3: Map function that connects actual to formal.
- Specifies how the parameters of the map function connects to the formal
- One function specified on an actual
-- Definition in a package:
map function qm_to_qs(signal master : view qspi_master_view ; i : integer ) to qspi_slave_view is
begin
map (
mosi <= master.mosi,
miso => master.miso,
sclk <= master.sclk,
ssel <= master.ssel(i)
) ;
end map function qm_to_s ;
map function qm_to_s(signal master : view qspi_master_view ; i : integer ) to spi_slave_view is
begin
map (
mosi <= master.mosi(0),
miso => master.miso(0),
sclk <= master.sclk,
ssel <= master.ssel(i)
) ;
end map function qm_to_s ;
-- Usage in an entity:
qspi_master_1 : qspi_master (qspi_master_bus => qspi_master_bus) ;
gen_qspi_slaves : for i in qspi_slave_bus'range generate
qspi_slave_1 : qspi_slave port map (qspi_slave_bus => map qm_to_qs(qspi_master_bus, i)) ;
end generate gen_spi_slaves ;
gen_spi_slaves : for i in spi_slave_bus'range generate
spi_slave_1 : spi_slave port map (spi_slave_bus => map qm_to_s(qspi_master_bus, i)) ;
end generate gen_spi_slaves ;
Alternative 4: Create a map function that overloads spaceship
- Requires additional static parameters as generics
- Issues: cannot be used on entity interface
map function "<=>"
generic (index : integer)
parameter (signal slave : view slave_view ; signal master : view master_view) is
begin
slave.mosi <=> master.mosi(0);
slave.miso <=> master.miso(0);
slave.sclk <=> master.sclk;
slave.ssel <=> master.ssel(index);
end function "<=>" ;
gen_spi_slave_bus : for i in spi_slave_bus'range generate
spi_slave_bus(i) <=> qspi_master_bus generic map (index => i) ;
end generate gen_spi_slave_bus ;
Alternative 5: Extending capability of spaceship with map ()
- Currently a separate LCS 70a
-- create the interconnect. 1 bit in ssel per slave
gen_qspi_slave_bus : for i in qspi_slave_bus'range generate
qspi_slave_bus(i) <=> map (
mosi => qspi_master_bus.mosi,
miso => qspi_master_bus.miso,
sclk => qspi_master_bus.sclk,
ssel => qspi_master_bus.ssel(i)
);
end generate gen_qspi_slave_bus ;
Alternative 6: A silly alternative as an abbreviated map ()
for qspi_slave_bus(i) map (
mosi => qspi_master_bus.mosi,
miso => qspi_master_bus.miso,
sclk => qspi_master_bus.sclk,
ssel => ssel
);