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.

328 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.UtilsP.all;
  11. library std;
  12. use std.env.all;
  13. entity WishBoneT is
  14. end entity WishBoneT;
  15. architecture sim of WishBoneT is
  16. component WishBoneMasterE is
  17. generic (
  18. G_ADR_WIDTH : positive := 8; --* address bus width
  19. G_DATA_WIDTH : positive := 8 --* data bus width
  20. );
  21. port (
  22. --+ wishbone system if
  23. WbRst_i : in std_logic;
  24. WbClk_i : in std_logic;
  25. --+ wishbone outputs
  26. WbCyc_o : out std_logic;
  27. WbStb_o : out std_logic;
  28. WbWe_o : out std_logic;
  29. WbAdr_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
  30. WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  31. --+ wishbone inputs
  32. WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  33. WbAck_i : in std_logic;
  34. WbErr_i : in std_logic;
  35. --+ local register if
  36. LocalWen_i : in std_logic;
  37. LocalRen_i : in std_logic;
  38. LocalAdress_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
  39. LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  40. LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  41. LocalAck_o : out std_logic;
  42. LocalError_o : out std_logic
  43. );
  44. end component WishBoneMasterE;
  45. component WishBoneSlaveE is
  46. generic (
  47. G_ADR_WIDTH : positive := 8; --* address bus width
  48. G_DATA_WIDTH : positive := 8 --* data bus width
  49. );
  50. port (
  51. --+ wishbone system if
  52. WbRst_i : in std_logic;
  53. WbClk_i : in std_logic;
  54. --+ wishbone inputs
  55. WbCyc_i : in std_logic;
  56. WbStb_i : in std_logic;
  57. WbWe_i : in std_logic;
  58. WbAdr_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
  59. WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
  60. --* wishbone outputs
  61. WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  62. WbAck_o : out std_logic;
  63. WbErr_o : out std_logic;
  64. --+ local register if
  65. LocalWen_o : out std_logic;
  66. LocalRen_o : out std_logic;
  67. LocalAdress_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
  68. LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
  69. LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0)
  70. );
  71. end component WishBoneSlaveE;
  72. --* testbench global clock period
  73. constant C_PERIOD : time := 5 ns;
  74. --* Wishbone data width
  75. constant C_DATA_WIDTH : natural := 8;
  76. --* Wishbone address width
  77. constant C_ADDRESS_WIDTH : natural := 8;
  78. type t_wishbone is record
  79. --+ wishbone outputs
  80. Cyc : std_logic;
  81. Stb : std_logic;
  82. We : std_logic;
  83. Adr : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  84. WDat : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  85. --+ wishbone inputs
  86. RDat : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  87. Ack : std_logic;
  88. Err : std_logic;
  89. end record t_wishbone;
  90. signal s_wishbone : t_wishbone := ('Z', 'Z', 'Z', (others => 'Z'), (others => 'Z'), (others => 'Z'), 'Z', 'Z');
  91. --* testbench global clock
  92. signal s_wb_clk : std_logic := '1';
  93. --* testbench global reset
  94. signal s_wb_reset : std_logic := '1';
  95. signal s_master_local_wen : std_logic;
  96. signal s_master_local_ren : std_logic;
  97. signal s_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  98. signal s_master_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  99. signal s_master_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  100. signal s_master_local_ack : std_logic;
  101. signal s_master_local_error : std_logic;
  102. signal s_slave_local_wen : std_logic;
  103. signal s_slave_local_ren : std_logic;
  104. signal s_slave_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  105. signal s_slave_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  106. signal s_slave_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  107. type t_register is array (0 to integer'(2**C_ADDRESS_WIDTH-1)) of std_logic_vector(C_DATA_WIDTH-1 downto 0);
  108. package SlvQueue is new libvhdl.QueueP
  109. generic map (
  110. QUEUE_TYPE => std_logic_vector(C_ADDRESS_WIDTH-1 downto 0),
  111. MAX_LEN => 2**C_ADDRESS_WIDTH,
  112. to_string => to_hstring
  113. );
  114. shared variable sv_wishbone_queue : SlvQueue.t_list_queue;
  115. package IntSlvDict is new libvhdl.DictP
  116. generic map (KEY_TYPE => integer,
  117. VALUE_TYPE => std_logic_vector,
  118. key_to_string => to_string,
  119. value_to_string => to_hstring);
  120. shared variable sv_wishbone_dict : IntSlvDict.t_dict;
  121. shared variable sv_coverage : CovPType;
  122. begin
  123. --* testbench global clock
  124. s_wb_clk <= not(s_wb_clk) after C_PERIOD/2;
  125. --* testbench global reset
  126. s_wb_reset <= '0' after C_PERIOD * 5;
  127. QueueInitP : process is
  128. begin
  129. sv_wishbone_queue.init(false);
  130. sv_wishbone_dict.init(false);
  131. wait;
  132. end process QueueInitP;
  133. WbMasterLocalP : process is
  134. variable v_random : RandomPType;
  135. variable v_wbmaster_address : integer;
  136. variable v_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
  137. variable v_wbmaster_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
  138. begin
  139. v_random.InitSeed(v_random'instance_name);
  140. v_wbmaster_data := (others => '0');
  141. s_master_local_din <= (others => '0');
  142. s_master_local_adress <= (others => '0');
  143. s_master_local_wen <= '0';
  144. s_master_local_ren <= '0';
  145. wait until s_wb_reset = '0';
  146. -- write the wishbone slave registers
  147. sv_coverage.AddBins(GenBin(0));
  148. sv_coverage.AddBins(GenBin(integer'(2**C_ADDRESS_WIDTH-1)));
  149. sv_coverage.AddBins(GenBin(1, integer'(2**C_ADDRESS_WIDTH-2), 64));
  150. while not sv_coverage.IsCovered loop
  151. v_wbmaster_address := sv_coverage.RandCovPoint;
  152. v_wbmaster_data := v_random.RandSlv(C_DATA_WIDTH);
  153. s_master_local_din <= v_wbmaster_data;
  154. s_master_local_adress <= uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH);
  155. s_master_local_wen <= '1';
  156. wait until rising_edge(s_wb_clk);
  157. s_master_local_din <= (others => '0');
  158. s_master_local_adress <= (others => '0');
  159. s_master_local_wen <= '0';
  160. wait until rising_edge(s_wb_clk) and s_master_local_ack = '1';
  161. sv_wishbone_queue.push(uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH));
  162. sv_wishbone_dict.set(v_wbmaster_address, v_wbmaster_data);
  163. sv_coverage.ICover(v_wbmaster_address);
  164. end loop;
  165. -- read back and check the wishbone slave registers
  166. while not(sv_wishbone_queue.is_empty) loop
  167. sv_wishbone_queue.pop(v_master_local_adress);
  168. s_master_local_adress <= v_master_local_adress;
  169. s_master_local_ren <= '1';
  170. wait until rising_edge(s_wb_clk);
  171. s_master_local_adress <= (others => '0');
  172. s_master_local_ren <= '0';
  173. wait until rising_edge(s_wb_clk) and s_master_local_ack = '1';
  174. sv_wishbone_dict.get(slv_to_uint(v_master_local_adress), v_wbmaster_data);
  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. finish;
  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_wishbone.Cyc,
  203. WbStb_o => s_wishbone.Stb,
  204. WbWe_o => s_wishbone.We,
  205. WbAdr_o => s_wishbone.Adr,
  206. WbDat_o => s_wishbone.WDat,
  207. --+ wishbone inputs
  208. WbDat_i => s_wishbone.RDat,
  209. WbAck_i => s_wishbone.Ack,
  210. WbErr_i => s_wishbone.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_wishbone.Cyc
  231. report "ERROR: Wishbone cycle should be 0b" & to_string(v_valid_access) & " instead of 0b" & to_string(s_wishbone.Cyc)
  232. severity failure;
  233. if (v_valid_access = '1') then
  234. WB_ADDR : assert s_wishbone.Adr = v_master_local_adress
  235. report "ERROR: Wishbone address 0x" & to_hstring(s_wishbone.Adr) & " differ from local address 0x" & to_hstring(v_master_local_adress)
  236. severity failure;
  237. if (s_wishbone.We = '1') then
  238. WB_DATA : assert s_wishbone.WDat = v_master_local_data
  239. report "ERROR: Wishbone data 0x" & to_hstring(s_wishbone.WDat) & " 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_wishbone.Cyc,
  255. WbStb_i => s_wishbone.Stb,
  256. WbWe_i => s_wishbone.We,
  257. WbAdr_i => s_wishbone.Adr,
  258. WbDat_i => s_wishbone.WDat,
  259. --* wishbone outputs
  260. WbDat_o => s_wishbone.RDat,
  261. WbAck_o => s_wishbone.Ack,
  262. WbErr_o => s_wishbone.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;