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.

240 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_sclk <= std_logic'val(G_SPI_CPOL+2);
  85. s_mosi <= '1';
  86. s_spi_state <= IDLE;
  87. elsif rising_edge(Clk_i) then
  88. case s_spi_state is
  89. when IDLE =>
  90. s_sclk <= std_logic'val(G_SPI_CPOL+2);
  91. s_mosi <= '1';
  92. s_recv_register <= (others => '0');
  93. v_bit_counter := C_BIT_COUNTER_START;
  94. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  95. s_transfer_valid <= false;
  96. if(DataValid_i = '1' and s_data_accept = '1') then
  97. s_spi_state <= WRITE;
  98. end if;
  99. when WRITE =>
  100. if (G_SPI_CPHA = 0 and v_bit_counter = C_BIT_COUNTER_START) then
  101. s_mosi <= s_send_register(v_bit_counter);
  102. s_spi_state <= READ;
  103. else
  104. if (v_sclk_counter = 0) then
  105. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  106. s_sclk <= not(s_sclk);
  107. s_mosi <= s_send_register(v_bit_counter);
  108. s_spi_state <= READ;
  109. else
  110. v_sclk_counter := v_sclk_counter - 1;
  111. end if;
  112. end if;
  113. when READ =>
  114. if (v_sclk_counter = 0) then
  115. s_sclk <= not(s_sclk);
  116. s_recv_register(v_bit_counter) <= a_miso;
  117. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  118. if (v_bit_counter = C_BIT_COUNTER_END) then
  119. if (G_SPI_CPHA = 0) then
  120. s_spi_state <= CYCLE;
  121. else
  122. s_spi_state <= STORE;
  123. end if;
  124. else
  125. if (G_DATA_DIR = 0) then
  126. v_bit_counter := v_bit_counter + 1;
  127. else
  128. v_bit_counter := v_bit_counter - 1;
  129. end if;
  130. s_spi_state <= WRITE;
  131. end if;
  132. else
  133. v_sclk_counter := v_sclk_counter - 1;
  134. end if;
  135. when CYCLE =>
  136. if (v_sclk_counter = 0) then
  137. s_sclk <= not(s_sclk);
  138. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  139. s_spi_state <= STORE;
  140. else
  141. v_sclk_counter := v_sclk_counter - 1;
  142. end if;
  143. when STORE =>
  144. if (v_sclk_counter = 0) then
  145. s_transfer_valid <= true;
  146. v_sclk_counter := G_SCLK_DIVIDER/2-1;
  147. s_spi_state <= SET_STE;
  148. else
  149. v_sclk_counter := v_sclk_counter - 1;
  150. end if;
  151. when SET_STE =>
  152. s_transfer_valid <= false;
  153. if (v_sclk_counter = 0) then
  154. s_spi_state <= IDLE;
  155. else
  156. v_sclk_counter := v_sclk_counter - 1;
  157. end if;
  158. when others =>
  159. s_spi_state <= IDLE;
  160. end case;
  161. end if;
  162. end process SpiControlP;
  163. --* Provide received SPI data to local interface
  164. --* Output data is overwritten if it isn't fetched
  165. --* until next finished SPI transmission
  166. RecvRegisterP : process (Reset_n_i, Clk_i) is
  167. begin
  168. if (Reset_n_i = '0') then
  169. Data_o <= (others => '0');
  170. s_data_valid <= '0';
  171. elsif rising_edge(Clk_i) then
  172. if (s_transfer_valid) then
  173. Data_o <= s_recv_register;
  174. s_data_valid <= '1';
  175. end if;
  176. if (DataAccept_i = '1' and s_data_valid = '1') then
  177. s_data_valid <= '0';
  178. end if;
  179. end if;
  180. end process RecvRegisterP;
  181. --+ internal signals
  182. s_ste <= '1' when s_spi_state = IDLE or s_spi_state = SET_STE else '0';
  183. --+ Output port connections
  184. DataValid_o <= s_data_valid;
  185. DataAccept_o <= s_data_accept;
  186. SpiSte_o <= s_ste;
  187. SpiSclk_o <= s_sclk;
  188. SpiMosi_o <= s_mosi when s_ste = '0' else '1';
  189. assert G_SCLK_DIVIDER rem 2 = 0
  190. report "WARNING: " & SpiMasterE'instance_name & LF & "G_SCLK_DIVIDER " & integer'image(G_SCLK_DIVIDER) &
  191. " rounded down to next even value " & integer'image(G_SCLK_DIVIDER-1)
  192. severity warning;
  193. -- psl default clock is rising_edge(Clk_i);
  194. --
  195. -- psl assert always (s_spi_state = IDLE or s_spi_state = WRITE or s_spi_state = READ or
  196. -- s_spi_state = CYCLE or s_spi_state = SET_STE or s_spi_state = STORE);
  197. -- psl assert always (s_data_valid and DataAccept_i) -> next not(s_data_valid);
  198. end architecture rtl;