M src/i2c/rx.vhd => src/i2c/rx.vhd +46 -35
@@ 24,11 24,15 @@ entity rx is
clk_i : in std_logic; -- Clock
rst_in : in std_logic; -- Reset (asynchronous)
start_read_i : in std_logic; -- Start reading with next scl_pulse
- ss_condition_i : in std_logic; -- Reset rx circuitry
+ ss_condition_i : in std_logic; -- Reset rx circuitry
scl_pulse_i : in std_logic; -- SCL rising edge pulse
+ scl_falling_delayed_i : in std_logic; -- SCL rising edge pulse
scl_stretch_o : out std_logic; -- Stretch SCL (keep SCL 0)
sda_i : in std_logic; -- SDA data line state
+ sda_enable_o : out std_logic; -- SDA data line state
+
+ generate_ack_i : in std_logic;
read_valid_o : out std_logic; -- Are there any data on read_data_o?
read_ready_o : out std_logic; -- Is it possible to read anymore, or
@@ 41,19 45,23 @@ end entity rx;
architecture a1 of rx is
-- IDLE - not doing anythign
-- RECEIVING - currently receiving data to the buffer
- -- SAVING - trying to save to the read data output, waiting for data being
+ -- ACK - going to generate acknowledge
+ -- ACK_ON - sda should be enabled, to signal ack
+ -- STRETCHING -
-- read if cannot save
- -- SAVING_STRETCHING - waiting for data being read, should
-- be sending already, but cannot, since the data are not read,
-- so stretching SCL
- type rx_state_t is (IDLE, RECEIVING, SAVING, SAVING_STRETCHING);
+ type rx_state_t is (IDLE, RECEIVING, ACK, ACK_ON, STRETCHING);
signal curr_state : rx_state_t;
signal next_state : rx_state_t;
-- Whether state = RECEIVING
signal curr_receiving : std_logic;
- -- Whether state = SAVING or SAVING_STRETCHING
+
+ -- Whether data are being saved (could be just one cycle if not filled, or
+ -- more if filled)
signal curr_saving : std_logic;
+ signal next_saving : std_logic;
-- Whether the read data output is filled
-- already (it's a register)
@@ 67,65 75,66 @@ architecture a1 of rx is
signal curr_read_data : std_logic_vector(7 downto 0);
signal next_read_data : std_logic_vector(7 downto 0);
begin -- architecture a1
- read_ready_o <= '1' when curr_state /= SAVING_STRETCHING and (curr_saving = '0' or curr_read_data_filled = '0') else '0';
- scl_stretch_o <= '1' when curr_state = SAVING_STRETCHING else '0';
+ read_ready_o <= '1' when curr_saving = '0' or curr_read_data_filled = '0' or confirm_read_i = '1' else
+ '0';
+
+ scl_stretch_o <= '1' when curr_state = STRETCHING else '0';
+
read_data_o <= curr_read_data;
- -- IDLE -> RECEIVING on start_read,
- -- RECEIVING -> RECEIVING when not received full data
- -- RECEIVING -> SAVING when received all data
- -- SAVING -> SAVING_STRETCHING when cannot overrode data AND start_read
- -- SAVING -> RECEIVING when start_read AND overriding data now
- -- SAVING -> SAVING when cannot override data (data not read yet)
- -- SAVING -> IDLE when can override data
- -- SAVING_STRETCHING -> SAVING_STRETCHING when data not read yet
- -- SAVING_STRETCHING -> RECEIVING when data read
+ sda_enable_o <= '1' when curr_state = ACK_ON and generate_ack_i = '1' else
+ '0';
set_next_state: process(all) is
+ variable start_receive : std_logic;
begin -- process set_next_state
next_state <= curr_state;
+ start_receive := '0';
if curr_state = IDLE then
if start_read_i = '1' then
- next_state <= RECEIVING;
+ start_receive := '1';
end if;
elsif curr_state = RECEIVING then
if curr_rx_buffer(7) = '1' and scl_pulse_i = '1' then
- next_state <= SAVING;
+ next_state <= ACK;
end if;
- elsif curr_state = SAVING then
- if curr_read_data_filled = '0' then
- if start_read_i = '1' then
- next_state <= RECEIVING;
- else
- next_state <= IDLE;
- end if;
- elsif confirm_read_i = '1' then
+ elsif curr_state = ACK then
+ if scl_falling_delayed_i = '1' then
+ next_state <= ACK_ON;
+ end if;
+ elsif curr_state = ACK_ON then
+ if scl_falling_delayed_i = '1' then
if start_read_i = '1' then
- next_state <= RECEIVING; -- skip SAVING_STRETCHING
+ start_receive := '1';
else
next_state <= IDLE;
end if;
- elsif start_read_i = '1' then
- next_state <= SAVING_STRETCHING;
end if;
- elsif curr_state = SAVING_STRETCHING then
+ elsif curr_state = STRETCHING then
if confirm_read_i = '1' then
next_state <= RECEIVING;
end if;
end if;
- if ss_condition_i = '1' then
- if curr_saving = '1' and curr_read_data_filled = '1' then
- next_state <= SAVING;
+ if start_receive = '1' then
+ if curr_read_data_filled = '0' or confirm_read_i = '1' or curr_saving = '0' then
+ next_state <= RECEIVING;
else
- next_state <= IDLE;
+ next_state <= STRETCHING;
end if;
end if;
+
+ if ss_condition_i = '1' then
+ next_state <= IDLE;
+ end if;
end process set_next_state;
curr_receiving <= '1' when curr_state = RECEIVING else '0';
- curr_saving <= '1' when curr_state = SAVING or curr_state = SAVING_STRETCHING else '0';
+
+ next_saving <= '1' when curr_rx_buffer(7) = '1' and scl_pulse_i = '1' and curr_state = RECEIVING else
+ '1' when curr_saving = '1' and curr_read_data_filled = '1' and confirm_read_i = '0' else
+ '0';
read_valid_o <= curr_read_data_filled;
@@ 153,11 162,13 @@ begin -- architecture a1
curr_rx_buffer <= (others => '0');
curr_read_data_filled <= '0';
curr_state <= IDLE;
+ curr_saving <= '0';
else
curr_read_data <= next_read_data;
curr_rx_buffer <= next_rx_buffer;
curr_read_data_filled <= next_read_data_filled;
curr_state <= next_state;
+ curr_saving <= next_saving;
end if;
end if;
end process set_regs;
D src/i2c/sdascl_enabler.vhd => src/i2c/sdascl_enabler.vhd +0 -91
@@ 1,91 0,0 @@
-library ieee;
-use ieee.std_logic_1164.all;
-
-library utils;
-
-entity sdascl_enabler is
- generic (
- DELAY : natural);
-
- port (
- clk_i : in std_logic;
- rst_in : in std_logic;
-
- scl_i : in std_logic;
- sda_i : in std_logic;
-
- scl_falling_pulse_i : in std_logic;
-
- transmitting_i : in std_logic;
- receiving_i : in std_logic;
-
- expects_ack_i : in std_logic;
- generate_ack_i : in std_logic;
-
- tx_sda_i : in std_logic;
- tx_scl_stretch_i : in std_logic;
- rx_scl_stretch_i : in std_logic;
-
- sda_enable_o : out std_logic;
- scl_enable_o : out std_logic);
-
-end entity sdascl_enabler;
-
-architecture a1 of sdascl_enabler is
- type state_t is (TRANSMITTING, RECEIVING, EXPECTS_ACK, GENERATE_ACK, NONE);
- signal curr_state : state_t;
- signal next_state : state_t;
-
- signal curr_scl_enable : std_logic := '0';
- signal next_scl_enable : std_logic;
-
- signal any_stretch : std_logic;
- signal should_start_stretch : std_logic;
-
- signal delayed_scl_pulse : std_logic;
-begin -- architecture a1
- scl_falling_delay: entity utils.delay
- generic map (
- DELAY => DELAY)
- port map (
- clk_i => clk_i,
- rst_in => rst_in,
- signal_i => scl_falling_pulse_i,
- signal_o => delayed_scl_pulse);
-
- scl_enable_o <= curr_scl_enable;
- sda_enable_o <= '0' when curr_state = EXPECTS_ACK else
- '1' when curr_state = GENERATE_ACK else
- not tx_sda_i when curr_state = TRANSMITTING else
- '0';
-
- any_stretch <= '1' when
- (tx_scl_stretch_i = '1' and transmitting_i = '1') or
- (rx_scl_stretch_i = '1' and receiving_i = '1')
- else '0';
- should_start_stretch <= '1' when any_stretch = '1' and scl_i = '0' else '0';
-
- next_scl_enable <= '1' when should_start_stretch = '1' else
- '0' when any_stretch = '0' else
- curr_scl_enable;
-
- next_state <= TRANSMITTING when transmitting_i = '1' and delayed_scl_pulse = '1' else
- RECEIVING when receiving_i = '1' and delayed_scl_pulse = '1'else
- EXPECTS_ACK when expects_ack_i = '1' and delayed_scl_pulse = '1'else
- GENERATE_ACK when generate_ack_i = '1' and delayed_scl_pulse = '1'else
- curr_state;
-
- set_regs: process (clk_i) is
- begin -- process set_regs
- if rising_edge(clk_i) then -- rising clock edge
- if rst_in = '0' then -- synchronous reset (active low)
- curr_state <= NONE;
- curr_scl_enable <= '0';
- else
- curr_state <= next_state;
- curr_scl_enable <= next_scl_enable;
- end if;
- end if;
- end process set_regs;
-
-end architecture a1;
M src/i2c/slave_state.vhd => src/i2c/slave_state.vhd +2 -30
@@ 6,10 6,6 @@ entity i2c_slave_state is
clk_i : in std_logic;
rst_in : in std_logic;
- sda_i : in std_logic;
- scl_i : in std_logic;
- scl_pulse_i : in std_logic;
-
start_condition_i : in std_logic;
stop_condition_i : in std_logic;
@@ 17,14 13,10 @@ entity i2c_slave_state is
address_detect_success_i : in std_logic;
address_detect_fail_i : in std_logic;
address_detect_start_o : out std_logic;
- address_detect_active_o : out std_logic;
- expects_ack_o : out std_logic;
- generate_ack_o : out std_logic;
receive_o : out std_logic;
transmit_o : out std_logic;
- start_receive_o : out std_logic;
- start_transmit_o : out std_logic
+ bus_busy_o : out std_logic
);
end entity i2c_slave_state;
@@ 40,34 32,16 @@ architecture a1 of i2c_slave_state is
signal curr_state : slave_state;
signal next_state : slave_state;
- constant TRANSMIT_LEN : integer := 9;
- signal curr_data_position : integer range 0 to TRANSMIT_LEN-1;
- signal next_data_position : integer range 0 to TRANSMIT_LEN-1;
-
signal communicating_with_master : std_logic;
begin -- architecture a1
communicating_with_master <= '1' when curr_state = BUS_ADDRESS or curr_state = RECEIVING or curr_state = TRANSMITTING else '0';
- next_data_position <= 0 when start_condition_i = '1' else
- 0 when stop_condition_i = '1' or curr_state = BUS_FREE else
- (curr_data_position + 1) mod TRANSMIT_LEN when scl_pulse_i = '1' and communicating_with_master = '1' else
- curr_data_position;
-
- generate_ack_o <= '1' when next_data_position = TRANSMIT_LEN - 1 and
- (curr_state = BUS_ADDRESS or curr_state = RECEIVING)
- else '0';
- expects_ack_o <= '1' when next_data_position = TRANSMIT_LEN - 1 and
- (curr_state = TRANSMITTING)
- else '0';
-
address_detect_start_o <= '1' when start_condition_i = '1' else '0';
receive_o <= '1' when curr_state = RECEIVING else '0';
transmit_o <= '1' when curr_state = TRANSMITTING else '0';
-
- start_receive_o <= '1' when curr_data_position /= 0 and next_data_position = 0 and curr_state = RECEIVING else '0';
- start_transmit_o <= '1' when curr_data_position /= 0 and next_data_position = 0 and curr_state = TRANSMITTING else '0';
+ bus_busy_o <= '1' when curr_state = BUS_BUSY else '0';
next_state <= BUS_ADDRESS when start_condition_i = '1' else
-- BUS_BUSY when curr_state = BUS_FREE and (sda_i = '0' or scl_i = '0') else --
@@ 83,10 57,8 @@ begin -- architecture a1
if rising_edge(clk_i) then -- rising clock edge
if rst_in = '0' then -- synchronous reset (active low)
curr_state <= BUS_FREE;
- curr_data_position <= 0;
else
curr_state <= next_state;
- curr_data_position <= next_data_position;
end if;
end if;
end process set_regs;
M src/i2c/tx.vhd => src/i2c/tx.vhd +37 -26
@@ 20,20 20,21 @@ use ieee.std_logic_1164.all;
library utils;
entity tx is
- generic (
- DELAY_SDA_FOR : natural := 5); -- How many cycles to delay setting SDA
- -- after falling edge of scl
port (
clk_i : in std_logic;
rst_in : in std_logic;
start_write_i : in std_logic;
ss_condition_i : in std_logic; -- Reset rx circuitry
+ expect_ack_i : in std_logic;
+ err_noack_o : out std_logic;
+
scl_rising_pulse_i : in std_logic;
- scl_falling_pulse_i : in std_logic;
+ scl_falling_delayed_i : in std_logic;
scl_stretch_o : out std_logic;
- sda_o : out std_logic;
+ sda_i : in std_logic;
+ sda_enable_o : out std_logic;
ready_o : out std_logic;
valid_i : in std_logic;
@@ 46,7 47,7 @@ architecture a1 of tx is
-- SENDING - data are in the buffer, being sent
-- WAITING_FOR_SEND there were data written to the buffer, but cannot send now
-- WAITING_FOR_DATA should be sending, but there are no data - stretching
- type tx_state_t is (IDLE, WAITING_FOR_FALLING_EDGE, SENDING, WAITING_FOR_DATA);
+ type tx_state_t is (IDLE, WAITING_FOR_FALLING_EDGE, SENDING, ACK, WAITING_FOR_DATA);
signal curr_state : tx_state_t;
signal next_state : tx_state_t;
@@ 67,39 68,38 @@ architecture a1 of tx is
signal tx_buffer : std_logic_vector(8 downto 0);
signal tx_buffer_filled : std_logic;
- signal scl_delayed_pulse : std_logic;
signal curr_scl : std_logic;
signal next_scl : std_logic;
+ signal curr_err_noack : std_logic;
+ signal next_err_noack : std_logic;
+
signal ready : std_logic;
begin -- architecture a1
- scl_falling_delay: entity utils.delay
- generic map (
- DELAY => DELAY_SDA_FOR)
- port map (
- clk_i => clk_i,
- rst_in => rst_in,
- signal_i => scl_falling_pulse_i,
- signal_o => scl_delayed_pulse);
-
scl_stretch_o <= '1' when curr_state = WAITING_FOR_DATA else '0';
- ready_o <= ready;
- sda_o <= tx_buffer(8) when curr_state = SENDING else '1';
+ ready_o <= ready and not curr_err_noack;
+ sda_enable_o <= not tx_buffer(8) when curr_state = SENDING else '0';
+ err_noack_o <= curr_err_noack;
- ready <= '0' when curr_tx_buffers_filled(curr_saving_buffer_index) = '1' else '1';
+ ready <= '0' when curr_tx_buffers_filled(curr_saving_buffer_index) = '1' or curr_err_noack = '1' else '1';
tx_buffer <= curr_tx_buffers(curr_tx_buffer_index);
tx_buffer_filled <= curr_tx_buffers_filled(curr_tx_buffer_index);
next_scl <= '1' when scl_rising_pulse_i = '1' else
- '0' when scl_falling_pulse_i = '1' else
+ '0' when scl_falling_delayed_i = '1' else
curr_scl;
- next_tx_buffer_index <= (curr_tx_buffer_index + 1) mod 2 when tx_buffer(7 downto 0) = "10000000" and scl_delayed_pulse = '1' else
+ next_tx_buffer_index <= (curr_tx_buffer_index + 1) mod 2 when tx_buffer(7 downto 0) = "10000000" and scl_falling_delayed_i = '1' else
curr_tx_buffer_index;
next_saving_buffer_index <= (curr_saving_buffer_index + 1) mod 2 when ready = '1' and valid_i = '1' else
curr_saving_buffer_index;
+ next_err_noack <= '0' when expect_ack_i = '0' else
+ '1' when curr_err_noack = '1' else
+ '1' when curr_state = ACK and scl_rising_pulse_i = '1' and sda_i = '1' else
+ '0';
+
set_next_tx_buffers: process(all) is
begin -- process set_next_tx_buffer
next_tx_buffers <= curr_tx_buffers;
@@ 107,7 107,7 @@ begin -- architecture a1
next_tx_buffers(curr_saving_buffer_index) <= write_data_i & '1';
end if;
- if curr_state = SENDING and scl_delayed_pulse = '1' then
+ if curr_state = SENDING and scl_falling_delayed_i = '1' then
next_tx_buffers(curr_tx_buffer_index) <= tx_buffer(7 downto 0) & '0';
end if;
end process set_next_tx_buffers;
@@ 115,7 115,7 @@ begin -- architecture a1
set_next_buffer_filled: process(all) is
begin -- process set_next_buffer_filled
next_tx_buffers_filled <= curr_tx_buffers_filled;
- if tx_buffer(7 downto 0) = "10000000" and scl_delayed_pulse = '1' then
+ if tx_buffer(7 downto 0) = "10000000" and scl_falling_delayed_i = '1' then
next_tx_buffers_filled(curr_tx_buffer_index) <= '0';
end if;
@@ 137,11 137,15 @@ begin -- architecture a1
start_sending := '1';
end if;
elsif curr_state = WAITING_FOR_FALLING_EDGE then
- if scl_delayed_pulse = '1' then
+ if scl_falling_delayed_i = '1' then
next_state <= SENDING;
end if;
elsif curr_state = SENDING then
- if tx_buffer(7 downto 0) = "10000000" and scl_delayed_pulse = '1' then
+ if tx_buffer(7 downto 0) = "10000000" and scl_falling_delayed_i = '1' then
+ next_state <= ACK;
+ end if;
+ elsif curr_state = ACK then
+ if scl_rising_pulse_i = '1' then
if start_write_i = '1' then
override_tx_buffer_filled := curr_tx_buffers_filled(next_tx_buffer_index);
start_sending := '1';
@@ 158,12 162,17 @@ begin -- architecture a1
if start_sending = '1' then
if override_tx_buffer_filled = '0' and valid_i = '0' then
next_state <= WAITING_FOR_DATA;
- elsif curr_scl = '0' then
+ elsif curr_scl = '0' and scl_rising_pulse_i = '0' then
next_state <= SENDING;
else
next_state <= WAITING_FOR_FALLING_EDGE;
end if;
end if;
+
+ if curr_err_noack = '1' then
+ next_state <= IDLE; -- not doing anything after an error.
+ -- Waiting for ss condition or reset
+ end if;
end process set_next_state;
set_regs: process (clk_i) is
@@ 176,6 185,7 @@ begin -- architecture a1
curr_tx_buffers_filled <= "00";
curr_saving_buffer_index <= 0;
curr_scl <= '1'; -- assume 1 (the default, no one transmitting)
+ curr_err_noack <= '0';
else
curr_state <= next_state;
curr_tx_buffers <= next_tx_buffers;
@@ 183,6 193,7 @@ begin -- architecture a1
curr_tx_buffers_filled <= next_tx_buffers_filled;
curr_saving_buffer_index <= next_saving_buffer_index;
curr_scl <= next_scl;
+ curr_err_noack <= next_err_noack;
end if;
end if;
end process set_regs;
M tb/i2c/rx_tb.vhd => tb/i2c/rx_tb.vhd +29 -11
@@ 25,6 25,7 @@ architecture a1 of rx_tb is
signal start_read : std_logic := '0';
signal valid, ready : std_logic;
signal scl_stretch : std_logic;
+ signal sda_enable : std_logic;
signal confirm_read : std_logic := '0';
signal read_data : std_logic_vector(7 downto 0);
@@ 71,21 72,31 @@ architecture a1 of rx_tb is
sda <= data(i);
trigger_scl_pulse(scl_rising_pulse, scl_falling_pulse);
end loop; -- i
+
+ -- ack
+ check_equal(sda_enable, '1');
+
+ trigger_scl_pulse(scl_rising_pulse, scl_falling_pulse);
+
+ check_equal(sda_enable, '0');
end procedure transmit;
begin -- architecture a1
uut : entity i2c.rx
port map (
- clk_i => clk,
- rst_in => rst_n,
- ss_condition_i => '0',
- start_read_i => start_read,
- scl_pulse_i => scl_rising_pulse,
- sda_i => sda,
- scl_stretch_o => scl_stretch,
- read_valid_o => valid,
- read_ready_o => ready,
- read_data_o => read_data,
- confirm_read_i => confirm_read);
+ clk_i => clk,
+ rst_in => rst_n,
+ ss_condition_i => '0',
+ generate_ack_i => '1',
+ start_read_i => start_read,
+ scl_pulse_i => scl_rising_pulse,
+ scl_falling_delayed_i => scl_falling_pulse,
+ sda_i => sda,
+ sda_enable_o => sda_enable,
+ scl_stretch_o => scl_stretch,
+ read_valid_o => valid,
+ read_ready_o => ready,
+ read_data_o => read_data,
+ confirm_read_i => confirm_read);
clk <= not clk after CLK_PERIOD / 2;
rst_n <= '1' after 2 * CLK_PERIOD;
@@ 161,11 172,13 @@ begin -- architecture a1
confirm_read <= '1';
wait until falling_edge(clk);
+ confirm_read <= '1';
check_equal(read_data, std_logic_vector'("10000001"));
check_equal(valid, '1');
check_equal(ready, '1');
check_equal(scl_stretch, '0');
wait until falling_edge(clk);
+ confirm_read <= '0';
check_equal(valid, '0');
check_equal(ready, '1');
check_equal(scl_stretch, '0');
@@ 175,6 188,11 @@ begin -- architecture a1
check_equal(valid, '1');
check_equal(ready, '1');
check_equal(scl_stretch, '0');
+ confirm_read <= '1';
+ wait until falling_edge(clk);
+ check_equal(valid, '0');
+ check_equal(ready, '1');
+ check_equal(scl_stretch, '0');
end if;
end loop;
M tb/i2c/tx_tb.vhd => tb/i2c/tx_tb.vhd +62 -27
@@ 19,7 19,9 @@ architecture a1 of tx_tb is
signal rst_n : std_logic := '0';
- signal sda, scl : std_logic := '0';
+ signal sda : std_logic;
+ signal sda_override : std_logic := '0';
+ signal sda_enable, scl : std_logic := '0';
signal scl_rising_pulse, scl_falling_pulse : std_logic := '0';
signal start_write : std_logic := '0';
@@ 27,7 29,11 @@ architecture a1 of tx_tb is
signal write_data : std_logic_vector(7 downto 0);
signal scl_stretch : std_logic;
+ signal err_noack : std_logic;
+
signal validate_sda_stable_when_scl_high : std_logic := '0';
+ signal check_noerr : std_logic := '0';
+ signal zero : std_logic := '0';
procedure trigger_scl_pulse(
signal scl : inout std_logic;
@@ 72,6 78,8 @@ architecture a1 of tx_tb is
procedure check_received_data (
constant data : in std_logic_vector(7 downto 0);
constant check_ready : in std_logic;
+ constant trigger_ack : in std_logic;
+ signal sda_override : inout std_logic;
signal scl : inout std_logic;
signal scl_rising_pulse : inout std_logic;
signal scl_falling_pulse : inout std_logic) is
@@ 89,7 97,7 @@ architecture a1 of tx_tb is
end if;
for i in 7 downto 0 loop
- check_equal(sda, data(i));
+ check_equal(sda_enable, not data(i));
if check_ready /= 'Z' then
check_equal(ready, check_ready);
@@ 99,37 107,52 @@ architecture a1 of tx_tb is
trigger_scl_pulse(scl, scl_rising_pulse, scl_falling_pulse);
end loop; -- i
+
+ -- ack
+ if trigger_ack = '1' then
+ sda_override <= '1';
+ end if;
+
+ trigger_scl_pulse(scl, scl_rising_pulse, scl_falling_pulse);
+
+ if trigger_ack = '1' then
+ sda_override <= '0';
+ end if;
end procedure check_received_data;
begin -- architecture a1
uut : entity i2c.tx
- generic map (
- DELAY_SDA_FOR => 1)
port map (
- clk_i => clk,
- rst_in => rst_n,
- start_write_i => start_write,
- ss_condition_i => '0',
- scl_stretch_o => scl_stretch,
- scl_rising_pulse_i => scl_rising_pulse,
- scl_falling_pulse_i => scl_falling_pulse,
- sda_o => sda,
- ready_o => ready,
- valid_i => valid,
- write_data_i => write_data);
+ clk_i => clk,
+ rst_in => rst_n,
+ start_write_i => start_write,
+ ss_condition_i => '0',
+ expect_ack_i => '1',
+ err_noack_o => err_noack,
+ scl_stretch_o => scl_stretch,
+ scl_rising_pulse_i => scl_rising_pulse,
+ scl_falling_delayed_i => scl_falling_pulse,
+ sda_enable_o => sda_enable,
+ sda_i => sda,
+ ready_o => ready,
+ valid_i => valid,
+ write_data_i => write_data);
clk <= not clk after CLK_PERIOD / 2;
rst_n <= '1' after 2 * CLK_PERIOD;
+ sda <= '0' when sda_override = '1' else
+ not sda_enable;
+
main: process is
begin -- process
scl <= '1';
wait until rst_n = '1';
wait until falling_edge(clk);
+ check_noerr <= '1';
test_runner_setup(runner, runner_cfg);
set_stop_level(failure);
-
while test_suite loop
if run("simple") then
valid <= '1';
@@ 138,8 161,8 @@ begin -- architecture a1
start_write <= '1';
wait until falling_edge(clk);
valid <= '0';
- check_received_data("11010100", '1', scl, scl_rising_pulse, scl_falling_pulse);
- check_equal(sda, '1');
+ check_received_data("11010100", '1', '1', sda_override, scl, scl_rising_pulse, scl_falling_pulse);
+ check_equal(sda_enable, '0');
elsif run("twice") then
valid <= '1';
write_data <= "11010100";
@@ 152,10 175,10 @@ begin -- architecture a1
valid <= '0';
check_equal(ready, '0');
- check_received_data("11010100", '0', scl, scl_rising_pulse, scl_falling_pulse);
+ check_received_data("11010100", '0', '1', sda_override, scl, scl_rising_pulse, scl_falling_pulse);
wait until falling_edge(clk);
- check_received_data("00101011", '1', scl, scl_rising_pulse, scl_falling_pulse);
- check_equal(sda, '1');
+ check_received_data("00101011", '1', '1', sda_override, scl, scl_rising_pulse, scl_falling_pulse);
+ check_equal(sda_enable, '0');
elsif run("three") then
valid <= '1';
write_data <= "11010100";
@@ 168,16 191,16 @@ begin -- architecture a1
valid <= '0';
check_equal(ready, '0');
- check_received_data("11010100", '0', scl, scl_rising_pulse, scl_falling_pulse);
+ check_received_data("11010100", '0', '1', sda_override, scl, scl_rising_pulse, scl_falling_pulse);
wait until falling_edge(clk);
check_equal(ready, '1');
write_data <= "00001111";
valid <= '1';
wait until falling_edge(clk);
valid <= '0';
- check_received_data("00101011", '0', scl, scl_rising_pulse, scl_falling_pulse);
- check_received_data("00001111", '1', scl, scl_rising_pulse, scl_falling_pulse);
- check_equal(sda, '1');
+ check_received_data("00101011", '0', '1', sda_override, scl, scl_rising_pulse, scl_falling_pulse);
+ check_received_data("00001111", '1', '1', sda_override, scl, scl_rising_pulse, scl_falling_pulse);
+ check_equal(sda_enable, '0');
elsif run("stretching") then
start_write <= '1';
check_equal(scl_stretch, '0');
@@ 192,12 215,24 @@ begin -- architecture a1
wait until falling_edge(clk);
valid <= '0';
check_equal(scl_stretch, '0');
- check_received_data("11001100", '1', scl, scl_rising_pulse, scl_falling_pulse);
+ check_received_data("11001100", '1', '1', sda_override, scl, scl_rising_pulse, scl_falling_pulse);
+ elsif run("no_ack") then
+ valid <= '1';
+ write_data <= "11010100";
+ check_equal(ready, '1');
+ start_write <= '1';
+ wait until falling_edge(clk);
+ valid <= '0';
+ check_noerr <= '0'; -- disable no err check
+ check_received_data("11010100", '1', '0', sda_override, scl, scl_rising_pulse, scl_falling_pulse);
+ check_equal(err_noack, '1');
+ check_equal(sda_enable, '0');
end if;
end loop;
test_runner_cleanup(runner);
end process;
- stability_check: check_stable(clk, validate_sda_stable_when_scl_high, scl_rising_pulse, scl_falling_pulse, sda);
+ no_err: check_stable(clk, check_noerr, check_noerr, zero, err_noack);
+ stability_check: check_stable(clk, validate_sda_stable_when_scl_high, scl_rising_pulse, scl_falling_pulse, sda_enable);
end architecture a1;