A tb/i2c/model/i2c_bus_pkg.vhd => tb/i2c/model/i2c_bus_pkg.vhd +283 -0
@@ 0,0 1,283 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+library vunit_lib;
+context vunit_lib.vunit_context;
+context vunit_lib.com_context;
+
+package i2c_bus_pkg is
+ constant free_bus_msg : msg_type_t := new_msg_type("free bus");
+ constant set_scl_freq_msg : msg_type_t := new_msg_type("scl freq");
+ constant gen_start_cond_msg : msg_type_t := new_msg_type("gen start cond");
+ constant gen_stop_cond_msg : msg_type_t := new_msg_type("gen stop cond");
+ constant gen_clocks_msg : msg_type_t := new_msg_type("gen clocks");
+ constant send_data_msg : msg_type_t := new_msg_type("send data");
+ constant send_data_clocks_msg : msg_type_t := new_msg_type("send data and clocks");
+
+ constant auto_ack_msg : msg_type_t := new_msg_type("auto acknowledge");
+
+ constant wait_start_cond_msg : msg_type_t := new_msg_type("wait start cond");
+ constant wait_stop_cond_msg : msg_type_t := new_msg_type("wait stop cond");
+ constant wait_clocks_msg : msg_type_t := new_msg_type("wait clocks");
+
+ constant check_data_msg : msg_type_t := new_msg_type("check data");
+ constant check_data_clocks_msg : msg_type_t := new_msg_type("check data and gen clocks");
+
+ constant wait_until_idle : msg_type_t := new_msg_type("wait until idle");
+
+ impure function get_actor (
+ constant inst_name : string)
+ return actor_t;
+
+ procedure free_bus (
+ constant actor : in actor_t);
+
+ procedure set_scl_frequency (
+ constant frequency : in real;
+ constant actor : in actor_t);
+
+ procedure gen_start_cond (
+ constant actor : in actor_t);
+
+ procedure gen_stop_cond (
+ constant actor : in actor_t);
+
+ procedure gen_clocks (
+ constant times : in natural;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure send_data (
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure send_ack (
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure send_ack_and_clock (
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure send_data_and_clock (
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure wait_for_start_cond (
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure wait_for_stop_cond (
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure wait_for_clocks (
+ constant times : in natural;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure check_data (
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure check_data_gen_clock (
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure check_ack_gen_clock (
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure check_ack (
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure set_auto_ack (
+ constant auto_ack : in boolean;
+ constant address : in std_logic_vector(6 downto 0);
+ constant bytes_count : in natural;
+ constant actor : in actor_t);
+
+end package i2c_bus_pkg;
+
+package body i2c_bus_pkg is
+
+ impure function get_actor (
+ constant inst_name : string)
+ return actor_t is
+ begin
+ return find(inst_name);
+ end function get_actor;
+
+ procedure free_bus (
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(free_bus_msg);
+ begin
+ send(net, actor, msg);
+ end procedure free_bus;
+
+ procedure set_scl_frequency (
+ constant frequency : in real;
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(set_scl_freq_msg);
+ begin
+ push(msg, frequency);
+ send(net, actor, msg);
+ end procedure set_scl_frequency;
+
+ procedure gen_start_cond (
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(gen_start_cond_msg);
+ begin
+ send(net, actor, msg);
+ end procedure gen_start_cond;
+
+ procedure gen_stop_cond (
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(gen_stop_cond_msg);
+ begin
+ send(net, actor, msg);
+ end procedure gen_stop_cond;
+
+ procedure gen_clocks (
+ constant times : in natural;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(gen_clocks_msg);
+ begin
+ push(msg, times);
+ push(msg, timeout);
+ send(net, actor, msg);
+ end procedure gen_clocks;
+
+ procedure send_data (
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(send_data_msg);
+ variable msg_data : std_logic_vector(1023 downto 0);
+ begin
+ msg_data(data'length - 1 downto 0) := data(data'range);
+ push(msg, data'length);
+ push(msg, msg_data);
+ push(msg, timeout);
+ send(net, actor, msg);
+ end procedure send_data;
+
+ procedure send_ack (
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ send_data("0", timeout, actor);
+ end procedure send_ack;
+
+ procedure send_ack_and_clock (
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ send_data_and_clock("0", timeout, actor);
+ end procedure send_ack_and_clock;
+
+ procedure send_data_and_clock (
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(send_data_clocks_msg);
+ variable msg_data : std_logic_vector(1023 downto 0);
+ begin
+ msg_data(data'length - 1 downto 0) := data(data'range);
+ push(msg, data'length);
+ push(msg, msg_data);
+ push(msg, timeout);
+ send(net, actor, msg);
+ end procedure send_data_and_clock;
+
+ procedure wait_for_start_cond (
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(wait_start_cond_msg);
+ begin
+ push(msg, timeout);
+ send(net, actor, msg);
+ end procedure wait_for_start_cond;
+
+ procedure wait_for_stop_cond (
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(wait_stop_cond_msg);
+ begin
+ push(msg, timeout);
+ send(net, actor, msg);
+ end procedure wait_for_stop_cond;
+
+ procedure wait_for_clocks (
+ constant times : in natural;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(wait_clocks_msg);
+ begin
+ push(msg, times);
+ push(msg, timeout);
+ send(net, actor, msg);
+ end procedure wait_for_clocks;
+
+ procedure check_data (
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ variable msg_data : std_logic_vector(1023 downto 0);
+ variable msg : msg_t := new_msg(check_data_msg);
+ begin
+ msg_data(exp_data'length - 1 downto 0) := exp_data(exp_data'range);
+ push(msg, exp_data'length);
+ push(msg, msg_data);
+ push(msg, timeout);
+ send(net, actor, msg);
+ end procedure check_data;
+
+ procedure check_data_gen_clock (
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ variable msg_data : std_logic_vector(1023 downto 0);
+ variable msg : msg_t := new_msg(check_data_clocks_msg);
+ begin
+ msg_data(exp_data'length - 1 downto 0) := exp_data(exp_data'range);
+ push(msg, exp_data'length);
+ push(msg, msg_data);
+ push(msg, timeout);
+ send(net, actor, msg);
+ end procedure check_data_gen_clock;
+
+ procedure check_ack_gen_clock (
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ check_data_gen_clock("0", timeout, actor);
+ end procedure check_ack_gen_clock;
+
+ procedure check_ack (
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ check_data("0", timeout, actor);
+ end procedure check_ack;
+
+ procedure set_auto_ack (
+ constant auto_ack : in boolean;
+ constant address : in std_logic_vector(6 downto 0);
+ constant bytes_count : in natural;
+ constant actor : in actor_t) is
+ variable msg : msg_t := new_msg(auto_ack_msg);
+ begin
+ push(msg, auto_ack);
+ push(msg, address);
+ push(msg, bytes_count);
+ send(net, actor, msg);
+ end procedure set_auto_ack;
+
+end package body i2c_bus_pkg;
A tb/i2c/model/i2c_master_pkg.vhd => tb/i2c/model/i2c_master_pkg.vhd +112 -0
@@ 0,0 1,112 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+library vunit_lib;
+context vunit_lib.vunit_context;
+context vunit_lib.com_context;
+
+use work.i2c_bus_pkg;
+
+package i2c_master_pkg is
+
+ procedure write (
+ constant address : in std_logic_vector(6 downto 0);
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure read (
+ constant address : in std_logic_vector(6 downto 0);
+ constant data : in std_logic_vector;
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure write_read (
+ constant address : in std_logic_vector(6 downto 0);
+ constant data : in std_logic_vector;
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+end package i2c_master_pkg;
+
+package body i2c_master_pkg is
+
+ procedure write (
+ constant address : in std_logic_vector(6 downto 0);
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ if data'length mod 8 /= 0 then
+ failure("The number of bits to write to the slave have to be divisible by 8.");
+ end if;
+
+ i2c_bus_pkg.gen_start_cond(actor);
+ i2c_bus_pkg.send_data_and_clock(address & '0', timeout, actor);
+
+ for i in 0 to data'length/8 - 1 loop
+ i2c_bus_pkg.send_data_and_clock(data(data'left - i*8 downto data'left - 7 - i*8), timeout, actor);
+ i2c_bus_pkg.check_ack_gen_clock(timeout, actor);
+ end loop; -- i
+
+ i2c_bus_pkg.gen_stop_cond(actor);
+ end procedure write;
+
+ procedure read (
+ constant address : in std_logic_vector(6 downto 0);
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ if exp_data'length mod 8 /= 0 then
+ failure("The number of bits to read from the slave have to be divisible by 8.");
+ end if;
+
+ i2c_bus_pkg.gen_start_cond(actor);
+ i2c_bus_pkg.send_data_and_clock(address & '1', timeout, actor);
+
+ for i in 0 to exp_data'length/8 - 1 loop
+ i2c_bus_pkg.check_data_gen_clock(exp_data(exp_data'left - i*8 downto exp_data'left - 7 - i*8), timeout, actor);
+ i2c_bus_pkg.send_ack_and_clock(timeout, actor);
+ end loop; -- i
+
+ i2c_bus_pkg.gen_stop_cond(actor);
+ end procedure read;
+
+ procedure write_read (
+ constant address : in std_logic_vector(6 downto 0);
+ constant data : in std_logic_vector;
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ if data'length mod 8 /= 0 then
+ failure("The number of bits to write to the slave have to be divisible by 8.");
+ end if;
+
+ if exp_data'length mod 8 /= 0 then
+ failure("The number of bits to read from the slave have to be divisible by 8.");
+ end if;
+
+ i2c_bus_pkg.gen_start_cond(actor);
+ i2c_bus_pkg.send_data_and_clock(address & '0', timeout, actor);
+
+ for i in 0 to data'length/8 - 1 loop
+ i2c_bus_pkg.send_data_and_clock(data(data'left - i*8 downto data'left - 7 - i*8), timeout, actor);
+ i2c_bus_pkg.check_ack_gen_clock(timeout, actor);
+ end loop; -- i
+
+ i2c_bus_pkg.gen_start_cond(actor);
+ i2c_bus_pkg.send_data_and_clock(address & '1', timeout, actor);
+
+ for i in 0 to exp_data'length/8 - 1 loop
+ i2c_bus_pkg.check_data_gen_clock(exp_data(exp_data'left - i*8 downto exp_data'left - 7 - i*8), timeout, actor);
+ i2c_bus_pkg.send_ack_and_clock(timeout, actor);
+ end loop; -- i
+
+ i2c_bus_pkg.gen_stop_cond(actor);
+ end procedure write_read;
+
+end package body i2c_master_pkg;
A tb/i2c/model/i2c_slave_pkg.vhd => tb/i2c/model/i2c_slave_pkg.vhd +135 -0
@@ 0,0 1,135 @@
+--- read(address, exp_data, timeout)
+--- wait start
+--- wait address
+--- ack (if matching)
+--- read data, check it
+--- check ack on every byte
+--- wait stop?
+--- write(address, data, timeout)
+--- wait start
+--- wait address
+--- ack (if matching)
+--- write data, check ack
+--- wait stop?
+--- read_write(address, exp_data, data, timeout)
+--- wait start
+--- wait address
+--- ack (if matcihng)
+--- start matching bytes
+--- ack every byte
+--- wait start
+--- wait address
+--- ack (if matching)
+--- write data, check ack
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+library vunit_lib;
+context vunit_lib.vunit_context;
+context vunit_lib.com_context;
+
+use work.i2c_bus_pkg;
+
+package i2c_slave_pkg is
+
+ procedure write (
+ constant address : in std_logic_vector(6 downto 0);
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure read (
+ constant address : in std_logic_vector(6 downto 0);
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+ procedure write_read (
+ constant address : in std_logic_vector(6 downto 0);
+ constant exp_data : in std_logic_vector;
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t);
+
+end package i2c_slave_pkg;
+
+package body i2c_slave_pkg is
+
+ procedure write (
+ constant address : in std_logic_vector(6 downto 0);
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ if exp_data'length mod 8 /= 0 then
+ failure("The number of bits to be written to the slave have to be divisible by 8.");
+ end if;
+
+ i2c_bus_pkg.wait_for_start_cond(timeout, actor);
+ i2c_bus_pkg.check_data(address & '0', timeout, actor);
+
+ for i in 0 to exp_data'length/8 - 1 loop
+ i2c_bus_pkg.check_data(exp_data(exp_data'left - i*8 downto exp_data'left - 7 - i*8), timeout, actor);
+ i2c_bus_pkg.send_ack(timeout, actor);
+ end loop; -- i
+
+ i2c_bus_pkg.wait_for_stop_cond(timeout, actor);
+ end procedure write;
+
+ procedure read (
+ constant address : in std_logic_vector(6 downto 0);
+ constant data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ if data'length mod 8 /= 0 then
+ failure("The number of bits to be read from the slave have to be divisible by 8.");
+ end if;
+
+ i2c_bus_pkg.wait_for_start_cond(timeout, actor);
+ i2c_bus_pkg.check_data(address & '1', timeout, actor);
+
+ for i in 0 to data'length/8 - 1 loop
+ i2c_bus_pkg.send_data(data(data'left - i*8 downto data'left - 7 - i*8), timeout, actor);
+ i2c_bus_pkg.check_ack(timeout, actor);
+ end loop; -- i
+
+ i2c_bus_pkg.wait_for_stop_cond(timeout, actor);
+ end procedure read;
+
+ procedure write_read (
+ constant address : in std_logic_vector(6 downto 0);
+ constant data : in std_logic_vector;
+ constant exp_data : in std_logic_vector;
+ constant timeout : in time;
+ constant actor : in actor_t) is
+ begin
+ if exp_data'length mod 8 /= 0 then
+ failure("The number of bits to be written to the slave have to be divisible by 8.");
+ end if;
+ if data'length mod 8 /= 0 then
+ failure("The number of bits to be read from the slave have to be divisible by 8.");
+ end if;
+
+ i2c_bus_pkg.wait_for_start_cond(timeout, actor);
+ i2c_bus_pkg.send_data_and_clock(address & '0', timeout, actor);
+
+ for i in 0 to exp_data'length/8 - 1 loop
+ i2c_bus_pkg.check_data(exp_data(exp_data'left - i*8 downto exp_data'left - 7 - i*8), timeout, actor);
+ i2c_bus_pkg.send_ack(timeout, actor);
+ end loop; -- i
+
+ i2c_bus_pkg.wait_for_start_cond(timeout, actor);
+ i2c_bus_pkg.send_data_and_clock(address & '1', timeout, actor);
+
+ for i in 0 to data'length/8 - 1 loop
+ i2c_bus_pkg.send_data(data(data'left - i*8 downto data'left - 7 - i*8), timeout, actor);
+ i2c_bus_pkg.check_ack(timeout, actor);
+ end loop; -- i
+
+ i2c_bus_pkg.wait_for_stop_cond(timeout, actor);
+ end procedure write_read;
+
+
+end package body i2c_slave_pkg;