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.

308 lines
11 KiB

  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use ieee.numeric_std.all;
  4. --+ including vhdl 2008 libraries
  5. --+ These lines can be commented out when using
  6. --+ a simulator with built-in VHDL 2008 support
  7. --library ieee_proposed;
  8. -- use ieee_proposed.standard_additions.all;
  9. -- use ieee_proposed.std_logic_1164_additions.all;
  10. -- use ieee_proposed.numeric_std_additions.all;
  11. library osvvm;
  12. use osvvm.RandomPkg.all;
  13. use osvvm.CoveragePkg.all;
  14. library libvhdl;
  15. use libvhdl.AssertP.all;
  16. use libvhdl.SimP.all;
  17. use libvhdl.QueueP.all;
  18. use libvhdl.DictP.all;
  19. use libvhdl.UtilsP.all;
  20. entity WishBoneT is
  21. end entity WishBoneT;
  22. architecture sim of WishBoneT is
  23. component WishBoneMasterE is
  24. generic (
  25. G_ADR_WIDTH : positive := 8; --* address bus width
  26. G_DATA_WIDTH : positive := 8 --* data bus width
  27. );
  28. port (
  29. --+ wishbone system if
  30. WbRst_i : in std_logic;
  31. WbClk_i : in std_logic;
  32. --+ wishbone outputs
  33. WbCyc_o : out std_logic;
  34. WbStb_o : out std_logic;
  35. WbWe_o : out std_logic;
  36. WbAdr_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
  37. WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  38. --+ wishbone inputs
  39. WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  40. WbAck_i : in std_logic;
  41. WbErr_i : in std_logic;
  42. --+ local register if
  43. LocalWen_i : in std_logic;
  44. LocalRen_i : in std_logic;
  45. LocalAdress_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
  46. LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  47. LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  48. LocalAck_o : out std_logic;
  49. LocalError_o : out std_logic
  50. );
  51. end component WishBoneMasterE;
  52. component WishBoneSlaveE is
  53. generic (
  54. G_ADR_WIDTH : positive := 8; --* address bus width
  55. G_DATA_WIDTH : positive := 8 --* data bus width
  56. );
  57. port (
  58. --+ wishbone system if
  59. WbRst_i : in std_logic;
  60. WbClk_i : in std_logic;
  61. --+ wishbone inputs
  62. WbCyc_i : in std_logic;
  63. WbStb_i : in std_logic;
  64. WbWe_i : in std_logic;
  65. WbAdr_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
  66. WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  67. --* wishbone outputs
  68. WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  69. WbAck_o : out std_logic;
  70. WbErr_o : out std_logic;
  71. --+ local register if
  72. LocalWen_o : out std_logic;
  73. LocalRen_o : out std_logic;
  74. LocalAdress_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
  75. LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  76. LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0)
  77. );
  78. end component WishBoneSlaveE;
  79. --* testbench global clock period
  80. constant C_PERIOD : time := 5 ns;
  81. --* Wishbone data width
  82. constant C_DATA_WIDTH : natural := 8;
  83. --* Wishbone address width
  84. constant C_ADDRESS_WIDTH : natural := 8;
  85. --* testbench global clock
  86. signal s_wb_clk : std_logic := '1';
  87. --* testbench global reset
  88. signal s_wb_reset : std_logic := '1';
  89. --+ test done array with entry for each test
  90. signal s_test_done : boolean;
  91. signal s_wb_cyc : std_logic;
  92. signal s_wb_stb : std_logic;
  93. signal s_wb_we : std_logic;
  94. signal s_wb_adr : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  95. signal s_wb_master_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  96. signal s_wb_slave_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  97. signal s_wb_ack : std_logic;
  98. signal s_wb_err : std_logic;
  99. signal s_master_local_wen : std_logic;
  100. signal s_master_local_ren : std_logic;
  101. signal s_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  102. signal s_master_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  103. signal s_master_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  104. signal s_master_local_ack : std_logic;
  105. signal s_master_local_error : std_logic;
  106. signal s_slave_local_wen : std_logic;
  107. signal s_slave_local_ren : std_logic;
  108. signal s_slave_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  109. signal s_slave_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  110. signal s_slave_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  111. type t_register is array (0 to integer'(2**C_ADDRESS_WIDTH-1)) of std_logic_vector(C_DATA_WIDTH-1 downto 0);
  112. shared variable sv_wishbone_queue : t_list_queue;
  113. shared variable sv_wishbone_dict : t_dict;
  114. shared variable sv_coverage : CovPType;
  115. begin
  116. --* testbench global clock
  117. s_wb_clk <= not(s_wb_clk) after C_PERIOD/2 when not(s_test_done) else '0';
  118. --* testbench global reset
  119. s_wb_reset <= '0' after C_PERIOD * 5;
  120. QueueInitP : process is
  121. begin
  122. sv_wishbone_queue.init(2**C_ADDRESS_WIDTH);
  123. sv_wishbone_dict.init(false);
  124. wait;
  125. end process QueueInitP;
  126. WbMasterLocalP : process is
  127. variable v_random : RandomPType;
  128. variable v_wbmaster_address : integer;
  129. variable v_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  130. variable v_wbmaster_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  131. variable v_error : t_dict_error;
  132. begin
  133. v_random.InitSeed(v_random'instance_name);
  134. v_wbmaster_data := (others => '0');
  135. s_master_local_din <= (others => '0');
  136. s_master_local_adress <= (others => '0');
  137. s_master_local_wen <= '0';
  138. s_master_local_ren <= '0';
  139. wait until s_wb_reset = '0';
  140. -- write the wishbone slave registers
  141. sv_coverage.AddBins(GenBin(0));
  142. sv_coverage.AddBins(GenBin(integer'(2**C_ADDRESS_WIDTH-1)));
  143. sv_coverage.AddBins(GenBin(1, integer'(2**C_ADDRESS_WIDTH-2), 64));
  144. while not sv_coverage.IsCovered loop
  145. v_wbmaster_address := sv_coverage.RandCovPoint;
  146. v_wbmaster_data := v_random.RandSlv(C_DATA_WIDTH);
  147. s_master_local_din <= v_wbmaster_data;
  148. s_master_local_adress <= uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH);
  149. s_master_local_wen <= '1';
  150. wait until rising_edge(s_wb_clk);
  151. s_master_local_din <= (others => '0');
  152. s_master_local_adress <= (others => '0');
  153. s_master_local_wen <= '0';
  154. wait until rising_edge(s_wb_clk) and s_master_local_ack = '1';
  155. sv_wishbone_queue.push(uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH));
  156. sv_wishbone_dict.set(integer'image(v_wbmaster_address), v_wbmaster_data, v_error);
  157. assert v_error = NO_ERROR
  158. report "ERROR: key error"
  159. severity failure;
  160. sv_coverage.ICover(v_wbmaster_address);
  161. end loop;
  162. -- read back and check the wishbone slave registers
  163. while not(sv_wishbone_queue.is_empty) loop
  164. sv_wishbone_queue.pop(v_master_local_adress);
  165. s_master_local_adress <= v_master_local_adress;
  166. s_master_local_ren <= '1';
  167. wait until rising_edge(s_wb_clk);
  168. s_master_local_adress <= (others => '0');
  169. s_master_local_ren <= '0';
  170. wait until rising_edge(s_wb_clk) and s_master_local_ack = '1';
  171. sv_wishbone_dict.get(integer'image(slv_to_uint(v_master_local_adress)), v_wbmaster_data, v_error);
  172. assert v_error = NO_ERROR
  173. report "ERROR: key error"
  174. severity failure;
  175. assert_equal(s_master_local_dout, v_wbmaster_data);
  176. end loop;
  177. report "INFO: Test successfully finished!";
  178. sv_coverage.SetMessage("WishboneT coverage results");
  179. sv_coverage.WriteBin;
  180. s_test_done <= true;
  181. wait;
  182. end process WbMasterLocalP;
  183. i_WishBoneMasterE : WishBoneMasterE
  184. generic map (
  185. G_ADR_WIDTH => C_ADDRESS_WIDTH,
  186. G_DATA_WIDTH => C_DATA_WIDTH
  187. )
  188. port map (
  189. --+ wishbone system if
  190. WbRst_i => s_wb_reset,
  191. WbClk_i => s_wb_clk,
  192. --+ wishbone outputs
  193. WbCyc_o => s_wb_cyc,
  194. WbStb_o => s_wb_stb,
  195. WbWe_o => s_wb_we,
  196. WbAdr_o => s_wb_adr,
  197. WbDat_o => s_wb_master_data,
  198. --+ wishbone inputs
  199. WbDat_i => s_wb_slave_data,
  200. WbAck_i => s_wb_ack,
  201. WbErr_i => s_wb_err,
  202. --+ local register if
  203. LocalWen_i => s_master_local_wen,
  204. LocalRen_i => s_master_local_ren,
  205. LocalAdress_i => s_master_local_adress,
  206. LocalData_i => s_master_local_din,
  207. LocalData_o => s_master_local_dout,
  208. LocalAck_o => s_master_local_ack,
  209. LocalError_o => s_master_local_error
  210. );
  211. WishBoneBusMonitorP : process is
  212. variable v_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  213. variable v_master_local_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  214. begin
  215. wait until s_master_local_wen = '1';
  216. v_master_local_adress := s_master_local_adress;
  217. v_master_local_data := s_master_local_din;
  218. wait until s_wb_cyc = '1';
  219. WB_ADDR : assert s_wb_adr = v_master_local_adress
  220. report "ERROR: Wishbone address 0x" & to_hstring(s_wb_adr) & " differ from local address 0x" & to_hstring(v_master_local_adress)
  221. severity failure;
  222. if (s_wb_we = '1') then
  223. WB_DATA : assert s_wb_master_data = v_master_local_data
  224. report "ERROR: Wishbone data 0x" & to_hstring(s_wb_master_data) & " differ from local data 0x" & to_hstring(v_master_local_data)
  225. severity failure;
  226. end if;
  227. end process WishBoneBusMonitorP;
  228. i_WishBoneSlaveE : WishBoneSlaveE
  229. generic map (
  230. G_ADR_WIDTH => C_ADDRESS_WIDTH,
  231. G_DATA_WIDTH => C_DATA_WIDTH
  232. )
  233. port map (
  234. --+ wishbone system if
  235. WbRst_i => s_wb_reset,
  236. WbClk_i => s_wb_clk,
  237. --+ wishbone inputs
  238. WbCyc_i => s_wb_cyc,
  239. WbStb_i => s_wb_stb,
  240. WbWe_i => s_wb_we,
  241. WbAdr_i => s_wb_adr,
  242. WbDat_i => s_wb_master_data,
  243. --* wishbone outputs
  244. WbDat_o => s_wb_slave_data,
  245. WbAck_o => s_wb_ack,
  246. WbErr_o => s_wb_err,
  247. --+ local register if
  248. LocalWen_o => s_slave_local_wen,
  249. LocalRen_o => s_slave_local_ren,
  250. LocalAdress_o => s_slave_local_adress,
  251. LocalData_o => s_slave_local_dout,
  252. LocalData_i => s_slave_local_din
  253. );
  254. WbSlaveLocalP : process is
  255. variable v_register : t_register := (others => (others => '0'));
  256. begin
  257. wait until rising_edge(s_wb_clk);
  258. if (s_wb_reset = '1') then
  259. v_register := (others => (others => '0'));
  260. s_slave_local_din <= (others => '0');
  261. else
  262. if (s_slave_local_wen = '1') then
  263. v_register(slv_to_uint(s_slave_local_adress)) := s_slave_local_dout;
  264. elsif (s_slave_local_ren = '1') then
  265. s_slave_local_din <= v_register(slv_to_uint(s_slave_local_adress));
  266. end if;
  267. end if;
  268. end process WbSlaveLocalP;
  269. end architecture sim;