Library of reusable VHDL components
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
6.1 KiB

  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use ieee.numeric_std.all;
  4. entity SpiSlaveE is
  5. generic (
  6. G_DATA_WIDTH : positive := 8; --* data bus width
  7. G_DATA_DIR : natural range 0 to 1 := 0; --* start from lsb/msb 0/1
  8. G_SPI_CPOL : natural range 0 to 1 := 0; --* SPI clock polarity
  9. G_SPI_CPHA : natural range 0 to 1 := 0 --* SPI clock phase
  10. );
  11. port (
  12. --+ system if
  13. Reset_n_i : in std_logic;
  14. Clk_i : in std_logic;
  15. --+ SPI slave if
  16. SpiSclk_i : in std_logic;
  17. SpiSte_i : in std_logic;
  18. SpiMosi_i : in std_logic;
  19. SpiMiso_o : out std_logic;
  20. --+ local VAI if
  21. Data_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  22. DataValid_i : in std_logic;
  23. DataAccept_o : out std_logic;
  24. Data_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  25. DataValid_o : out std_logic;
  26. DataAccept_i : in std_logic
  27. );
  28. end entity SpiSlaveE;
  29. architecture rtl of SpiSlaveE is
  30. type t_spi_state is (IDLE, TRANSFER, STORE);
  31. signal s_spi_state : t_spi_state;
  32. signal s_send_register : std_logic_vector(G_DATA_WIDTH-1 downto 0);
  33. signal s_recv_register : std_logic_vector(G_DATA_WIDTH-1 downto 0);
  34. signal s_sclk_d : std_logic_vector(2 downto 0);
  35. signal s_ste_d : std_logic_vector(2 downto 0);
  36. signal s_mosi_d : std_logic_vector(2 downto 0);
  37. signal s_miso : std_logic;
  38. signal s_data_valid : std_logic;
  39. signal s_transfer_valid : boolean;
  40. signal s_sclk_rising : boolean;
  41. signal s_sclk_falling : boolean;
  42. signal s_read_edge : boolean;
  43. signal s_write_edge : boolean;
  44. alias a_ste : std_logic is s_ste_d(s_ste_d'left);
  45. alias a_mosi : std_logic is s_mosi_d(s_mosi_d'left);
  46. constant C_BIT_COUNTER_START : natural := (G_DATA_WIDTH-1) * G_DATA_DIR;
  47. constant C_BIT_COUNTER_END : natural := (G_DATA_WIDTH-1) * to_integer(not(to_unsigned(G_DATA_DIR, 1)));
  48. begin
  49. --* help signals for edge detection on sclk
  50. s_sclk_rising <= true when s_sclk_d(2 downto 1) = "01" else false;
  51. s_sclk_falling <= true when s_sclk_d(2 downto 1) = "10" else false;
  52. s_read_edge <= s_sclk_rising when G_SPI_CPOL = G_SPI_CPHA else s_sclk_falling;
  53. s_write_edge <= s_sclk_falling when G_SPI_CPOL = G_SPI_CPHA else s_sclk_rising;
  54. --* Sync asynchronous SPI inputs with 3 stage FF line
  55. --* We use 3 FF because of edge detection on sclk line
  56. --* Mosi & ste are also registered with 3 FF to stay in
  57. --* sync with registered sclk
  58. SpiSyncP : process (Reset_n_i, Clk_i) is
  59. begin
  60. if (Reset_n_i = '0') then
  61. if (G_SPI_CPOL = 0) then
  62. s_sclk_d <= (others => '0');
  63. else
  64. s_sclk_d <= (others => '1');
  65. end if;
  66. s_ste_d <= (others => '1');
  67. s_mosi_d <= (others => '0');
  68. elsif rising_edge(Clk_i) then
  69. s_sclk_d <= s_sclk_d(1 downto 0) & SpiSclk_i;
  70. s_ste_d <= s_ste_d(1 downto 0) & SpiSte_i;
  71. s_mosi_d <= s_mosi_d(1 downto 0) & SpiMosi_i;
  72. end if;
  73. end process SpiSyncP;
  74. --* Save local data input when new data is provided and
  75. --* we're not inside a running SPI transmission
  76. --* Beware: Last saved data before a started SPI transmission "wins"
  77. SendRegisterP : process (Reset_n_i, Clk_i) is
  78. begin
  79. if (Reset_n_i = '0') then
  80. s_send_register <= (others => '0');
  81. DataAccept_o <= '0';
  82. elsif rising_edge(Clk_i) then
  83. DataAccept_o <= '0';
  84. if (DataValid_i = '1' and s_spi_state = IDLE) then
  85. s_send_register <= Data_i;
  86. DataAccept_o <= '1';
  87. end if;
  88. end if;
  89. end process SendRegisterP;
  90. --* Spi slave control FSM
  91. SpiControlP : process (Reset_n_i, Clk_i) is
  92. variable v_bit_counter : natural range 0 to G_DATA_WIDTH-1;
  93. begin
  94. if (Reset_n_i = '0') then
  95. s_miso <= '0';
  96. s_recv_register <= (others => '0');
  97. v_bit_counter := C_BIT_COUNTER_START;
  98. s_transfer_valid <= false;
  99. s_spi_state <= IDLE;
  100. elsif rising_edge(Clk_i) then
  101. case s_spi_state is
  102. when IDLE =>
  103. s_miso <= '0';
  104. s_recv_register <= (others => '0');
  105. v_bit_counter := C_BIT_COUNTER_START;
  106. s_transfer_valid <= false;
  107. if (a_ste = '0') then
  108. if (G_SPI_CPHA = 0) then
  109. s_miso <= s_send_register(v_bit_counter);
  110. end if;
  111. s_spi_state <= TRANSFER;
  112. end if;
  113. when TRANSFER =>
  114. if s_read_edge then
  115. s_recv_register(v_bit_counter) <= a_mosi;
  116. if (v_bit_counter = C_BIT_COUNTER_END) then
  117. s_spi_state <= STORE;
  118. else
  119. if (G_DATA_DIR = 0) then
  120. v_bit_counter := v_bit_counter + 1;
  121. else
  122. v_bit_counter := v_bit_counter - 1;
  123. end if;
  124. end if;
  125. elsif s_write_edge then
  126. s_miso <= s_send_register(v_bit_counter);
  127. else
  128. if (a_ste = '1') then
  129. s_spi_state <= IDLE;
  130. end if;
  131. end if;
  132. when STORE =>
  133. if (a_ste = '1') then
  134. s_transfer_valid <= true;
  135. s_spi_state <= IDLE;
  136. end if;
  137. when others =>
  138. s_spi_state <= IDLE;
  139. end case;
  140. end if;
  141. end process SpiControlP;
  142. --* Provide received SPI data to local interface
  143. --* Output data is overwritten if it isn't fetched
  144. --* until next finished SPI transmission
  145. RecvRegisterP : process (Reset_n_i, Clk_i) is
  146. begin
  147. if (Reset_n_i = '0') then
  148. Data_o <= (others => '0');
  149. s_data_valid <= '0';
  150. elsif rising_edge(Clk_i) then
  151. if (s_transfer_valid) then
  152. Data_o <= s_recv_register;
  153. s_data_valid <= '1';
  154. end if;
  155. if (DataAccept_i = '1' and s_data_valid = '1') then
  156. s_data_valid <= '0';
  157. end if;
  158. end if;
  159. end process RecvRegisterP;
  160. --+ Output port connections
  161. DataValid_o <= s_data_valid;
  162. SpiMiso_o <= 'Z' when SpiSte_i = '1' else s_miso;
  163. -- psl default clock is rising_edge(Clk_i);
  164. --
  165. -- psl assert always (s_spi_state = IDLE or s_spi_state = TRANSFER or s_spi_state = STORE);
  166. -- psl assert always (s_data_valid and DataAccept_i) -> next not(s_data_valid);
  167. end architecture rtl;