library ieee;
use ieee.std_logic_1164.all;
library vunit_lib;
-- use vunit_lib.check_pkg.all;
context vunit_lib.vunit_context;
use work.tb_pkg.all;
package tb_i2c_pkg is
type std_logic_arr_t is array (natural range <>) of std_logic;
function f_resolve_pull_up (
constant signals : std_logic_arr_t)
return std_logic;
subtype pull_up_std_logic is f_resolve_pull_up std_logic;
signal sda : pull_up_std_logic;
signal scl : pull_up_std_logic;
signal tx_ready : std_logic;
signal rx_valid : std_logic;
signal rx_data : std_logic_vector(7 downto 0);
procedure scl_fall (
signal scl_override : inout std_logic);
procedure scl_rise (
signal scl_override : inout std_logic);
procedure scl_pulse (
signal scl_override : inout std_logic);
procedure sda_fall (
signal sda_override : inout std_logic;
constant assert_no_condition : in std_logic := '1');
procedure sda_rise (
signal sda_override : inout std_logic;
constant assert_no_condition : in std_logic := '1');
procedure tx_write_data (
constant data : in std_logic_vector(7 downto 0);
signal tx_data : inout std_logic_vector(7 downto 0);
signal tx_valid : inout std_logic);
procedure rx_read_data (
constant exp_data : in std_logic_vector(7 downto 0);
signal rx_confirm_read : inout std_logic);
end package tb_i2c_pkg;
package body tb_i2c_pkg is
function f_resolve_pull_up (
constant signals : std_logic_arr_t)
return std_logic is
variable sig : std_logic := '1';
begin
for i in signals'range loop
if signals(i) = '0' then
sig := '0';
end if;
end loop; -- i
return sig;
end function f_resolve_pull_up;
procedure scl_fall (
signal scl_override : inout std_logic) is
begin -- procedure scl_rise
scl_override <= '1';
wait until falling_edge(clk);
wait until falling_edge(clk);
wait until falling_edge(clk);
wait until falling_edge(clk);
end procedure scl_fall;
procedure scl_rise (
signal scl_override : inout std_logic) is
begin -- procedure scl_rise
wait until falling_edge(clk);
wait until falling_edge(clk);
wait until falling_edge(clk);
scl_override <= '0';
wait until falling_edge(clk);
wait until falling_edge(clk);
wait until falling_edge(clk);
wait until falling_edge(clk);
wait until falling_edge(clk);
wait until falling_edge(clk);
wait until falling_edge(clk);
end procedure scl_rise;
procedure scl_pulse (
signal scl_override : inout std_logic) is
begin -- procedure scl_rise
scl_rise(scl_override);
wait until falling_edge(clk);
wait until falling_edge(clk);
scl_fall(scl_override);
end procedure scl_pulse;
procedure sda_fall (
signal sda_override : inout std_logic;
constant assert_no_condition : in std_logic := '1') is
begin -- procedure scl_rise
if assert_no_condition = '1' and sda /= '0' then
check_equal(scl, '0', "Cannot change sda as that would trigger start condition.", failure);
end if;
sda_override <= '1';
wait until falling_edge(clk);
end procedure sda_fall;
procedure sda_rise (
signal sda_override : inout std_logic;
constant assert_no_condition : in std_logic := '1') is
begin -- procedure scl_rise
if assert_no_condition = '1' and sda /= '0' then
check_equal(scl, '0', "Cannot change sda as that would trigger stop condition.", failure);
end if;
sda_override <= '0';
wait until falling_edge(clk);
end procedure sda_rise;
procedure tx_write_data (
constant data : in std_logic_vector(7 downto 0);
signal tx_data : inout std_logic_vector(7 downto 0);
signal tx_valid : inout std_logic
) is
begin
check_equal(tx_ready, '1', "not ready when trying to write data!");
tx_data <= data;
tx_valid <= '1';
wait until falling_edge(clk);
tx_valid <= '0';
end procedure tx_write_data;
procedure rx_read_data (
constant exp_data : in std_logic_vector(7 downto 0);
signal rx_confirm_read : inout std_logic
) is
begin
check_equal(rx_valid, '1', "not valid when trying to read data!");
check_equal(rx_data, exp_data, "Read rx data not equal to expected");
rx_confirm_read <= '1';
wait until falling_edge(clk);
rx_confirm_read <= '0';
end procedure rx_read_data;
end package body tb_i2c_pkg;