Here is my implementation. Last question, is it possible to put an internal pull-up on the chip select (CSn) signals?
-- The idea is that choose either A or B is exclusively
-- connected to O
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity bidir_SPI_switch is
port(
en, S : IN BIT;
A_CSn, A_SCLK, A_SIMO, A_SOMI : INOUT STD_LOGIC;
B_CSn, B_SCLK, B_SIMO, B_SOMI : INOUT STD_LOGIC;
O_CSn, O_SCLK, O_SIMO, O_SOMI : INOUT STD_LOGIC
);
end bidir_SPI_switch;
architecture behaviour of bidir_SPI_switch is
begin
process(en,S,
A_CSn, A_SCLK, A_SIMO, A_SOMI,
B_CSn, B_SCLK, B_SIMO, B_SOMI,
O_CSn, O_SCLK, O_SIMO, O_SOMI)
begin
-- change default state of each port depending on if
-- the port is a Master only, Slave only or both.
A_CSn <= 'Z';
A_SCLK <= 'Z';
A_SIMO <= 'Z';
A_SOMI <= 'Z';
B_CSn <= 'Z';
B_SCLK <= 'Z';
B_SIMO <= 'Z';
B_SOMI <= 'Z';
O_CSn <= 'Z';
O_SCLK <= 'Z';
O_SIMO <= 'Z';
O_SOMI <= 'Z';
-- when disabled, A <=> O
if en = '0' then
if (A_CSn = '0') then
O_CSn <= '0';
O_SCLK <= A_SCLK;
O_SIMO <= A_SIMO;
A_SOMI <= O_SOMI;
end if;
if (O_CSn = '0') then
A_CSn <= '0';
A_SCLK <= O_SCLK;
A_SIMO <= O_SIMO;
O_SOMI <= A_SOMI;
end if;
-- when enabled
else
-- S = 0, A <=> O
if (S = '0') then
if (A_CSn = '0') then
O_CSn <= '0';
O_SCLK <= A_SCLK;
O_SIMO <= A_SIMO;
A_SOMI <= O_SOMI;
end if;
if (O_CSn = '0') then
A_CSn <= '0';
A_SCLK <= O_SCLK;
A_SIMO <= O_SIMO;
O_SOMI <= A_SOMI;
end if;
-- S = 1, B <=> O
else
if (B_CSn = '0') then
O_CSn <= '0';
O_SCLK <= B_SCLK;
O_SIMO <= B_SIMO;
B_SOMI <= O_SOMI;
end if;
if (O_CSn = '0') then
B_CSn <= '0';
B_SCLK <= O_SCLK;
B_SIMO <= O_SIMO;
O_SOMI <= B_SOMI;
end if;
end if; -- S = '1'
end if; -- en = '1'
end process;
end architecture behaviour;