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.

196 lines
5.6 KiB

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