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

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 std;
use std.env.all;
entity WishBoneT is
end entity WishBoneT;
architecture sim of WishBoneT is
component WishBoneMasterE is
generic (
G_ADR_WIDTH : positive := 8; --* address bus width
G_DATA_WIDTH : positive := 8 --* data bus width
);
port (
--+ wishbone system if
WbRst_i : in std_logic;
WbClk_i : in std_logic;
--+ wishbone outputs
WbCyc_o : out std_logic;
WbStb_o : out std_logic;
WbWe_o : out std_logic;
WbAdr_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
--+ wishbone inputs
WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
WbAck_i : in std_logic;
WbErr_i : in std_logic;
--+ local register if
LocalWen_i : in std_logic;
LocalRen_i : in std_logic;
LocalAdress_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalAck_o : out std_logic;
LocalError_o : out std_logic
);
end component WishBoneMasterE;
component WishBoneSlaveE is
generic (
G_ADR_WIDTH : positive := 8; --* address bus width
G_DATA_WIDTH : positive := 8 --* data bus width
);
port (
--+ wishbone system if
WbRst_i : in std_logic;
WbClk_i : in std_logic;
--+ wishbone inputs
WbCyc_i : in std_logic;
WbStb_i : in std_logic;
WbWe_i : in std_logic;
WbAdr_i : in std_logic_vector(G_ADR_WIDTH-1 downto 0);
WbDat_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
--* wishbone outputs
WbDat_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
WbAck_o : out std_logic;
WbErr_o : out std_logic;
--+ local register if
LocalWen_o : out std_logic;
LocalRen_o : out std_logic;
LocalAdress_o : out std_logic_vector(G_ADR_WIDTH-1 downto 0);
LocalData_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
LocalData_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0)
);
end component WishBoneSlaveE;
--* 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;
type t_wishbone is record
--+ wishbone outputs
Cyc : std_logic;
Stb : std_logic;
We : std_logic;
Adr : std_logic_vector(C_ADDRESS_WIDTH-1 downto 0);
WDat : std_logic_vector(C_DATA_WIDTH-1 downto 0);
--+ wishbone inputs
RDat : std_logic_vector(C_DATA_WIDTH-1 downto 0);
Ack : std_logic;
Err : std_logic;
end record t_wishbone;
signal s_wishbone : t_wishbone := ('Z', 'Z', 'Z', (others => 'Z'), (others => 'Z'), (others => 'Z'), 'Z', 'Z');
--* 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);
type t_register is array (0 to integer'(2**C_ADDRESS_WIDTH-1)) of 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 => integer,
VALUE_TYPE => std_logic_vector,
key_to_string => to_string,
value_to_string => to_hstring);
shared variable sv_wishbone_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_wishbone_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_wishbone_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_wishbone_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 (
G_ADR_WIDTH => C_ADDRESS_WIDTH,
G_DATA_WIDTH => 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 (
G_ADR_WIDTH => C_ADDRESS_WIDTH,
G_DATA_WIDTH => 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
variable v_register : t_register := (others => (others => '0'));
begin
wait until rising_edge(s_wb_clk);
if (s_wb_reset = '1') then
v_register := (others => (others => '0'));
s_slave_local_din <= (others => '0');
else
if (s_slave_local_wen = '1') then
v_register(slv_to_uint(s_slave_local_adress)) := s_slave_local_dout;
elsif (s_slave_local_ren = '1') then
s_slave_local_din <= v_register(slv_to_uint(s_slave_local_adress));
end if;
end if;
end process WbSlaveLocalP;
end architecture sim;