OpenCores
URL https://opencores.org/ocsvn/iicmb/iicmb/trunk

Subversion Repositories iicmb

[/] [iicmb/] [trunk/] [src_tb/] [iicmb_m_wb_tb.vhd] - Rev 5

Compare with Previous | Blame | View Log

 
--==============================================================================
--                                                                             |
--    Project: IIC Multiple Bus Controller (IICMB)                             |
--                                                                             |
--    Module:  Testbench for 'iicmb_m_wb'.                                     |
--    Version:                                                                 |
--             1.0,   April 29, 2016                                           |
--             1.1,   May   10, 2016 Changed i2c_slave_model instance          |
--                                   parameter interface                       |
--                                                                             |
--    Author:  Sergey Shuvalkin, (sshuv2@opencores.org)                        |
--                                                                             |
--==============================================================================
--==============================================================================
-- Copyright (c) 2016, Sergey Shuvalkin                                        |
-- All rights reserved.                                                        |
--                                                                             |
-- Redistribution and use in source and binary forms, with or without          |
-- modification, are permitted provided that the following conditions are met: |
--                                                                             |
-- 1. Redistributions of source code must retain the above copyright notice,   |
--    this list of conditions and the following disclaimer.                    |
-- 2. Redistributions in binary form must reproduce the above copyright        |
--    notice, this list of conditions and the following disclaimer in the      |
--    documentation and/or other materials provided with the distribution.     |
--                                                                             |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   |
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  |
-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE    |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR         |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF        |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN     |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)     |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  |
-- POSSIBILITY OF SUCH DAMAGE.                                                 |
--==============================================================================
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library iicmb;
use iicmb.iicmb_pkg.all;
 
use work.test.all;
 
 
--==============================================================================
entity iicmb_m_wb_tb is
end entity iicmb_m_wb_tb;
--==============================================================================
 
