Skip to content

Commit

Permalink
Add more checks, coverage & tests
Browse files Browse the repository at this point in the history
* Add functional coverage for block & rmw cycles
* Add some more checks for WB rules
* Add tests of block cycles
  • Loading branch information
tmeissner committed Oct 28, 2021
1 parent 90bd091 commit dbfe16a
Show file tree
Hide file tree
Showing 3 changed files with 294 additions and 59 deletions.
122 changes: 122 additions & 0 deletions wishbone/wishbone_pkg.vhd
Expand Up @@ -8,8 +8,12 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all;



package wishbone_pkg is


type t_slv_array is array (natural range <>) of std_logic_vector;

type t_wb_syscon is record
Reset : std_logic;
Clk : std_logic;
Expand All @@ -36,4 +40,122 @@ package wishbone_pkg is
Tgd : std_logic_vector;
end record;


function to_string(wb : t_wb_master) return string;
function to_string(wb : t_wb_slave) return string;

procedure log_wishbone (signal clk : std_logic; master : t_wb_master; slave : t_wb_slave);


procedure cycle (signal syscon : in t_wb_syscon;
signal master : out t_wb_master;
signal slave : in t_wb_slave;
Wen : in std_logic;
Adr : in std_logic_vector;
WDat : in std_logic_vector;
RDat : out std_logic_vector);

procedure single_cycle (signal syscon : in t_wb_syscon;
signal master : out t_wb_master;
signal slave : in t_wb_slave;
Wen : in std_logic;
Adr : in std_logic_vector;
WDat : in std_logic_vector;
RDat : out std_logic_vector);

procedure block_cycle (signal syscon : in t_wb_syscon;
signal master : out t_wb_master;
signal slave : in t_wb_slave;
Wen : in std_logic;
Adr : in t_slv_array;
WDat : in t_slv_array;
RDat : out t_slv_array);

end package wishbone_pkg;



package body wishbone_pkg is


procedure cycle (signal syscon : in t_wb_syscon;
signal master : out t_wb_master;
signal slave : in t_wb_slave;
Wen : in std_logic;
Adr : in std_logic_vector;
WDat : in std_logic_vector;
RDat : out std_logic_vector) is
begin
master.Cyc <= '1';
master.Stb <= '1';
master.We <= Wen;
master.Adr <= Adr;
master.Dat <= WDat;
wait until rising_edge(syscon.Clk) and (slave.Ack or slave.Err or slave.Rty) = '1';
RDat := slave.Dat;
end procedure cycle;

