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.

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