--==============================================================================
architecture beh of iicmb_m_wb_tb is
 
  constant c_f_clk   : real      := 100000.0; -- in kHz
  constant c_f_scl_0 : real      :=    100.0; -- in kHz
  constant c_f_scl_1 : real      :=    100.0; -- in kHz
  constant c_f_scl_2 : real      :=    100.0; -- in kHz
  constant c_f_scl_3 : real      :=    100.0; -- in kHz
  constant c_p_clk   : time      := integer(1000000000.0/c_f_clk) * 1 ps;
 
  constant c_bus_num : positive  := 4;
 
  ------------------------------------------------------------------------------
  component iicmb_m_wb is
    generic
    (
      g_bus_num   :       positive range 1 to 16 := 1;
      g_f_clk     :       real                   := 100000.0;
      g_f_scl_0   :       real                   :=    100.0;
      g_f_scl_1   :       real                   :=    100.0;
      g_f_scl_2   :       real                   :=    100.0;
      g_f_scl_3   :       real                   :=    100.0;
      g_f_scl_4   :       real                   :=    100.0;
      g_f_scl_5   :       real                   :=    100.0;
      g_f_scl_6   :       real                   :=    100.0;
      g_f_scl_7   :       real                   :=    100.0;
      g_f_scl_8   :       real                   :=    100.0;
      g_f_scl_9   :       real                   :=    100.0;
      g_f_scl_a   :       real                   :=    100.0;
      g_f_scl_b   :       real                   :=    100.0;
      g_f_scl_c   :       real                   :=    100.0;
      g_f_scl_d   :       real                   :=    100.0;
      g_f_scl_e   :       real                   :=    100.0;
      g_f_scl_f   :       real                   :=    100.0
    );
    port
    (
      clk_i       : in    std_logic;
      rst_i       : in    std_logic;
      cyc_i       : in    std_logic;
      stb_i       : in    std_logic;
      ack_o       :   out std_logic;
      adr_i       : in    std_logic_vector(1 downto 0);
      we_i        : in    std_logic;
      dat_i       : in    std_logic_vector(7 downto 0);
      dat_o       :   out std_logic_vector(7 downto 0);
      irq         :   out std_logic;
      scl_i       : in    std_logic_vector(0 to g_bus_num - 1);
      sda_i       : in    std_logic_vector(0 to g_bus_num - 1);
      scl_o       :   out std_logic_vector(0 to g_bus_num - 1);
      sda_o       :   out std_logic_vector(0 to g_bus_num - 1)
    );
  end component iicmb_m_wb;
  ------------------------------------------------------------------------------
 
  ------------------------------------------------------------------------------
  component wire_mdl is
    generic
    (
      g_resistance_0       :       real       := 1.0; -- In Ohms
      g_resistance_1       :       real       := 1.0; -- In Ohms
      g_capacitance        :       real       := 1.0; -- In pF
      g_initial_level      :       bit        := '0'
    );
    port
    (
      sig_in               : in    bit;
      sig_out              :   out real;
      sig_out_l            :   out bit
    );
  end component wire_mdl;
  ------------------------------------------------------------------------------
 
  ------------------------------------------------------------------------------
  component i2c_slave_model is
    generic
    (
      I2C_ADR : integer
    );
    port
    (
      scl     : inout std_logic;
      sda     : inout std_logic
    );
  end component i2c_slave_model;
  ------------------------------------------------------------------------------
 
  ------------------------------------------------------------------------------
  function get_slave_addr(n : natural) return std_logic_vector is
    variable ret : std_logic_vector(6 downto 0);
  begin
    ret := "010" & std_logic_vector(to_unsigned(n, 4));
    return ret;
  end function get_slave_addr;
  ------------------------------------------------------------------------------
 
  signal   clk_i         : std_logic := '0';
  signal   rst_i         : std_logic := '1';
  signal   cyc_i         : std_logic := '0';
  signal   stb_i         : std_logic := '0';
  signal   ack_o         : std_logic;
  signal   adr_i         : std_logic_vector(1 downto 0) := "00";
  signal   we_i          : std_logic := '0';
  signal   dat_i         : std_logic_vector(7 downto 0) := "00000000";
  signal   dat_o         : std_logic_vector(7 downto 0);
 
  signal   scl_o         : std_logic_vector(0 to c_bus_num - 1) := (others => '1');
  signal   scl           : std_logic_vector(0 to c_bus_num - 1) := (others => 'H');
  signal   sda_o         : std_logic_vector(0 to c_bus_num - 1) := (others => '1');
  signal   sda           : std_logic_vector(0 to c_bus_num - 1) := (others => 'H');
 
  type real_vector is array (natural range <>) of real;
  signal   scl_real      : real_vector(0 to c_bus_num - 1);
  signal   sda_real      : real_vector(0 to c_bus_num - 1);
  signal   scl_quant     : bit_vector(0 to c_bus_num - 1);
  signal   sda_quant     : bit_vector(0 to c_bus_num - 1);
  signal   scl_nquant    : bit_vector(0 to c_bus_num - 1) := (others => '1');
  signal   sda_nquant    : bit_vector(0 to c_bus_num - 1) := (others => '1');
  signal   irq           : std_logic;
 
  ---- Byte-wide commands:
  constant wb_m_set_bus  : std_logic_vector(7 downto 0) := "00000" & mcmd_set_bus;
  constant wb_m_write    : std_logic_vector(7 downto 0) := "00000" & mcmd_write;
  constant wb_m_read_ack : std_logic_vector(7 downto 0) := "00000" & mcmd_read_ack;
  constant wb_m_read_nak : std_logic_vector(7 downto 0) := "00000" & mcmd_read_nak;
  constant wb_m_start    : std_logic_vector(7 downto 0) := "00000" & mcmd_start;
  constant wb_m_stop     : std_logic_vector(7 downto 0) := "00000" & mcmd_stop;
  constant wb_m_wait     : std_logic_vector(7 downto 0) := "00000" & mcmd_wait;
 
