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.

241 lines
7.4 KiB

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