~ruther/vhdl-i2c

4b483a5b6e72335f720515624f3a1903b771bd6a — Rutherther 1 year, 3 months ago a284ba6
tests: add startstop condition detector tests, fix behavior
2 files changed, 133 insertions(+), 13 deletions(-)

M src/i2c/startstop_condition_detector.vhd
A tb/i2c/startstop_condition_detector_tb.vhd
M src/i2c/startstop_condition_detector.vhd => src/i2c/startstop_condition_detector.vhd +17 -13
@@ 13,28 13,32 @@ entity startstop_condition_detector is
end entity startstop_condition_detector;

architecture a1 of startstop_condition_detector is
  signal reg_start, reg_stop : std_logic;
  signal next_start, next_stop : std_logic;
  -- signal curr_start, curr_stop : std_logic;
  -- signal next_start, next_stop : std_logic;

  signal reg_prev_sda : std_logic;
  signal next_prev_sda : std_logic;
  signal curr_prev_sda, curr_prev_scl : std_logic;
  signal next_prev_sda, next_prev_scl : std_logic;
begin  -- architecture a1
  -- start_o <= curr_start;
  -- stop_o <= curr_stop;

  next_prev_sda <= sda_i;
  next_prev_scl <= scl_i;

  next_start <= '0' when reg_start = '1' else
                '1' when reg_prev_sda = '0' and sda_i = '1' and scl_i = '1' else
                '0';
  next_stop <= '0' when reg_stop = '1' else
               '1' when reg_prev_sda = '1' and sda_i = '0' and scl_i = '1' else
               '0';
  start_o <= -- '0' when curr_start = '1' else
             '1' when curr_prev_sda = '1' and sda_i = '0' and curr_prev_scl = '1' and scl_i = '1' else
             '0';
  stop_o <= -- '0' when curr_stop = '1' else
            '1' when curr_prev_sda = '0' and sda_i = '1' and curr_prev_scl = '1' and scl_i = '1' else
            '0';

  set_next: process (clk_i) is
  begin  -- process set_next
    if rising_edge(clk_i) then          -- rising clock edge
      reg_prev_sda <= next_prev_sda;
      reg_start <= next_start;
      reg_stop <= next_stop;
      curr_prev_sda <= next_prev_sda;
      curr_prev_scl <= next_prev_scl;
      -- curr_start <= next_start;
      -- curr_stop <= next_stop;
    end if;
  end process set_next;


A tb/i2c/startstop_condition_detector_tb.vhd => tb/i2c/startstop_condition_detector_tb.vhd +116 -0
@@ 0,0 1,116 @@
library ieee;
use ieee.std_logic_1164.all;

library i2c;

library vunit_lib;
context vunit_lib.vunit_context;

entity startstop_condition_detector is

  generic (
    runner_cfg : string);

end entity startstop_condition_detector;

architecture tb of startstop_condition_detector is
  signal clk : std_logic := '0';
  constant CLK_PERIOD : time := 10 ns;

  signal rst_n : std_logic := '0';

  signal sda, scl : std_logic;

  signal start, stop : std_logic;
begin  -- architecture tb
  uut: entity i2c.startstop_condition_detector
    port map (
      clk_i   => clk,
      sda_i   => sda,
      scl_i   => scl,
      start_o => start,
      stop_o  => stop);

  clk <= not clk after CLK_PERIOD / 2;
  rst_n <= '1' after 2 * CLK_PERIOD;

  main: process is
  begin  -- process
    sda <= '1';
    wait until rising_edge(clk);
    scl <= '1';
    wait until rst_n = '1';
    wait until falling_edge(clk);

    test_runner_setup(runner, runner_cfg);
    set_stop_level(failure);

    while test_suite loop
      if run("scl_high_start_stop") then
        -- start
        sda <= '0';
        wait until rising_edge(clk);
        check_equal(start, '1');
        check_equal(stop, '0');
        sda <= '1';
        wait until rising_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '1');
        sda <= '1';
        wait until rising_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '0');
        sda <= '1';
      elsif run("scl_low") then
        scl <= '0';
        sda <= '0';
        wait until falling_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '0');
        sda <= '1';
        wait until falling_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '0');
        sda <= '1';
        wait until falling_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '0');
        sda <= '1';
      elsif run("scl_low_then_high") then
        scl <= '0';
        sda <= '0';
        wait until rising_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '0');
        sda <= '1';
        wait until rising_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '0');
        sda <= '1';
        wait until rising_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '0');
        sda <= '1';
        wait until rising_edge(clk);
        scl <= '1';
        wait until rising_edge(clk);
        sda <= '0';
        wait until rising_edge(clk);
        check_equal(start, '1');
        check_equal(stop, '0');
        sda <= '1';
        wait until rising_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '1');
        sda <= '1';
        wait until rising_edge(clk);
        check_equal(start, '0');
        check_equal(stop, '0');
        sda <= '1';
      end if;
    end loop;

    test_runner_cleanup(runner);
  end process main;

end architecture tb;

Do not follow this link