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.

162 lines
4.8 KiB

  1. -- Copyright (c) 2014 - 2022 by Torsten Meissner
  2. --
  3. -- Licensed under the Apache License, Version 2.0 (the "License");
  4. -- you may not use this file except in compliance with the License.
  5. -- You may obtain a copy of the License at
  6. --
  7. -- https://www.apache.org/licenses/LICENSE-2.0
  8. --
  9. -- Unless required by applicable law or agreed to in writing, software
  10. -- distributed under the License is distributed on an "AS IS" BASIS,
  11. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. -- See the License for the specific language governing permissions and
  13. -- limitations under the License.
  14. library ieee;
  15. use ieee.std_logic_1164.all;
  16. use ieee.numeric_std.all;
  17. library osvvm;
  18. use osvvm.RandomPkg.all;
  19. library libvhdl;
  20. use libvhdl.AssertP.all;
  21. use libvhdl.SimP.all;
  22. use libvhdl.UtilsP.all;
  23. entity SimT is
  24. end entity SimT;
  25. architecture sim of SimT is
  26. --* testbench global clock period
  27. constant C_PERIOD : time := 5 ns;
  28. --* SPI data transfer data width
  29. constant C_DATA_WIDTH : natural := 8;
  30. signal s_tests_done : boolean_vector(0 to 1) := (others => false);
  31. signal s_clk : std_logic := '0';
  32. signal s_sclk : std_logic;
  33. signal s_ste : std_logic;
  34. signal s_mosi : std_logic;
  35. signal s_miso : std_logic;
  36. package SlvQueue is new libvhdl.QueueP
  37. generic map (
  38. QUEUE_TYPE => std_logic_vector(C_DATA_WIDTH-1 downto 0),
  39. MAX_LEN => 32,
  40. to_string => to_hstring
  41. );
  42. shared variable sv_mosi_queue : SlvQueue.t_list_queue;
  43. shared variable sv_miso_queue : SlvQueue.t_list_queue;
  44. begin
  45. s_clk <= not(s_clk) after C_PERIOD when not(and_reduce(s_tests_done)) else '0';
  46. QueueInitP : process is
  47. begin
  48. sv_mosi_queue.init(false);
  49. sv_miso_queue.init(false);
  50. wait;
  51. end process QueueInitP;
  52. SimTestP : process is
  53. variable v_time : time;
  54. begin
  55. wait until s_clk = '1';
  56. v_time := now;
  57. wait_cycles(s_clk, 10);
  58. assert (now - v_time) = C_PERIOD * 20
  59. severity failure;
  60. s_tests_done(0) <= true;
  61. report "INFO: wait_cycles() procedure tests finished successfully";
  62. wait;
  63. end process SimTestP;
  64. -- Unit test of spi master procedure, checks all combinations
  65. -- of cpol & cpha against spi slave procedure
  66. SpiMasterP : process is
  67. variable v_send_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
  68. variable v_receive_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
  69. variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
  70. variable v_random : RandomPType;
  71. begin
  72. v_random.InitSeed(v_random'instance_name);
  73. for direction in 0 to 1 loop
  74. for mode in 0 to 3 loop
  75. for i in 0 to 255 loop
  76. v_send_data := v_random.RandSlv(C_DATA_WIDTH);
  77. sv_mosi_queue.push(v_send_data);
  78. spi_master (data_in => v_send_data,
  79. data_out => v_receive_data,
  80. sclk => s_sclk,
  81. ste => s_ste,
  82. mosi => s_mosi,
  83. miso => s_miso,
  84. dir => direction,
  85. cpol => mode / 2,
  86. cpha => mode mod 2,
  87. period => 1 us
  88. );
  89. sv_miso_queue.pop(v_queue_data);
  90. assert_equal(v_receive_data, v_queue_data);
  91. end loop;
  92. end loop;
  93. end loop;
  94. wait;
  95. end process SpiMasterP;
  96. -- Unit test of spi slave procedure, checks all combinations
  97. -- of cpol & cpha against spi master procedure
  98. SpiSlaveP : process is
  99. variable v_send_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
  100. variable v_receive_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
  101. variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
  102. variable v_random : RandomPType;
  103. begin
  104. v_random.InitSeed(v_random'instance_name);
  105. for direction in 0 to 1 loop
  106. for mode in 0 to 3 loop
  107. for i in 0 to 255 loop
  108. v_send_data := v_random.RandSlv(C_DATA_WIDTH);
  109. sv_miso_queue.push(v_send_data);
  110. spi_slave (data_in => v_send_data,
  111. data_out => v_receive_data,
  112. sclk => s_sclk,
  113. ste => s_ste,
  114. mosi => s_mosi,
  115. miso => s_miso,
  116. dir => direction,
  117. cpol => mode / 2,
  118. cpha => mode mod 2
  119. );
  120. sv_mosi_queue.pop(v_queue_data);
  121. assert_equal(v_receive_data, v_queue_data);
  122. end loop;
  123. end loop;
  124. end loop;
  125. report "INFO: All tests of valid spi_master() & spi_slave() combinations finished successfully";
  126. s_tests_done(1) <= true;
  127. wait;
  128. end process SpiSlaveP;
  129. end architecture sim;