Möchte man seine EA-Ports erweitern, bietet sich das SPI Protokoll geradezu an, denn fast jeder uC hat eine solche Schnittstelle. Und falls keine da ist, kann sie leicht in Software gehackt werden. Auf der Empfängerseite bieten sich CPLDs an: viele IO-Pins ergeben viele Anschlussmöglichkeiten, und die Registerdichte ist ausreichend. Hier eine Implementation für 24 Ein- und Ausgänge, die in einem XC9572 CPLD realisiert wurde:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity SPI_Slave is Generic ( breite: natural := 24); Port ( SCLK : in STD_LOGIC; SS : in STD_LOGIC; MOSI : in STD_LOGIC; MISO : out STD_LOGIC; Dout : out STD_LOGIC_VECTOR (breite-1 downto 0); Din : in STD_LOGIC_VECTOR (breite-1 downto 0)); end SPI_Slave; architecture Behavioral of SPI_Slave is signal dinsr : STD_LOGIC_VECTOR (breite-1 downto 0); signal doutsr : STD_LOGIC_VECTOR (breite-1 downto 0); begin -- Parallel-Eingänge --> MISO process (SS, Din, SCLK) begin if (SS='1') then dinsr <= Din; elsif falling_edge(SCLK) then -- nach der fallenden SCLK-Flanke dinsr <= dinsr(dinsr'left-1 downto 0) & '0'; -- wird MISO aktualisiert end if; end process; MISO <= dinsr(dinsr'left) when SS='0' else 'Z'; -- MOSI --> Parallel-Ausgänge process (SCLK) begin if rising_edge(SCLK) then -- mit der steigenden SCLK-Flanke doutsr <= doutsr(doutsr'left-1 downto 0) & MOSI; -- wird MOSI eingelesen end if; end process; process (SS) begin if rising_edge(SS) then -- Device wird deselektiert Dout <= doutsr; -- Ausgangssignale an die Pins durchgeben end if; end process; end Behavioral;
Die Kommunikation findet im SPI-Modus 0 statt. Ruhezustand SCLK ist demnach LOW, die Daten werden an der steigenden Flanke eingelesen, und an der fallenden Flanke geändert.
Diese Implementation ist darauf optimiert, so wenig Register wie möglich zu verwenden. Sie eignet sich deshalb nur für CPLDs! Für FPGAs ist die Umsetzung mit asynchronem Reset und zusätzlichen Taktdomänen äusserst ungünstig. Hier sollte eher der Ansatz mit einer Überabtaktung des SCLK mit anschliessender Flankenerkennung gewählt werden. Etwa so wie dort auf dem uC.net im Beitrag Erfahrung mit SPI Slave und Spartan 6 FPGA?
Im weiteren Eintrag findet sich eine Testbench für das obige Design. Diese Testbench kann natürlich auch für FPGAs verwendet werden, weil sie ja keine Struktur, sondern nur das Verhalten des SPI Interfaces beschreibt.