--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity spi_slave is
+ port(
+ CLK_ext : in std_logic; --fast clock
+ CLK_int : in std_logic; --slow clock
+
+ SPI_CLK : in std_logic;
+ SPI_CS : in std_logic;
+ SPI_IN : in std_logic;
+ SPI_OUT : out std_logic;
+
+ DATA_OUT : out std_logic_vector(15 downto 0);
+ DATA_IN : in std_logic_vector(15 downto 0);
+ ADDR_OUT : out std_logic_vector(7 downto 0);
+ WRITE_OUT : out std_logic;
+ READ_OUT : out std_logic;
+ READY_IN : in std_logic;
+
+ DEBUG : out std_logic_vector(15 downto 0)
+ );
+end entity;
+
+architecture SPI_Slave_arch of spi_slave is
+signal spi_clk_last : std_logic;
+signal spi_clk_reg : std_logic;
+signal spi_cs_reg : std_logic;
+signal spi_in_reg : std_logic;
+
+signal operation_i : std_logic;
+signal data_write : std_logic_vector(15 downto 0);
+signal data_in_i : std_logic_vector(15 downto 0);
+signal addr_i : std_logic_vector(7 downto 0);
+signal last_input : std_logic;
+signal input : std_logic_vector(31 downto 0);
+
+signal next_output : std_logic;
+signal output_data : std_logic_vector (31 downto 0);
+
+signal bitcnt : integer range 0 to 31 := 31;
+
+type state_t is (IDLE, WAIT_FOR_CMD, GET_DATA, PREPARE_OUTPUT, WRITE_DATA, WAIT_FINISH);
+signal state : state_t;
+
+signal buf_SPI_OUT : std_logic;
+
+signal DATA_OUT_inz : std_logic_vector(15 downto 0);
+signal ADDR_OUT_int : std_logic_vector(7 downto 0);
+signal READ_OUT_int : std_logic;
+signal WRITE_OUT_int : std_logic;
+
+
+begin
+
+spi_clk_last <= spi_clk_reg when rising_edge(CLK_ext);
+spi_clk_reg <= SPI_CLK when rising_edge(CLK_ext);
+spi_cs_reg <= SPI_CS when rising_edge(CLK_ext);
+spi_in_reg <= SPI_IN when rising_edge(CLK_ext);
+
+DATA_OUT <= data_write when rising_edge(CLK_int);
+READ_OUT <= READ_OUT_int when rising_edge(CLK_int);
+WRITE_OUT <= WRITE_OUT_int when rising_edge(CLK_int);
+ADDR_OUT <= ADDR_OUT_int when rising_edge(CLK_int);
+
+
+PROC_OUTPUT : process begin
+ wait until rising_edge(CLK_ext);
+ next_output <= output_data(bitcnt);
+ if spi_clk_reg = '0' and spi_clk_last = '1' then
+ SPI_OUT <= last_input;
+ if operation_i = '0' and bitcnt <= 15 then
+ SPI_OUT <= next_output;
+ end if;
+ end if;
+end process;
+
+PROC_INPUT_SHIFT : process begin
+ wait until rising_edge(CLK_ext);
+ if spi_cs_reg = '1' then
+ bitcnt <= 31;
+ else
+ if spi_clk_reg = '1' and spi_clk_last = '0' then
+ if bitcnt /= 0 then
+ bitcnt <= bitcnt - 1;
+ else
+ bitcnt <= 31;
+ end if;
+ last_input <= spi_in_reg;
+ input(bitcnt) <= spi_in_reg;
+ end if;
+ end if;
+end process;
+
+PROC_GEN_SIGNALS : process begin
+ wait until rising_edge(CLK_ext);
+
+ READ_OUT_int <= '0';
+ WRITE_OUT_int <= '0';
+
+ case state is
+ when IDLE =>
+ if spi_cs_reg = '0' then
+ state <= WAIT_FOR_CMD;
+ end if;
+
+ when WAIT_FOR_CMD =>
+ if bitcnt = 22 then
+ operation_i <= input(23);
+ if (input(23) = '0') then
+ READ_OUT_int <= '1';
+ end if;
+ ADDR_OUT_int <= input(31 downto 24);
+ state <= GET_DATA;
+ end if;
+
+ when GET_DATA =>
+ output_data(15 downto 0) <= x"0000";
+ if operation_i = '0' then --read
+ READ_OUT_int <= '1';
+ end if;
+ state <= PREPARE_OUTPUT;
+
+ when PREPARE_OUTPUT =>
+ if operation_i = '0' then --read
+ READ_OUT_int <= '1';
+ if READY_IN = '1' then
+ output_data(15 downto 0) <= DATA_IN;
+ state <= WRITE_DATA;
+ end if;
+ else --write
+ output_data(15 downto 0) <= x"0000";
+ state <= WRITE_DATA;
+ end if;
+
+ when WRITE_DATA =>
+ if bitcnt = 31 then
+ if operation_i = '1' then
+ WRITE_OUT_int <= '1';
+ data_write <= input(15 downto 0);
+ end if;
+ state <= WAIT_FINISH;
+ end if;
+
+ when WAIT_FINISH =>
+ if operation_i = '1' then
+ WRITE_OUT_int <= '1';
+ if WRITE_OUT = '1' then
+ WRITE_OUT_int <= '0';
+ state <= IDLE;
+ end if;
+ else
+ state <= IDLE;
+ end if;
+
+ end case;
+
+ if spi_cs_reg = '1' then
+ state <= IDLE;
+ operation_i <= '0';
+ end if;
+end process;
+
+DEBUG(0) <= spi_clk_reg;
+DEBUG(1) <= spi_cs_reg;
+DEBUG(2) <= spi_in_reg;
+DEBUG(3) <= buf_SPI_OUT;
+DEBUG(7 downto 4) <= std_logic_vector(to_unsigned(bitcnt,4));
+DEBUG(14 downto 8) <= input(30 downto 24);
+--DEBUG_OUT(15) <= write_i(4);
+
+end;