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.

232 lines
6.9 KiB

  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. entity SpiMasterE 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. G_SCLK_DIVIDER : positive range 6 to positive'high := 10 --* SCLK divider related to system clock
  9. );
  10. port (
  11. --+ system if
  12. Reset_n_i : in std_logic;
  13. Clk_i : in std_logic;
  14. --+ SPI slave if
  15. SpiSclk_o : out std_logic;
  16. SpiSte_o : out std_logic;
  17. SpiMosi_o : out std_logic;
  18. SpiMiso_i : in std_logic;
  19. --+ local VAI if
  20. Data_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  21. DataValid_i : in std_logic;
  22. DataAccept_o : out std_logic;
  23. Data_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  24. DataValid_o : out std_logic;
  25. DataAccept_i : in std_logic
  26. );
  27. end entity SpiMasterE;
  28. architecture rtl of SpiMasterE is
  29. type t_spi_state is (IDLE, WRITE, READ, CYCLE, STORE, SET_STE);
  30. signal s_spi_state : t_spi_state;
  31. signal s_send_register : std_logic_vector(G_DATA_WIDTH-1 downto 0);
  32. signal s_recv_register : std_logic_vector(G_DATA_WIDTH-1 downto 0);
  33. signal s_miso_d : std_logic_vector(1 downto 0);
  34. signal s_mosi : std_logic;
  35. signal s_sclk : std_logic;
  36. signal s_ste : std_logic;
  37. signal s_data_valid : std_logic;
  38. signal s_data_accept : 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_miso : std_logic is s_miso_d(s_miso_d'left);
  45. begin
  46. --* Sync asynchronous SPI inputs with 2 stage FF line
  47. SpiSyncP : process (Reset_n_i, Clk_i) is
  48. begin
  49. if (Reset_n_i = '0') then
  50. s_miso_d <= (others => '0');
  51. elsif rising_edge(Clk_i) then
  52. s_miso_d <= s_miso_d(0) & SpiMiso_i;
  53. end if;
  54. end process SpiSyncP;
  55. --* Save local data input when new data is provided and
  56. --* we're not inside a running SPI transmission
  57. SendRegisterP : process (Reset_n_i, Clk_i) is
  58. begin
  59. if (Reset_n_i = '0') then
  60. s_send_register <= (others => '0');
  61. s_data_accept <= '0';
  62. elsif rising_edge(Clk_i) then
  63. s_data_accept <= '0';
  64. if (DataValid_i = '1' and s_spi_state = IDLE) then
  65. s_send_register <= Data_i;
  66. s_data_accept <= '1';
  67. end if;
  68. end if;
  69. end process SendRegisterP;
  70. --* Spi master control FSM
  71. SpiControlP : process (Reset_n_i, Clk_i) is
  72. variable v_bit_counter : natural range 0 to G_DATA_WIDTH-1;
  73. variable v_sclk_counter : natural range 0 to G_SCLK_DIVIDER-1;
  74. begin
  75. if (Reset_n_i = '0') then
  76. s_recv_register <= (others => '0');
  77. v_bit_counter := G_DATA_WIDTH-1;
  78. v_sclk_counter := G_SCLK_DIVIDER-1;
  79. s_transfer_valid <= false;
  80. s_ste <= '1';
  81. s_sclk <= std_logic'val(G_SPI_CPOL+2);
  82. s_mosi <= '1';
  83. s_spi_state <= IDLE;
  84. elsif rising_edge(Clk_i) then
  85. case s_spi_state is
  86. when IDLE =>
  87. s_ste <= '1';
  88. s_sclk <= std_logic'val(G_SPI_CPOL+2);
  89. s_mosi <= '0';
  90. s_recv_register <= (others => '0');
  91. v_bit_counter := G_DATA_WIDTH-1;
  92. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  93. s_transfer_valid <= false;
  94. if(DataValid_i = '1' and s_data_accept = '1') then
  95. s_ste <= '0';
  96. s_spi_state <= WRITE;
  97. end if;
  98. when WRITE =>
  99. if (G_SPI_CPHA = 0 and v_bit_counter = G_DATA_WIDTH-1) then
  100. s_mosi <= s_send_register(v_bit_counter);
  101. s_spi_state <= READ;
  102. else
  103. if (v_sclk_counter = 0) then
  104. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  105. s_sclk <= not(s_sclk);
  106. s_mosi <= s_send_register(v_bit_counter);
  107. s_spi_state <= READ;
  108. else
  109. v_sclk_counter := v_sclk_counter - 1;
  110. end if;
  111. end if;
  112. when READ =>
  113. if (v_sclk_counter = 0) then
  114. s_sclk <= not(s_sclk);
  115. s_recv_register(v_bit_counter) <= a_miso;
  116. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  117. if (v_bit_counter = 0) then
  118. if (G_SPI_CPHA = 0) then
  119. s_spi_state <= CYCLE;
  120. else
  121. s_spi_state <= STORE;
  122. end if;
  123. else
  124. v_bit_counter := v_bit_counter - 1;
  125. s_spi_state <= WRITE;
  126. end if;
  127. else
  128. v_sclk_counter := v_sclk_counter - 1;
  129. end if;
  130. when CYCLE =>
  131. if (v_sclk_counter = 0) then
  132. s_sclk <= not(s_sclk);
  133. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  134. s_spi_state <= STORE;
  135. else
  136. v_sclk_counter := v_sclk_counter - 1;
  137. end if;
  138. when STORE =>
  139. if (v_sclk_counter = 0) then
  140. s_transfer_valid <= true;
  141. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  142. s_spi_state <= SET_STE;
  143. else
  144. v_sclk_counter := v_sclk_counter - 1;
  145. end if;
  146. when SET_STE =>
  147. s_transfer_valid <= false;
  148. s_ste <= '1';
  149. if (v_sclk_counter = 0) then
  150. s_spi_state <= IDLE;
  151. else
  152. v_sclk_counter := v_sclk_counter - 1;
  153. end if;
  154. when others =>
  155. s_spi_state <= IDLE;
  156. end case;
  157. end if;
  158. end process SpiControlP;
  159. --* Provide received SPI data to local interface
  160. --* Output data is overwritten if it isn't fetched
  161. --* until next finished SPI transmission
  162. RecvRegisterP : process (Reset_n_i, Clk_i) is
  163. begin
  164. if (Reset_n_i = '0') then
  165. Data_o <= (others => '0');
  166. s_data_valid <= '0';
  167. elsif rising_edge(Clk_i) then
  168. if (s_transfer_valid) then
  169. Data_o <= s_recv_register;
  170. s_data_valid <= '1';
  171. end if;
  172. if (DataAccept_i = '1' and s_data_valid = '1') then
  173. s_data_valid <= '0';
  174. end if;
  175. end if;
  176. end process RecvRegisterP;
  177. --+ Output port connections
  178. DataValid_o <= s_data_valid;
  179. DataAccept_o <= s_data_accept;
  180. SpiSte_o <= s_ste;
  181. SpiSclk_o <= s_sclk;
  182. SpiMosi_o <= s_mosi;
  183. assert G_SCLK_DIVIDER rem 2 = 0
  184. report "WARNING: " & SpiMasterE'instance_name & LF & "G_SCLK_DIVIDER " & integer'image(G_SCLK_DIVIDER) &
  185. " rounded down to next even value " & integer'image(G_SCLK_DIVIDER-1)
  186. severity warning;
  187. -- psl default clock is rising_edge(Clk_i);
  188. --
  189. -- psl assert always (s_spi_state = IDLE or s_spi_state = WRITE or s_spi_state = READ or
  190. -- s_spi_state = CYCLE or s_spi_state = SET_STE or s_spi_state = STORE);
  191. -- psl assert always (s_data_valid and DataAccept_i) -> next not(s_data_valid);
  192. end architecture rtl;