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.

288 lines
9.6 KiB

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