procedure single_cycle (signal syscon : in t_wb_syscon;
signal master : out t_wb_master;
signal slave : in t_wb_slave;
Wen : in std_logic;
Adr : in std_logic_vector;
WDat : in std_logic_vector;
RDat : out std_logic_vector) is
begin
cycle(syscon, master, slave, Wen, Adr, WDat, RDat);
master.Cyc <= '0';
master.Stb <= '0';
master.We <= '0';
master.Adr <= (master.Adr'range => '0');
master.Dat <= (master.Dat'range => '0');
wait until rising_edge(syscon.Clk);
end procedure single_cycle;

procedure block_cycle (signal syscon : in t_wb_syscon;
signal master : out t_wb_master;
signal slave : in t_wb_slave;
Wen : in std_logic;
Adr : in t_slv_array;
WDat : in t_slv_array;
RDat : out t_slv_array) is
begin
assert Adr'length = WDat'length and WDat'length = RDat'length;
for i in Adr'low to Adr'high-1 loop
cycle(syscon, master, slave, Wen, Adr(i), WDat(i), RDat(i));
end loop;
single_cycle(syscon, master, slave, Wen, Adr(Adr'high), WDat(WDat'high), RDat(RDat'high));
end procedure block_cycle;

function to_string(wb : t_wb_master) return string is
begin
return "Cyc: " & to_string(wb.Cyc) & LF &
"Stb: " & to_string(wb.Stb) & LF &
"We: " & to_string(wb.We) & LF &
"Lock: " & to_string(wb.Lock) & LF &
"Adr: " & to_hstring(wb.Adr) & LF &
"Dat: " & to_hstring(wb.Dat) & LF &
"Sel: " & to_hstring(wb.Sel) & LF &
"Tgc: " & to_hstring(wb.Tgc) & LF &
"Tga: " & to_hstring(wb.Tga) & LF &
"Tgd: " & to_hstring(wb.Tgd);
end function to_string;

function to_string(wb : t_wb_slave) return string is
begin
return "Ack: " & to_string(wb.Ack) & LF &
"Err: " & to_string(wb.Err) & LF &
"Rty: " & to_string(wb.Rty) & LF &
"Dat: " & to_hstring(wb.Dat) & LF &
"Tgd: " & to_hstring(wb.Tgd);
end function to_string;

procedure log_wishbone (signal clk : std_logic; master : t_wb_master; slave : t_wb_slave) is
begin
wait until rising_edge(clk);
report "Wishbone master:" & LF & to_string(master);
report "Wishbone slave:" & LF & to_string(slave);
end procedure log_wishbone;


end package body wishbone_pkg;
56 changes: 31 additions & 25 deletions wishbone/wishbone_tb.vhd
Expand Up @@ -21,6 +21,7 @@ end entity wishbone_tb;

architecture testbench of wishbone_tb is

constant C_CLOCK_PERIOD : time := 2 ns;

constant C_WB_ADDR_WIDTH : positive := 32;
constant C_WB_DATA_WIDTH : positive := 32;
Expand All @@ -39,53 +40,58 @@ architecture testbench of wishbone_tb is
signal s_wb_slave : t_wb_slave(Dat(C_WB_DATA_WIDTH-1 downto 0),
Tgd(C_WB_TGD_WIDTH-1 downto 0));

signal s_wb_slave_resp : std_logic_vector(2 downto 0);

alias s_clk is s_wb_syscon.Clk;
alias s_reset is s_wb_syscon.Reset;


begin


s_clk <= not s_clk after 1 ns;
s_clk <= not s_clk after C_CLOCK_PERIOD / 2;
s_reset <= '0' after 4 ns;

s_wb_slave_resp <= s_wb_slave.Rty & s_wb_slave.Err & s_wb_slave.Ack;

wb_master_p : process is
subtype t_wb_array is t_slv_array(0 to 7)(open);
variable v_wb_adr : t_wb_array(open)(C_WB_ADDR_WIDTH-1 downto 0);
variable v_wb_wdata : t_wb_array(open)(C_WB_DATA_WIDTH-1 downto 0);
variable v_wb_rdata : t_wb_array(open)(C_WB_DATA_WIDTH-1 downto 0);
begin
s_wb_master.Cyc <= '0';
s_wb_master.Stb <= '0';
wait until s_reset = '0';
-- simple reads
for i in 0 to 2 loop
wait until rising_edge(s_clk);
s_wb_master.Cyc <= '1';
s_wb_master.Stb <= '1';
s_wb_master.We <= '0';
wait until s_wb_slave_resp(i) = '1' and rising_edge(s_clk);
report "Master: end simple read cycle";
s_wb_master.Cyc <= '0';
s_wb_master.Stb <= '0';
-- single read cycles
for wait_cycles in 0 to 3 loop
single_cycle(s_wb_syscon, s_wb_master, s_wb_slave, '0', v_wb_adr(0), v_wb_wdata(0), v_wb_rdata(0));
end loop;
-- single write cycles
for wait_cycles in 0 to 3 loop
single_cycle(s_wb_syscon, s_wb_master, s_wb_slave, '1', v_wb_adr(0), v_wb_wdata(0), v_wb_rdata(0));
end loop;
-- block cycles
block_cycle(s_wb_syscon, s_wb_master, s_wb_slave, '0', v_wb_adr, v_wb_wdata, v_wb_rdata);
block_cycle(s_wb_syscon, s_wb_master, s_wb_slave, '1', v_wb_adr, v_wb_wdata, v_wb_rdata);
wait for 10 ns;
stop(0);
end process wb_master_p;


wb_slave_p : process is
variable v_resp : std_logic_vector(2 downto 0) := "000";
begin
(s_wb_slave.Rty, s_wb_slave.Err, s_wb_slave.Ack) <= v_resp;
s_wb_slave.Rty <= '0';
s_wb_slave.Err <= '0';
s_wb_slave.Ack <= '0';
wait until s_reset = '0';
-- simple read
for i in 0 to 2 loop
wait until (s_wb_master.Cyc and s_wb_master.Stb) = '1' and rising_edge(s_clk);
v_resp(i) := '1';
(s_wb_slave.Rty, s_wb_slave.Err, s_wb_slave.Ack) <= v_resp;
wait until not s_wb_master.Stb;
v_resp(i) := '0';
(s_wb_slave.Rty, s_wb_slave.Err, s_wb_slave.Ack) <= v_resp;
loop
for wait_cycles in 0 to 3 loop
wait until rising_edge(s_clk) and (s_wb_master.Cyc and s_wb_master.Stb) = '1';
if wait_cycles /= 0 then
wait for C_CLOCK_PERIOD * wait_cycles - 1 ps;
wait until rising_edge(s_clk);
end if;
s_wb_slave.Ack <= '1';
wait until rising_edge(s_clk);
s_wb_slave.Ack <= '0';
end loop;
end loop;
wait;
end process wb_slave_p;
Expand Down

0 comments on commit dbfe16a

Please sign in to comment.