|
@ -11,6 +11,9 @@ library libvhdl; |
|
|
use libvhdl.SimP.all; |
|
|
use libvhdl.SimP.all; |
|
|
use libvhdl.UtilsP.all; |
|
|
use libvhdl.UtilsP.all; |
|
|
|
|
|
|
|
|
|
|
|
library work; |
|
|
|
|
|
use work.WishBoneP.all; |
|
|
|
|
|
|
|
|
library std; |
|
|
library std; |
|
|
use std.env.all; |
|
|
use std.env.all; |
|
|
|
|
|
|
|
@ -24,65 +27,6 @@ end entity WishBoneT; |
|
|
architecture sim of WishBoneT is |
|
|
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 |
|
|
--* testbench global clock period |
|
|
constant C_PERIOD : time := 5 ns; |
|
|
constant C_PERIOD : time := 5 ns; |
|
|
--* Wishbone data width |
|
|
--* Wishbone data width |
|
@ -90,20 +34,11 @@ architecture sim of WishBoneT is |
|
|
--* Wishbone address width |
|
|
--* Wishbone address width |
|
|
constant C_ADDRESS_WIDTH : natural := 8; |
|
|
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'); |
|
|
|
|
|
|
|
|
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 |
|
|
--* testbench global clock |
|
|
signal s_wb_clk : std_logic := '1'; |
|
|
signal s_wb_clk : std_logic := '1'; |
|
@ -123,8 +58,6 @@ architecture sim of WishBoneT is |
|
|
signal s_slave_local_dout : std_logic_vector(C_DATA_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); |
|
|
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 |
|
|
package SlvQueue is new libvhdl.QueueP |
|
|
generic map ( |
|
|
generic map ( |
|
@ -136,12 +69,13 @@ architecture sim of WishBoneT is |
|
|
shared variable sv_wishbone_queue : SlvQueue.t_list_queue; |
|
|
shared variable sv_wishbone_queue : SlvQueue.t_list_queue; |
|
|
|
|
|
|
|
|
package IntSlvDict is new libvhdl.DictP |
|
|
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); |
|
|
|
|
|
|
|
|
generic map (KEY_TYPE => natural, |
|
|
|
|
|
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_wb_master_dict : IntSlvDict.t_dict; |
|
|
|
|
|
shared variable sv_wb_slave_dict : IntSlvDict.t_dict; |
|
|
|
|
|
|
|
|
shared variable sv_coverage : CovPType; |
|
|
shared variable sv_coverage : CovPType; |
|
|
|
|
|
|
|
@ -158,7 +92,8 @@ begin |
|
|
QueueInitP : process is |
|
|
QueueInitP : process is |
|
|
begin |
|
|
begin |
|
|
sv_wishbone_queue.init(false); |
|
|
sv_wishbone_queue.init(false); |
|
|
sv_wishbone_dict.init(false); |
|
|
|
|
|
|
|
|
sv_wb_master_dict.init(false); |
|
|
|
|
|
sv_wb_slave_dict.init(false); |
|
|
wait; |
|
|
wait; |
|
|
end process QueueInitP; |
|
|
end process QueueInitP; |
|
|
|
|
|
|
|
@ -192,7 +127,7 @@ begin |
|
|
s_master_local_wen <= '0'; |
|
|
s_master_local_wen <= '0'; |
|
|
wait until rising_edge(s_wb_clk) and s_master_local_ack = '1'; |
|
|
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_queue.push(uint_to_slv(v_wbmaster_address, C_ADDRESS_WIDTH)); |
|
|
sv_wishbone_dict.set(v_wbmaster_address, v_wbmaster_data); |
|
|
|
|
|
|
|
|
sv_wb_master_dict.set(v_wbmaster_address, v_wbmaster_data); |
|
|
sv_coverage.ICover(v_wbmaster_address); |
|
|
sv_coverage.ICover(v_wbmaster_address); |
|
|
end loop; |
|
|
end loop; |
|
|
-- read back and check the wishbone slave registers |
|
|
-- read back and check the wishbone slave registers |
|
@ -204,7 +139,7 @@ begin |
|
|
s_master_local_adress <= (others => '0'); |
|
|
s_master_local_adress <= (others => '0'); |
|
|
s_master_local_ren <= '0'; |
|
|
s_master_local_ren <= '0'; |
|
|
wait until rising_edge(s_wb_clk) and s_master_local_ack = '1'; |
|
|
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); |
|
|
|
|
|
|
|
|
sv_wb_master_dict.get(slv_to_uint(v_master_local_adress), v_wbmaster_data); |
|
|
assert_equal(s_master_local_dout, v_wbmaster_data); |
|
|
assert_equal(s_master_local_dout, v_wbmaster_data); |
|
|
end loop; |
|
|
end loop; |
|
|
-- test local write & read at the same time |
|
|
-- test local write & read at the same time |
|
@ -225,10 +160,6 @@ begin |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i_WishBoneMasterE : WishBoneMasterE |
|
|
i_WishBoneMasterE : WishBoneMasterE |
|
|
generic map ( |
|
|
|
|
|
G_ADR_WIDTH => C_ADDRESS_WIDTH, |
|
|
|
|
|
G_DATA_WIDTH => C_DATA_WIDTH |
|
|
|
|
|
) |
|
|
|
|
|
port map ( |
|
|
port map ( |
|
|
--+ wishbone system if |
|
|
--+ wishbone system if |
|
|
WbRst_i => s_wb_reset, |
|
|
WbRst_i => s_wb_reset, |
|
@ -254,37 +185,33 @@ begin |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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; |
|
|
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) |
|
|
|
|
|
|
|
|
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; |
|
|
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 if; |
|
|
end process WishBoneBusMonitorP; |
|
|
|
|
|
|
|
|
end if; |
|
|
|
|
|
end process WishBoneBusMonitorP; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i_WishBoneSlaveE : WishBoneSlaveE |
|
|
|
|
|
generic map ( |
|
|
|
|
|
G_ADR_WIDTH => C_ADDRESS_WIDTH, |
|
|
|
|
|
G_DATA_WIDTH => C_DATA_WIDTH |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
i_WishBoneSlaveE : WishBoneSlaveE |
|
|
port map ( |
|
|
port map ( |
|
|
--+ wishbone system if |
|
|
--+ wishbone system if |
|
|
WbRst_i => s_wb_reset, |
|
|
WbRst_i => s_wb_reset, |
|
@ -308,21 +235,42 @@ begin |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
WbSlaveLocalP : process is |
|
|
|
|
|
variable v_data : std_logic_vector(s_slave_local_din'range); |
|
|
|
|
|
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; |
|
|
|
|
|
sv_wb_slave_dict.get(slv_to_uint(s_slave_local_adress), v_data); |
|
|
|
|
|
s_slave_local_din <= v_data; |
|
|
end if; |
|
|
end if; |
|
|
end process WbSlaveLocalP; |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end architecture sim; |
|
|
end architecture sim; |