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.

285 lines
8.1 KiB

  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use ieee.numeric_std.all;
  4. library libvhdl;
  5. use libvhdl.AssertP.all;
  6. use libvhdl.SimP.all;
  7. --+ including vhdl 2008 libraries
  8. library ieee_proposed;
  9. use ieee_proposed.standard_additions.all;
  10. use ieee_proposed.std_logic_1164_additions.all;
  11. use ieee_proposed.numeric_std_additions.all;
  12. entity SpiT is
  13. end entity SpiT;
  14. architecture sim of SpiT is
  15. component SpiMasterE is
  16. generic (
  17. G_DATA_WIDTH : positive := 8;
  18. G_SPI_CPOL : natural range 0 to 1 := 0;
  19. G_SPI_CPHA : natural range 0 to 1 := 0;
  20. G_SCLK_DIVIDER : positive := 10
  21. );
  22. port (
  23. --+ system if
  24. Reset_n_i : in std_logic;
  25. Clk_i : in std_logic;
  26. --+ SPI slave if
  27. SpiSclk_o : out std_logic;
  28. SpiSte_o : out std_logic;
  29. SpiMosi_o : out std_logic;
  30. SpiMiso_i : in std_logic;
  31. --+ local VAI if
  32. Data_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  33. DataValid_i : in std_logic;
  34. DataAccept_o : out std_logic;
  35. Data_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  36. DataValid_o : out std_logic;
  37. DataAccept_i : in std_logic
  38. );
  39. end component SpiMasterE;
  40. component SpiSlaveE is
  41. generic (
  42. G_DATA_WIDTH : positive := 8;
  43. G_SPI_CPOL : natural range 0 to 1 := 0;
  44. G_SPI_CPHA : natural range 0 to 1 := 0
  45. );
  46. port (
  47. --+ system if
  48. Reset_n_i : in std_logic;
  49. Clk_i : in std_logic;
  50. --+ SPI slave if
  51. SpiSclk_i : in std_logic;
  52. SpiSte_i : in std_logic;
  53. SpiMosi_i : in std_logic;
  54. SpiMiso_o : out std_logic;
  55. --+ local VAI if
  56. Data_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  57. DataValid_i : in std_logic;
  58. DataAccept_o : out std_logic;
  59. Data_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  60. DataValid_o : out std_logic;
  61. DataAccept_i : in std_logic
  62. );
  63. end component SpiSlaveE;
  64. --* testbench global clock period
  65. constant C_PERIOD : time := 5 ns;
  66. --* SPI data transfer data width
  67. constant C_DATA_WIDTH : natural := 8;
  68. --* testbench global clock
  69. signal s_clk : std_logic := '0';
  70. --* testbench global reset
  71. signal s_reset_n : std_logic := '0';
  72. --* SPI mode range subtype
  73. subtype t_spi_mode is natural range 0 to 3;
  74. --+ test done array with entry for each test
  75. signal s_test_done : boolean_vector(t_spi_mode'low to 2*t_spi_mode'high+1) := (others => false);
  76. begin
  77. --* testbench global clock
  78. s_clk <= not(s_clk) after C_PERIOD/2 when not(and_reduce(s_test_done)) else '0';
  79. --* testbench global reset
  80. s_reset_n <= '1' after 100 ns;
  81. --+ spi ste demultiplexing
  82. SpiMastersG : for mode in t_spi_mode'low to t_spi_mode'high generate
  83. signal s_sclk : std_logic;
  84. signal s_ste : std_logic;
  85. signal s_mosi : std_logic;
  86. signal s_miso : std_logic;
  87. signal s_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  88. signal s_din_valid : std_logic;
  89. signal s_din_accept : std_logic;
  90. signal s_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  91. signal s_dout_valid : std_logic;
  92. signal s_dout_accept : std_logic;
  93. begin
  94. SpiMasterStimP : process is
  95. begin
  96. wait until s_reset_n = '1';
  97. for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
  98. s_din <= std_logic_vector(to_unsigned(i, C_DATA_WIDTH));
  99. s_din_valid <= '1';
  100. wait until rising_edge(s_clk) and s_din_accept = '1';
  101. s_din_valid <= '0';
  102. wait until rising_edge(s_clk);
  103. end loop;
  104. wait;
  105. end process SpiMasterStimP;
  106. i_SpiMasterE : SpiMasterE
  107. generic map (
  108. G_DATA_WIDTH => 8,
  109. G_SPI_CPOL => mode / 2,
  110. G_SPI_CPHA => mode mod 2,
  111. G_SCLK_DIVIDER => 10
  112. )
  113. port map (
  114. --+ system if
  115. Reset_n_i => s_reset_n,
  116. Clk_i => s_clk,
  117. --+ SPI slave if
  118. SpiSclk_o => s_sclk,
  119. SpiSte_o => s_ste,
  120. SpiMosi_o => s_mosi,
  121. SpiMiso_i => s_miso,
  122. --+ local VAI if
  123. Data_i => s_din,
  124. DataValid_i => s_din_valid,
  125. DataAccept_o => s_din_accept,
  126. Data_o => s_dout,
  127. DataValid_o => s_dout_valid,
  128. DataAccept_i => s_dout_accept
  129. );
  130. SpiMasterCheckP : process is
  131. begin
  132. wait until s_reset_n = '1';
  133. for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
  134. wait until rising_edge(s_clk) and s_dout_valid = '1';
  135. s_dout_accept <= '1';
  136. assert_equal(s_dout, std_logic_vector(to_unsigned(i, C_DATA_WIDTH)));
  137. wait until rising_edge(s_clk);
  138. s_dout_accept <= '0';
  139. end loop;
  140. report "INFO: SpiMaster (mode=" & to_string(mode) & ") test successfully";
  141. s_test_done(mode) <= true;
  142. wait;
  143. end process SpiMasterCheckP;
  144. -- Unit test of spi slave procedure, checks all combinations
  145. -- of cpol & cpha against spi master procedure
  146. SpiSlaveP : process is
  147. variable v_master_data : std_logic_vector(7 downto 0) := (others => '0');
  148. begin
  149. for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
  150. spi_slave (data_in => v_master_data,
  151. data_out => v_master_data,
  152. sclk => s_sclk,
  153. ste => s_ste,
  154. mosi => s_mosi,
  155. miso => s_miso,
  156. cpol => mode / 2,
  157. cpha => mode mod 2
  158. );
  159. assert_equal(v_master_data, std_logic_vector(to_unsigned(i, C_DATA_WIDTH)));
  160. v_master_data := std_logic_vector(unsigned(v_master_data) + 1);
  161. end loop;
  162. wait;
  163. end process SpiSlaveP;
  164. end generate SpiMastersG;
  165. --+ spi ste demultiplexing
  166. SpiSlavesG : for mode in t_spi_mode'low to t_spi_mode'high generate
  167. signal s_sclk : std_logic;
  168. signal s_ste : std_logic;
  169. signal s_mosi : std_logic;
  170. signal s_miso : std_logic;
  171. signal s_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  172. signal s_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  173. signal s_dout_valid : std_logic;
  174. signal s_dout_accept : std_logic;
  175. begin
  176. -- Unit test of spi master procedure, checks all combinations
  177. -- of cpol & cpha against spi slave procedure
  178. SpiMasterP : process is
  179. variable v_slave_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
  180. begin
  181. s_sclk <= '1';
  182. s_ste <= '1';
  183. s_mosi <= '1';
  184. wait until s_reset_n = '1';
  185. for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
  186. spi_master (data_in => std_logic_vector(to_unsigned(i, C_DATA_WIDTH)),
  187. data_out => v_slave_data,
  188. sclk => s_sclk,
  189. ste => s_ste,
  190. mosi => s_mosi,
  191. miso => s_miso,
  192. cpol => mode / 2,
  193. cpha => mode mod 2,
  194. period => 100 ns
  195. );
  196. assert_equal(v_slave_data, std_logic_vector(to_unsigned(i, C_DATA_WIDTH)));
  197. end loop;
  198. report "INFO: SpiSlave (mode=" & to_string(mode) & ") test successfully";
  199. s_test_done(mode+4) <= true;
  200. wait;
  201. end process SpiMasterP;
  202. s_din <= std_logic_vector(unsigned(s_dout) + 1);
  203. i_SpiSlaveE : SpiSlaveE
  204. generic map (
  205. G_DATA_WIDTH => 8,
  206. G_SPI_CPOL => mode / 2,
  207. G_SPI_CPHA => mode mod 2
  208. )
  209. port map (
  210. --+ system if
  211. Reset_n_i => s_reset_n,
  212. Clk_i => s_clk,
  213. --+ SPI slave if
  214. SpiSclk_i => s_sclk,
  215. SpiSte_i => s_ste,
  216. SpiMosi_i => s_mosi,
  217. SpiMiso_o => s_miso,
  218. --+ local VAI if
  219. Data_i => s_din,
  220. DataValid_i => s_dout_valid,
  221. DataAccept_o => s_dout_accept,
  222. Data_o => s_dout,
  223. DataValid_o => s_dout_valid,
  224. DataAccept_i => s_dout_accept
  225. );
  226. end generate SpiSlavesG;
  227. end architecture sim;