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.

304 lines
10 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. use osvvm.CoveragePkg.all;
  20. library libvhdl;
  21. use libvhdl.AssertP.all;
  22. use libvhdl.SimP.all;
  23. use libvhdl.UtilsP.all;
  24. library work;
  25. use work.WishBoneP.all;
  26. library std;
  27. use std.env.all;
  28. entity WishBoneT is
  29. end entity WishBoneT;
  30. architecture sim of WishBoneT is
  31. --* testbench global clock period
  32. constant C_PERIOD : time := 5 ns;
  33. --* Wishbone data width
  34. constant C_DATA_WIDTH : natural := 8;
  35. --* Wishbone address width
  36. constant C_ADDRESS_WIDTH : natural := 8;
  37. signal s_wishbone : t_wishbone_if(
  38. Adr(C_ADDRESS_WIDTH-1 downto 0),
  39. WDat(C_DATA_WIDTH-1 downto 0),
  40. RDat(C_DATA_WIDTH-1 downto 0)
  41. );
  42. --* testbench global clock
  43. signal s_wb_clk : std_logic := '1';
  44. --* testbench global reset
  45. signal s_wb_reset : std_logic := '1';
  46. signal s_master_local_wen : std_logic;
  47. signal s_master_local_ren : std_logic;
  48. signal s_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  49. signal s_master_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  50. signal s_master_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  51. signal s_master_local_ack : std_logic;
  52. signal s_master_local_error : std_logic;
  53. signal s_slave_local_wen : std_logic;
  54. signal s_slave_local_ren : std_logic;
  55. signal s_slave_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  56. signal s_slave_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  57. signal s_slave_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  58. package SlvQueue is new libvhdl.QueueP
  59. generic map (
  60. QUEUE_TYPE => std_logic_vector(C_ADDRESS_WIDTH-1 downto 0),
  61. MAX_LEN => 2**C_ADDRESS_WIDTH,
  62. to_string => to_hstring
  63. );
  64. shared variable sv_wishbone_queue : SlvQueue.t_list_queue;
  65. package IntSlvDict is new libvhdl.DictP
  66. generic map (KEY_TYPE => natural,
  67. VALUE_TYPE => std_logic_vector,
  68. key_to_string => to_string,
  69. value_to_string => to_hstring);
  70. shared variable sv_wb_master_dict : IntSlvDict.t_dict;
  71. shared variable sv_wb_slave_dict : IntSlvDict.t_dict;
  72. shared variable sv_coverage : CovPType;
  73. begin
  74. --* testbench global clock
  75. s_wb_clk <= not(s_wb_clk) after C_PERIOD/2;
  76. --* testbench global reset
  77. s_wb_reset <= '0' after C_PERIOD * 5;
  78. QueueInitP : process is
  79. begin
  80. sv_wishbone_queue.init(false);
  81. sv_wb_master_dict.init(false);
  82. sv_wb_slave_dict.init(false);
  83. wait;
  84. end process QueueInitP;
  85. WbMasterLocalP : process is
  86. variable v_random : RandomPType;
  87. variable v_wbmaster_address : integer;
  88. variable v_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  89. variable v_wbmaster_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  90. begin
  91. v_random.InitSeed(v_random'instance_name);
  92. v_wbmaster_data := (others => '0');
  93. s_master_local_din <= (others => '0');
  94. s_master_local_adress <= (others => '0');
  95. s_master_local_wen <= '0';
  96. s_master_local_ren <= '0';
  97. wait until s_wb_reset = '0';
  98. -- write the wishbone slave registers
  99. sv_coverage.AddBins(GenBin(0));
  100. sv_coverage.AddBins(GenBin(integer'(2**C_ADDRESS_WIDTH-1)));
  101. sv_coverage.AddBins(GenBin(1, integer'(2**C_ADDRESS_WIDTH-2), 64));
  102. while not sv_coverage.IsCovered loop
  103. v_wbmaster_address := sv_coverage.RandCovPoint;
  104. v_wbmaster_data := v_random.RandSlv(C_DATA_WIDTH);
  105. s_master_local_din <= v_wbmaster_data;
  106. s_master_local_adress <= uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH);
  107. s_master_local_wen <= '1';
  108. wait until rising_edge(s_wb_clk);
  109. s_master_local_din <= (others => '0');
  110. s_master_local_adress <= (others => '0');
  111. s_master_local_wen <= '0';
  112. wait until rising_edge(s_wb_clk) and s_master_local_ack = '1';
  113. sv_wishbone_queue.push(uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH));
  114. sv_wb_master_dict.set(v_wbmaster_address, v_wbmaster_data);
  115. sv_coverage.ICover(v_wbmaster_address);
  116. end loop;
  117. -- read back and check the wishbone slave registers
  118. while not(sv_wishbone_queue.is_empty) loop
  119. sv_wishbone_queue.pop(v_master_local_adress);
  120. s_master_local_adress <= v_master_local_adress;
  121. s_master_local_ren <= '1';
  122. wait until rising_edge(s_wb_clk);
  123. s_master_local_adress <= (others => '0');
  124. s_master_local_ren <= '0';
  125. wait until rising_edge(s_wb_clk) and s_master_local_ack = '1';
  126. sv_wb_master_dict.get(slv_to_uint(v_master_local_adress), v_wbmaster_data);
  127. assert_equal(s_master_local_dout, v_wbmaster_data);
  128. end loop;
  129. -- test local write & read at the same time
  130. wait until rising_edge(s_wb_clk);
  131. s_master_local_wen <= '1';
  132. s_master_local_ren <= '1';
  133. wait until rising_edge(s_wb_clk);
  134. s_master_local_wen <= '0';
  135. s_master_local_ren <= '0';
  136. wait until rising_edge(s_wb_clk);
  137. -- Test finished
  138. report "INFO: Test successfully finished!";
  139. sv_coverage.SetMessage("WishboneT coverage results");
  140. sv_coverage.WriteBin;
  141. finish;
  142. wait;
  143. end process WbMasterLocalP;
  144. i_WishBoneMasterE : WishBoneMasterE
  145. generic map (
  146. Coverage => false,
  147. Formal => false,
  148. Simulation => true,
  149. AddressWidth => C_ADDRESS_WIDTH,
  150. DataWidth => C_DATA_WIDTH
  151. )
  152. port map (
  153. --+ wishbone system if
  154. WbRst_i => s_wb_reset,
  155. WbClk_i => s_wb_clk,
  156. --+ wishbone outputs
  157. WbCyc_o => s_wishbone.Cyc,
  158. WbStb_o => s_wishbone.Stb,
  159. WbWe_o => s_wishbone.We,
  160. WbAdr_o => s_wishbone.Adr,
  161. WbDat_o => s_wishbone.WDat,
  162. --+ wishbone inputs
  163. WbDat_i => s_wishbone.RDat,
  164. WbAck_i => s_wishbone.Ack,
  165. WbErr_i => s_wishbone.Err,
  166. --+ local register if
  167. LocalWen_i => s_master_local_wen,
  168. LocalRen_i => s_master_local_ren,
  169. LocalAdress_i => s_master_local_adress,
  170. LocalData_i => s_master_local_din,
  171. LocalData_o => s_master_local_dout,
  172. LocalAck_o => s_master_local_ack,
  173. LocalError_o => s_master_local_error
  174. );
  175. WishBoneBusMonitorP : process is
  176. variable v_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  177. variable v_master_local_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  178. variable v_valid_access : std_logic;
  179. begin
  180. wait until (s_master_local_wen = '1' or s_master_local_ren = '1') and rising_edge(s_wb_clk);
  181. v_master_local_adress := s_master_local_adress;
  182. v_master_local_data := s_master_local_din;
  183. v_valid_access := s_master_local_wen xor s_master_local_ren;
  184. wait until rising_edge(s_wb_clk);
  185. WB_CYC : assert v_valid_access = s_wishbone.Cyc
  186. report "ERROR: Wishbone cycle should be 0b" & to_string(v_valid_access) & " instead of 0b" & to_string(s_wishbone.Cyc)
  187. severity failure;
  188. if (v_valid_access = '1') then
  189. WB_ADDR : assert s_wishbone.Adr = v_master_local_adress
  190. report "ERROR: Wishbone address 0x" & to_hstring(s_wishbone.Adr) & " differ from local address 0x" & to_hstring(v_master_local_adress)
  191. severity failure;
  192. if (s_wishbone.We = '1') then
  193. WB_DATA : assert s_wishbone.WDat = v_master_local_data
  194. report "ERROR: Wishbone data 0x" & to_hstring(s_wishbone.WDat) & " differ from local data 0x" & to_hstring(v_master_local_data)
  195. severity failure;
  196. end if;
  197. end if;
  198. end process WishBoneBusMonitorP;
  199. i_WishBoneSlaveE : WishBoneSlaveE
  200. generic map (
  201. Formal => false,
  202. Simulation => true,
  203. AddressWidth => C_ADDRESS_WIDTH,
  204. DataWidth => C_DATA_WIDTH
  205. )
  206. port map (
  207. --+ wishbone system if
  208. WbRst_i => s_wb_reset,
  209. WbClk_i => s_wb_clk,
  210. --+ wishbone inputs
  211. WbCyc_i => s_wishbone.Cyc,
  212. WbStb_i => s_wishbone.Stb,
  213. WbWe_i => s_wishbone.We,
  214. WbAdr_i => s_wishbone.Adr,
  215. WbDat_i => s_wishbone.WDat,
  216. --* wishbone outputs
  217. WbDat_o => s_wishbone.RDat,
  218. WbAck_o => s_wishbone.Ack,
  219. WbErr_o => s_wishbone.Err,
  220. --+ local register if
  221. LocalWen_o => s_slave_local_wen,
  222. LocalRen_o => s_slave_local_ren,
  223. LocalAdress_o => s_slave_local_adress,
  224. LocalData_o => s_slave_local_dout,
  225. LocalData_i => s_slave_local_din
  226. );
  227. WbSlaveLocalP : process is
  228. begin
  229. wait until rising_edge(s_wb_clk);
  230. if (s_wb_reset = '1') then
  231. s_slave_local_din <= (others => '0');
  232. else
  233. if (s_slave_local_wen = '1') then
  234. sv_wb_slave_dict.set(slv_to_uint(s_slave_local_adress), s_slave_local_dout);
  235. elsif (s_slave_local_ren = '1') then
  236. WB_SLAVE_REG : assert sv_wb_slave_dict.hasKey(slv_to_uint(s_slave_local_adress))
  237. report "ERROR: Requested register at addr 0x" & to_hstring(s_slave_local_adress) & " not written before"
  238. severity failure;
  239. s_slave_local_din <= sv_wb_slave_dict.get(slv_to_uint(s_slave_local_adress));
  240. end if;
  241. end if;
  242. end process WbSlaveLocalP;
  243. i_WishBoneChecker : WishBoneCheckerE
  244. port map (
  245. --+ wishbone system if
  246. WbRst_i => s_wb_reset,
  247. WbClk_i => s_wb_clk,
  248. --+ wishbone outputs
  249. WbMCyc_i => s_wishbone.Cyc,
  250. WbMStb_i => s_wishbone.Stb,
  251. WbMWe_i => s_wishbone.We,
  252. WbMAdr_i => s_wishbone.Adr,
  253. WbMDat_i => s_wishbone.WDat,
  254. --+ wishbone inputs
  255. WbSDat_i => s_wishbone.RDat,
  256. WbSAck_i => s_wishbone.Ack,
  257. WbSErr_i => s_wishbone.Err,
  258. WbRty_i => '0'
  259. );
  260. end architecture sim;