library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library osvvm; use osvvm.RandomPkg.all; use osvvm.CoveragePkg.all; library libvhdl; use libvhdl.AssertP.all; use libvhdl.SimP.all; use libvhdl.UtilsP.all; library work; use work.WishBoneP.all; library std; use std.env.all; entity WishBoneT is end entity WishBoneT; architecture sim of WishBoneT is --* testbench global clock period constant C_PERIOD : time := 5 ns; --* Wishbone data width constant C_DATA_WIDTH : natural := 8; --* Wishbone address width constant C_ADDRESS_WIDTH : natural := 8; signal s_wishbone : t_wishbone_if( Adr(C_ADDRESS_WIDTH-1 downto 0), WDat(C_DATA_WIDTH-1 downto 0), RDat(C_DATA_WIDTH-1 downto 0) ); --* testbench global clock signal s_wb_clk : std_logic := '1'; --* testbench global reset signal s_wb_reset : std_logic := '1'; signal s_master_local_wen : std_logic; signal s_master_local_ren : std_logic; signal s_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0); signal s_master_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0); signal s_master_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0); signal s_master_local_ack : std_logic; signal s_master_local_error : std_logic; signal s_slave_local_wen : std_logic; signal s_slave_local_ren : std_logic; signal s_slave_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0); signal s_slave_local_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0); signal s_slave_local_din : std_logic_vector(C_DATA_WIDTH-1 downto 0); package SlvQueue is new libvhdl.QueueP generic map ( QUEUE_TYPE => std_logic_vector(C_ADDRESS_WIDTH-1 downto 0), MAX_LEN => 2**C_ADDRESS_WIDTH, to_string => to_hstring ); shared variable sv_wishbone_queue : SlvQueue.t_list_queue; package IntSlvDict is new libvhdl.DictP generic map (KEY_TYPE => natural, VALUE_TYPE => std_logic_vector, key_to_string => to_string, value_to_string => to_hstring); shared variable sv_wb_master_dict : IntSlvDict.t_dict; shared variable sv_wb_slave_dict : IntSlvDict.t_dict; shared variable sv_coverage : CovPType; begin --* testbench global clock s_wb_clk <= not(s_wb_clk) after C_PERIOD/2; --* testbench global reset s_wb_reset <= '0' after C_PERIOD * 5; QueueInitP : process is begin sv_wishbone_queue.init(false); sv_wb_master_dict.init(false); sv_wb_slave_dict.init(false); wait; end process QueueInitP; WbMasterLocalP : process is variable v_random : RandomPType; variable v_wbmaster_address : integer; variable v_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0); variable v_wbmaster_data : std_logic_vector(C_DATA_WIDTH-1 downto 0); begin v_random.InitSeed(v_random'instance_name); v_wbmaster_data := (others => '0'); s_master_local_din <= (others => '0'); s_master_local_adress <= (others => '0'); s_master_local_wen <= '0'; s_master_local_ren <= '0'; wait until s_wb_reset = '0'; -- write the wishbone slave registers sv_coverage.AddBins(GenBin(0)); sv_coverage.AddBins(GenBin(integer'(2**C_ADDRESS_WIDTH-1))); sv_coverage.AddBins(GenBin(1, integer'(2**C_ADDRESS_WIDTH-2), 64)); while not sv_coverage.IsCovered loop v_wbmaster_address := sv_coverage.RandCovPoint; v_wbmaster_data := v_random.RandSlv(C_DATA_WIDTH); s_master_local_din <= v_wbmaster_data; s_master_local_adress <= uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH); s_master_local_wen <= '1'; wait until rising_edge(s_wb_clk); s_master_local_din <= (others => '0'); s_master_local_adress <= (others => '0'); s_master_local_wen <= '0'; wait until rising_edge(s_wb_clk) and s_master_local_ack = '1'; sv_wishbone_queue.push(uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH)); sv_wb_master_dict.set(v_wbmaster_address, v_wbmaster_data); sv_coverage.ICover(v_wbmaster_address); end loop; -- read back and check the wishbone slave registers while not(sv_wishbone_queue.is_empty) loop sv_wishbone_queue.pop(v_master_local_adress); s_master_local_adress <= v_master_local_adress; s_master_local_ren <= '1'; wait until rising_edge(s_wb_clk); s_master_local_adress <= (others => '0'); s_master_local_ren <= '0'; wait until rising_edge(s_wb_clk) and s_master_local_ack = '1'; sv_wb_master_dict.get(slv_to_uint(v_master_local_adress), v_wbmaster_data); assert_equal(s_master_local_dout, v_wbmaster_data); end loop; -- test local write & read at the same time wait until rising_edge(s_wb_clk); s_master_local_wen <= '1'; s_master_local_ren <= '1'; wait until rising_edge(s_wb_clk); s_master_local_wen <= '0'; s_master_local_ren <= '0'; wait until rising_edge(s_wb_clk); -- Test finished report "INFO: Test successfully finished!"; sv_coverage.SetMessage("WishboneT coverage results"); sv_coverage.WriteBin; finish; wait; end process WbMasterLocalP; i_WishBoneMasterE : WishBoneMasterE generic map ( Coverage => false, Formal => false, Simulation => true, AddressWidth => C_ADDRESS_WIDTH, DataWidth => C_DATA_WIDTH ) port map ( --+ wishbone system if WbRst_i => s_wb_reset, WbClk_i => s_wb_clk, --+ wishbone outputs WbCyc_o => s_wishbone.Cyc, WbStb_o => s_wishbone.Stb, WbWe_o => s_wishbone.We, WbAdr_o => s_wishbone.Adr, WbDat_o => s_wishbone.WDat, --+ wishbone inputs WbDat_i => s_wishbone.RDat, WbAck_i => s_wishbone.Ack, WbErr_i => s_wishbone.Err, --+ local register if LocalWen_i => s_master_local_wen, LocalRen_i => s_master_local_ren, LocalAdress_i => s_master_local_adress, LocalData_i => s_master_local_din, LocalData_o => s_master_local_dout, LocalAck_o => s_master_local_ack, LocalError_o => s_master_local_error ); WishBoneBusMonitorP : process is variable v_master_local_adress : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0); variable v_master_local_data : std_logic_vector(C_DATA_WIDTH-1 downto 0); variable v_valid_access : std_logic; begin wait until (s_master_local_wen = '1' or s_master_local_ren = '1') and rising_edge(s_wb_clk); v_master_local_adress := s_master_local_adress; v_master_local_data := s_master_local_din; v_valid_access := s_master_local_wen xor s_master_local_ren; wait until rising_edge(s_wb_clk); WB_CYC : assert v_valid_access = s_wishbone.Cyc report "ERROR: Wishbone cycle should be 0b" & to_string(v_valid_access) & " instead of 0b" & to_string(s_wishbone.Cyc) severity failure; if (v_valid_access = '1') then WB_ADDR : assert s_wishbone.Adr = v_master_local_adress report "ERROR: Wishbone address 0x" & to_hstring(s_wishbone.Adr) & " differ from local address 0x" & to_hstring(v_master_local_adress) severity failure; if (s_wishbone.We = '1') then WB_DATA : assert s_wishbone.WDat = v_master_local_data report "ERROR: Wishbone data 0x" & to_hstring(s_wishbone.WDat) & " differ from local data 0x" & to_hstring(v_master_local_data) severity failure; end if; end if; end process WishBoneBusMonitorP; i_WishBoneSlaveE : WishBoneSlaveE generic map ( Formal => false, Simulation => true, AddressWidth => C_ADDRESS_WIDTH, DataWidth => C_DATA_WIDTH ) port map ( --+ wishbone system if WbRst_i => s_wb_reset, WbClk_i => s_wb_clk, --+ wishbone inputs WbCyc_i => s_wishbone.Cyc, WbStb_i => s_wishbone.Stb, WbWe_i => s_wishbone.We, WbAdr_i => s_wishbone.Adr, WbDat_i => s_wishbone.WDat, --* wishbone outputs WbDat_o => s_wishbone.RDat, WbAck_o => s_wishbone.Ack, WbErr_o => s_wishbone.Err, --+ local register if LocalWen_o => s_slave_local_wen, LocalRen_o => s_slave_local_ren, LocalAdress_o => s_slave_local_adress, LocalData_o => s_slave_local_dout, LocalData_i => s_slave_local_din ); WbSlaveLocalP : process is begin wait until rising_edge(s_wb_clk); if (s_wb_reset = '1') then s_slave_local_din <= (others => '0'); else if (s_slave_local_wen = '1') then sv_wb_slave_dict.set(slv_to_uint(s_slave_local_adress), s_slave_local_dout); elsif (s_slave_local_ren = '1') then WB_SLAVE_REG : assert sv_wb_slave_dict.hasKey(slv_to_uint(s_slave_local_adress)) report "ERROR: Requested register at addr 0x" & to_hstring(s_slave_local_adress) & " not written before" severity failure; s_slave_local_din <= sv_wb_slave_dict.get(slv_to_uint(s_slave_local_adress)); end if; end if; end process WbSlaveLocalP; i_WishBoneChecker : WishBoneCheckerE port map ( --+ wishbone system if WbRst_i => s_wb_reset, WbClk_i => s_wb_clk, --+ wishbone outputs WbMCyc_i => s_wishbone.Cyc, WbMStb_i => s_wishbone.Stb, WbMWe_i => s_wishbone.We, WbMAdr_i => s_wishbone.Adr, WbMDat_i => s_wishbone.WDat, --+ wishbone inputs WbSDat_i => s_wishbone.RDat, WbSAck_i => s_wishbone.Ack, WbSErr_i => s_wishbone.Err, WbRty_i => '0' ); end architecture sim;