begin
 
  clk_i <= not(clk_i) after c_p_clk / 2;
  rst_i <= '1', '0' after 113 ns;
 
  ------------------------------------------------------------------------------
  -- Wishbone bus activity process:
  process
    ----------------------------------------------------------------------------
    procedure wb_write(addr : in std_logic_vector(1 downto 0); data : in std_logic_vector(7 downto 0)) is
    begin
      cyc_i   <= '1';
      stb_i   <= '1';
      adr_i   <= addr;
      we_i    <= '1';
      dat_i   <= data;
      wait until rising_edge(clk_i)and(ack_o = '1');
      cyc_i   <= '0';
      stb_i   <= '0';
      print_string("Wishbone Write: 0x" & to_string(addr, "X", 2) & " : " & "0x" & to_string(data, "X", 2) & newline);
    end procedure wb_write;
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    procedure wb_read(addr : in std_logic_vector(1 downto 0); data : out std_logic_vector(7 downto 0)) is
    begin
      cyc_i   <= '1';
      stb_i   <= '1';
      adr_i   <= addr;
      we_i    <= '0';
      wait until rising_edge(clk_i)and(ack_o = '1');
      data    := dat_o;
      cyc_i   <= '0';
      stb_i   <= '0';
      print_string("Wishbone Read : 0x" & to_string(addr, "X", 2) & " : " & "0x" & to_string(dat_o, "X", 2) & newline);
    end procedure wb_read;
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    procedure wb_wait(n : in positive) is
    begin
      print_string("Wishbone Waiting for " & integer'image(n) & " cycles." & newline);
      cyc_i   <= '0';
      stb_i   <= '0';
      for i in 0 to n - 1 loop
        wait until rising_edge(clk_i);
      end loop;
    end procedure wb_wait;
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    procedure wb_halt is
    begin
      print_string("Wishbone Halted" & newline);
      cyc_i   <= '0';
      stb_i   <= '0';
      wait;
    end procedure wb_halt;
    ----------------------------------------------------------------------------
    procedure i2c_write_byte(slave_addr : in std_logic_vector(6 downto 0); addr : in std_logic_vector(7 downto 0); data : in std_logic_vector(7 downto 0)) is
      variable v_tmp : std_logic_vector(7 downto 0);
    begin
      wb_write("10", wb_m_start);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("01", slave_addr & "0");
      wb_write("10", wb_m_write);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("01", addr);
      wb_write("10", wb_m_write);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("01", data);
      wb_write("10", wb_m_write);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("10", wb_m_stop);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
    end procedure i2c_write_byte;
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    procedure i2c_read_byte(slave_addr : in std_logic_vector(6 downto 0); addr : in std_logic_vector(7 downto 0); data : out std_logic_vector(7 downto 0)) is
      variable v_tmp : std_logic_vector(7 downto 0);
    begin
      wb_write("10", wb_m_start);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("01", slave_addr & "0");
      wb_write("10", wb_m_write);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("01", addr);
      wb_write("10", wb_m_write);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("10", wb_m_start);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("01", slave_addr & "1");
      wb_write("10", wb_m_write);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      --
      wb_write("10", wb_m_read_nak);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
      wb_read("01", data);
      --
      wb_write("10", wb_m_stop);
      wait until rising_edge(clk_i)and(irq = '1');
      wb_read("10", v_tmp);
      assert (v_tmp(7) = '1') report "Something gone wrong" severity error;
    end procedure i2c_read_byte;
    ----------------------------------------------------------------------------
    variable v_data : std_logic_vector(7 downto 0);
  begin
    -- Initial delay:
    wb_wait(100);
 
    --
    wb_read("00", v_data);
    wb_read("01", v_data);                                           
    wb_read("10", v_data);                                           
    wb_wait(1);
    wb_read("11", v_data);                                           
    --
    wb_wait(10);
    -- Enable controller and interrupts
    wb_write("00", "11000000");
    wb_read("00", v_data);
    --
    -- Select Bus #1
    wb_wait(10);
    wb_write("01", "00000001");
    wb_write("10", wb_m_set_bus);
    wb_wait(1);
    wb_read("10", v_data);
    --
 
    --
    wb_wait(10);
    i2c_write_byte(get_slave_addr(1), x"00", x"4A");
    i2c_write_byte(get_slave_addr(1), x"01", x"67");
    --
 
    --
    wb_wait(10);
    i2c_read_byte(get_slave_addr(1), x"00", v_data);
    print_string("Data read: " & to_string(v_data, "X", 2) & newline);
    i2c_read_byte(get_slave_addr(1), x"01", v_data);
    print_string("Data read: " & to_string(v_data, "X", 2) & newline);
    --
 
    -- Halt bus activity
    wb_halt;
  end process;
  ------------------------------------------------------------------------------
 
  ------------------------------------------------------------------------------
  dut : iicmb_m_wb
    generic map
    (
      g_bus_num   => c_bus_num,
      g_f_clk     => c_f_clk,
      g_f_scl_0   => c_f_scl_0,
      g_f_scl_1   => c_f_scl_1,
      g_f_scl_2   => c_f_scl_2,
      g_f_scl_3   => c_f_scl_3
    )
    port map
    (
      clk_i       => clk_i,
      rst_i       => rst_i,
      cyc_i       => cyc_i,
      stb_i       => stb_i,
      ack_o       => ack_o,
      adr_i       => adr_i,
      we_i        => we_i,
      dat_i       => dat_i,
      dat_o       => dat_o,
      irq         => irq,
      scl_i       => to_stdlogicvector(scl_quant),
      sda_i       => to_stdlogicvector(sda_quant),
      scl_o       => scl_o,
      sda_o       => sda_o
    );
  ------------------------------------------------------------------------------
 
  --****************************************************************************
  bus_gen:
  for i in 0 to c_bus_num - 1 generate
    scl(i) <= '0' when (scl_o(i) = '0') else 'Z';
    sda(i) <= '0' when (sda_o(i) = '0') else 'Z';
 
    ----------------------------------------------------------------------------
    wire_mdl_inst_0 : wire_mdl
      generic map
      (
        g_resistance_0       => 40.0,
        g_resistance_1       => 4000.0,
        g_capacitance        => 200.0, -- In pF
        g_initial_level      => '1'
      )
      port map
      (
        sig_in               => scl_nquant(i),
        sig_out              => scl_real(i),
        sig_out_l            => scl_quant(i)
      );
    ----------------------------------------------------------------------------
 
    ----------------------------------------------------------------------------
    wire_mdl_inst_1 : wire_mdl
      generic map
      (
        g_resistance_0       => 40.0,
        g_resistance_1       => 4000.0,
        g_capacitance        => 200.0, -- In pF
        g_initial_level      => '1'
      )
      port map
      (
        sig_in               => sda_nquant(i),
        sig_out              => sda_real(i),
        sig_out_l            => sda_quant(i)
      );
    ----------------------------------------------------------------------------
 
    ----------------------------------------------------------------------------
    i2c_slave_model_inst0 : i2c_slave_model
      generic map
      (
        I2C_ADR => to_integer(unsigned(get_slave_addr(i)))
      )
      port map
      (
        scl     => scl(i),
        sda     => sda(i)
      );
    ----------------------------------------------------------------------------
  end generate bus_gen;
  --****************************************************************************
 
  scl <= (others => 'H'); -- Pull up
  sda <= (others => 'H'); -- Pull up
 
  scl_nquant <= to_bitvector(to_x01(scl));
  sda_nquant <= to_bitvector(to_x01(sda));
 
end architecture beh;
--==============================================================================
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.