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.

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