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.

324 lines
12 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. -- test local write & read at the same time
  178. wait until rising_edge(s_wb_clk);
  179. s_master_local_wen <= '1';
  180. s_master_local_ren <= '1';
  181. wait until rising_edge(s_wb_clk);
  182. s_master_local_wen <= '0';
  183. s_master_local_ren <= '0';
  184. wait until rising_edge(s_wb_clk);
  185. -- Test finished
  186. report "INFO: Test successfully finished!";
  187. sv_coverage.SetMessage("WishboneT coverage results");
  188. sv_coverage.WriteBin;
  189. s_test_done <= true;
  190. wait;
  191. end process WbMasterLocalP;
  192. i_WishBoneMasterE : WishBoneMasterE
  193. generic map (
  194. G_ADR_WIDTH => C_ADDRESS_WIDTH,
  195. G_DATA_WIDTH => C_DATA_WIDTH
  196. )
  197. port map (
  198. --+ wishbone system if
  199. WbRst_i => s_wb_reset,
  200. WbClk_i => s_wb_clk,
  201. --+ wishbone outputs
  202. WbCyc_o => s_wb_cyc,
  203. WbStb_o => s_wb_stb,
  204. WbWe_o => s_wb_we,
  205. WbAdr_o => s_wb_adr,
  206. WbDat_o => s_wb_master_data,
  207. --+ wishbone inputs
  208. WbDat_i => s_wb_slave_data,
  209. WbAck_i => s_wb_ack,
  210. WbErr_i => s_wb_err,
  211. --+ local register if
  212. LocalWen_i => s_master_local_wen,
  213. LocalRen_i => s_master_local_ren,
  214. LocalAdress_i => s_master_local_adress,
  215. LocalData_i => s_master_local_din,
  216. LocalData_o => s_master_local_dout,
  217. LocalAck_o => s_master_local_ack,
  218. LocalError_o => s_master_local_error
  219. );
  220. WishBoneBusMonitorP : process is
  221. variable v_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  222. variable v_master_local_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  223. variable v_valid_access : std_logic;
  224. begin
  225. wait until (s_master_local_wen = '1' or s_master_local_ren = '1') and rising_edge(s_wb_clk);
  226. v_master_local_adress := s_master_local_adress;
  227. v_master_local_data := s_master_local_din;
  228. v_valid_access := s_master_local_wen xor s_master_local_ren;
  229. wait until rising_edge(s_wb_clk);
  230. WB_CYC : assert v_valid_access = s_wb_cyc
  231. report "ERROR: Wishbone cycle should be 0b" & to_string(v_valid_access) & " instead of 0b" & to_string(s_wb_cyc)
  232. severity failure;
  233. if (v_valid_access = '1') then
  234. WB_ADDR : assert s_wb_adr = v_master_local_adress
  235. report "ERROR: Wishbone address 0x" & to_hstring(s_wb_adr) & " differ from local address 0x" & to_hstring(v_master_local_adress)
  236. severity failure;
  237. if (s_wb_we = '1') then
  238. WB_DATA : assert s_wb_master_data = v_master_local_data
  239. report "ERROR: Wishbone data 0x" & to_hstring(s_wb_master_data) & " differ from local data 0x" & to_hstring(v_master_local_data)
  240. severity failure;
  241. end if;
  242. end if;
  243. end process WishBoneBusMonitorP;
  244. i_WishBoneSlaveE : WishBoneSlaveE
  245. generic map (
  246. G_ADR_WIDTH => C_ADDRESS_WIDTH,
  247. G_DATA_WIDTH => C_DATA_WIDTH
  248. )
  249. port map (
  250. --+ wishbone system if
  251. WbRst_i => s_wb_reset,
  252. WbClk_i => s_wb_clk,
  253. --+ wishbone inputs
  254. WbCyc_i => s_wb_cyc,
  255. WbStb_i => s_wb_stb,
  256. WbWe_i => s_wb_we,
  257. WbAdr_i => s_wb_adr,
  258. WbDat_i => s_wb_master_data,
  259. --* wishbone outputs
  260. WbDat_o => s_wb_slave_data,
  261. WbAck_o => s_wb_ack,
  262. WbErr_o => s_wb_err,
  263. --+ local register if
  264. LocalWen_o => s_slave_local_wen,
  265. LocalRen_o => s_slave_local_ren,
  266. LocalAdress_o => s_slave_local_adress,
  267. LocalData_o => s_slave_local_dout,
  268. LocalData_i => s_slave_local_din
  269. );
  270. WbSlaveLocalP : process is
  271. variable v_register : t_register := (others => (others => '0'));
  272. begin
  273. wait until rising_edge(s_wb_clk);
  274. if (s_wb_reset = '1') then
  275. v_register := (others => (others => '0'));
  276. s_slave_local_din <= (others => '0');
  277. else
  278. if (s_slave_local_wen = '1') then
  279. v_register(slv_to_uint(s_slave_local_adress)) := s_slave_local_dout;
  280. elsif (s_slave_local_ren = '1') then
  281. s_slave_local_din <= v_register(slv_to_uint(s_slave_local_adress));
  282. end if;
  283. end if;
  284. end process WbSlaveLocalP;
  285. end architecture sim;