library IEEE ; use IEEE . STD_LOGIC_1164 . ALL ; use IEEE . NUMERIC_STD . ALL ; entity spi_multibyte is -- SPI mode 0: CPOL=0, CPHA=0 Generic ( crystal_clock_frequency : integer := 50000000; -- Hertz SPI_clock_frequency : integer := 100000; -- Hertz / for calculating the reload value for clock divider_length : integer := 16 ; -- number of bits to be transmitted data_per_SS : integer := 2 ---number of data per CS ); Port ( TX_Data_1 : in STD_LOGIC_VECTOR ( divider_length - 1 downto 0 ); -- Transmit data_1 Tx_Data_2 : in STD_LOGIC_VECTOR ( divider_length - 1 downto 0); --- Transmit Data_2 RX_Data : out STD_LOGIC_VECTOR ( divider_length - 1 downto 0 ); -- Receive data MOSI : out STD_LOGIC ; MISO : in STD_LOGIC ; SCLK : out STD_LOGIC ; SS : out STD_LOGIC ; TX_Start : in STD_LOGIC ; TX_Done : out STD_LOGIC ; clk : in STD_LOGIC ); end spi_multibyte ; architecture Behavioral of spi_multibyte is signal delay : integer range 0 to ( crystal_clock_frequency /( 2 * SPI_clock_frequency )); constant clock_delay : integer:= ( crystal_clock_frequency /( 2 * SPI_clock_frequency ))- 1 ; type spitx_states is ( spi_stx , spi_txactive , spi_etx ); signal spitxstate : spitx_states := spi_stx ; signal spiclk : std_logic ; signal spiclklast : std_logic ; signal bitcounter : integer range 0 to divider_length*data_per_SS ;-- if bitcounter = length --> transfer all bits signal tx_reg : std_logic_vector ( 31 downto 0 ) := ( others => '0' ); signal tx_reg_1 : std_logic_vector ( divider_length - 1 downto 0 ) := ( others => '0' ); signal tx_reg_2 : std_logic_vector ( divider_length - 1 downto 0 ) := ( others => '0' ); signal rx_reg : std_logic_vector ( divider_length - 1 downto 0 ) := ( others => '0' ); begin ------ Management -------- process begin wait until rising_edge ( CLK ); if ( delay> 0 ) then delay <= delay - 1 ; else delay <= clock_delay ; end if ; spiclklast <= spiclk ; case spitxstate is when spi_stx => SS <= '1' ; -- slave select disabled TX_Done <= '0' ; bitcounter <= divider_length * data_per_SS ; spiclk <= '0' ; -- SPI mode 0 if (TX_Start = '1' ) then spitxstate <= spi_txactive ; SS <= '0' ; delay <= clock_delay ; end if ; when spi_txactive => -- transfer data from tx_reg_1 if ( delay = 0 ) then -- shift spiclk <= not spiclk ; if ( bitcounter = 0 ) then -- transfer all bits -> deselect spiclk <= '0' ; -- SPI mode 0 spitxstate <= spi_etx ; end if ; if ( spiclk = '1' ) then -- SPI mode 0 bitcounter <= bitcounter - 1 ; end if ; end if ; when spi_etx => SS <= '1' ; -- disable Slave Select TX_Done <= '1' ; if ( TX_Start ='0' ) then -- Handshake: wait until start flag cleared spitxstate <= spi_stx ; end if ; end case ; end process ; -----Process to send mutiple data under one CS Transmit---- ---- Receive shift register ----- process begin wait until rising_edge ( CLK ); if ( spiclk = '1' and spiclklast = '0' ) then -- SPI mode 0 rx_reg <= rx_reg ( rx_reg 'left -1 downto 0 ) & MISO ; end if ; end process ; ---- Send shift register ------- process begin wait until rising_edge ( CLK ); if(data_per_SS = 1) then if ( spitxstate = spi_stx ) then -- Reset if SS inactive tx_reg_1 <= TX_Data_1 ; end if ; end if; if(data_per_SS = 2) then if(spitxstate = spi_stx) then tx_reg_1 <= TX_Data_1 ; tx_reg_2 <= TX_Data_2 ; end if ; end if; if(data_per_SS = 1) then if ( spiclk = '0' and spiclklast = '1' ) then -- SPI mode 0 tx_reg_1 <= tx_reg_1 ( tx_reg_1 'left - 1 downto 0 ) & tx_reg_1 ( 0 ); tx_reg <= tx_reg_1; end if ; end if; if(data_per_SS = 2) then if ( spiclk = '0' and spiclklast = '1' ) then -- SPI mode 0 tx_reg_1 <= tx_reg_1 ( tx_reg_1 'left - 1 downto 0 ) & tx_reg_1 ( 0 ); tx_reg_2 <= tx_reg_2 ( tx_reg_2 'left - 1 downto 0 ) & tx_reg_2 ( 0 ); end if ; tx_reg <= tx_reg_1 (31 downto 16); tx_reg <= tx_reg_2 (15 downto 0); end if; end process ; SCLK <= spiclk ; MOSI <= tx_reg ( tx_reg 'left ); RX_Data <= rx_reg ; end Behavioral ;