diff --git a/modules/common/gc_glitch_filt.vhd b/modules/common/gc_glitch_filt.vhd
index b291d8af1dd6ea7eaefdda1e7f66bfd808a2a9ea..bbd8fbb7f09c2229e99c993069465e0ac10c8e91 100644
--- a/modules/common/gc_glitch_filt.vhd
+++ b/modules/common/gc_glitch_filt.vhd
@@ -66,29 +66,10 @@ end entity gc_glitch_filt;
 
 architecture behav of gc_glitch_filt is
 
-  --============================================================================
-  -- Component declarations
-  --============================================================================
-  component gc_sync_ffs is
-    generic(
-      g_sync_edge : string := "positive"
-      );
-    port(
-      clk_i    : in  std_logic;  -- clock from the destination clock domain
-      rst_n_i  : in  std_logic;           -- reset
-      data_i   : in  std_logic;           -- async input
-      synced_o : out std_logic;           -- synchronized output
-      npulse_o : out std_logic;  -- negative edge detect output (single-clock
-      -- pulse)
-      ppulse_o : out std_logic   -- positive edge detect output (single-clock
-     -- pulse)
-      );
-  end component gc_sync_ffs;
-
   --============================================================================
   -- Signal declarations
   --============================================================================
-  signal gc_glitch_filt : std_logic_vector(g_len downto 0);
+  signal glitch_filt : std_logic_vector(g_len downto 0);
   signal dat_synced  : std_logic;
 
 --==============================================================================
@@ -112,7 +93,7 @@ begin
     );
 
   -- Then, assign the current sample of the glitch filter
-  gc_glitch_filt(0) <= dat_synced;
+  glitch_filt(0) <= dat_synced;
 
   -- Generate glitch filter FFs when the filter length is > 0
   gen_glitch_filt: if (g_len > 0) generate
@@ -120,9 +101,9 @@ begin
     begin
       if rising_edge(clk_i) then
         if (rst_n_i = '0') then
-          gc_glitch_filt(g_len downto 1) <= (others => '0');
+          glitch_filt(g_len downto 1) <= (others => '0');
         else
-          gc_glitch_filt(g_len downto 1) <= gc_glitch_filt(g_len-1 downto 0);
+          glitch_filt(g_len downto 1) <= glitch_filt(g_len-1 downto 0);
         end if;
       end if;
     end process p_glitch_filt;
@@ -134,9 +115,9 @@ begin
     if rising_edge(clk_i) then
       if (rst_n_i = '0') then
         dat_o <= '0';
-      elsif (gc_glitch_filt = (gc_glitch_filt'range => '1')) then
+      elsif (glitch_filt = (glitch_filt'range => '1')) then
         dat_o <= '1';
-      elsif (gc_glitch_filt = (gc_glitch_filt'range => '0')) then
+      elsif (glitch_filt = (glitch_filt'range => '0')) then
         dat_o <= '0';
       end if;
     end if;
diff --git a/modules/common/gc_i2c_slave.vhd b/modules/common/gc_i2c_slave.vhd
index b549e21b7ed7958176b7e34dd62ea0ef7badfeef..d7c0111c2d030d5c166992c8ad2a2ab41d0dbde5 100644
--- a/modules/common/gc_i2c_slave.vhd
+++ b/modules/common/gc_i2c_slave.vhd
@@ -49,6 +49,8 @@
 --==============================================================================
 -- last changes:
 --    2013-03-13   Theodor Stana     t.stana@cern.ch     File created
+--    2013-11-22   Theodor Stana                         Changed to sampling SDA
+--                                                       on SCL rising edge
 --==============================================================================
 -- TODO:
 --    - Stop condition
@@ -61,53 +63,57 @@ use ieee.numeric_std.all;
 use work.gencores_pkg.all;
 
 entity gc_i2c_slave is
+  generic
+  (
+    -- Length of glitch filter
+    -- 0 - SCL and SDA lines are passed only through synchronizer
+    -- 1 - one clk_i glitches filtered
+    -- 2 - two clk_i glitches filtered
+    g_gf_len : natural := 0
+  );
   port
   (
     -- Clock, reset ports
-    clk_i      : in  std_logic;
-    rst_n_i    : in  std_logic;
+    clk_i         : in  std_logic;
+    rst_n_i       : in  std_logic;
 
     -- I2C lines
-    scl_i      : in  std_logic;
-    scl_o      : out std_logic;
-    scl_en_o   : out std_logic;
-    sda_i      : in  std_logic;
-    sda_o      : out std_logic;
-    sda_en_o   : out std_logic;
+    scl_i         : in  std_logic;
+    scl_o         : out std_logic;
+    scl_en_o      : out std_logic;
+    sda_i         : in  std_logic;
+    sda_o         : out std_logic;
+    sda_en_o      : out std_logic;
 
     -- Slave address
-    i2c_addr_i : in  std_logic_vector(6 downto 0);
+    addr_i        : in  std_logic_vector(6 downto 0);
 
     -- ACK input, should be set after done_p_o = '1'
     -- (note that the bit is reversed wrt I2C ACK bit)
     -- '1' - ACK
     -- '0' - NACK
-    i2c_ack_i  : in  std_logic;
-
-    -- I2C bus operation, set after address detection
-    -- '0' - write
-    -- '1' - read
-    op_o       : out std_logic;
+    ack_i         : in  std_logic;
 
     -- Byte to send, should be loaded while done_p_o = '1'
-    tx_byte_i  : in  std_logic_vector(7 downto 0);
+    tx_byte_i     : in  std_logic_vector(7 downto 0);
 
     -- Received byte, valid after done_p_o = '1'
-    rx_byte_o  : out std_logic_vector(7 downto 0);
-
-    -- Done pulse signal, valid when
-    -- * received address matches i2c_addr_i, signaling valid op_o;
-    -- * a byte was received, signaling valid rx_byte_o and an ACK/NACK should be
-    -- sent to master;
-    -- * sent a byte, should set tx_byte_i.
-    done_p_o   : out std_logic;
-
-    -- I2C transfer state
-    -- "00" - Idle
-    -- "01" - Got address, matches i2c_addr_i
-    -- "10" - Read done, waiting ACK/NACK
-    -- "11" - Write done, waiting next byte
-    stat_o     : out std_logic_vector(1 downto 0)
+    rx_byte_o     : out std_logic_vector(7 downto 0);
+
+    -- Pulse outputs signaling various I2C actions
+    -- Start and stop conditions
+    sta_p_o       : out std_logic;
+    sto_p_o       : out std_logic;
+    -- Received address corresponds addr_i
+    addr_good_p_o : out std_logic;
+    -- Read and write done
+    r_done_p_o    : out std_logic;
+    w_done_p_o    : out std_logic;
+
+    -- I2C bus operation, set after address detection
+    -- '0' - write
+    -- '1' - read
+    op_o          : out std_logic
   );
 end entity gc_i2c_slave;
 
@@ -120,8 +126,8 @@ architecture behav of gc_i2c_slave is
   type t_state is
     (
       IDLE,            -- idle
-      STA,             -- start condition received
       ADDR,            -- shift in I2C address bits
+      ADDR_CHECK,      -- check received I2C address
       ADDR_ACK,        -- ACK/NACK to I2C address
       RD,              -- shift in byte to read
       RD_ACK,          -- ACK/NACK to received byte
@@ -134,8 +140,8 @@ architecture behav of gc_i2c_slave is
   -- Signal declarations
   --============================================================================
   -- Deglitched signals and delays for SCL and SDA lines
-  signal scl_deglitched     : std_logic;
-  signal scl_deglitched_d0  : std_logic;
+  signal scl_deglitched    : std_logic;
+  signal scl_deglitched_d0 : std_logic;
   signal sda_deglitched    : std_logic;
   signal sda_deglitched_d0 : std_logic;
   signal scl_r_edge_p      : std_logic;
@@ -143,30 +149,32 @@ architecture behav of gc_i2c_slave is
   signal sda_f_edge_p      : std_logic;
   signal sda_r_edge_p      : std_logic;
 
-  -- FSM
-  signal state : t_state;
-
-  -- FSM tick
-  signal tick_p   : std_logic;
-  signal tick_cnt : std_logic_vector(5 downto 0);
+  -- FSM signals
+  signal state             : t_state;
+  signal inhibit           : std_logic;
 
   -- RX and TX shift registers
-  signal txsr : std_logic_vector(7 downto 0);
-  signal rxsr : std_logic_vector(7 downto 0);
+  signal txsr              : std_logic_vector(7 downto 0);
+  signal rxsr              : std_logic_vector(7 downto 0);
 
   -- Bit counter on RX & TX
-  signal bit_cnt : unsigned(2 downto 0);
+  signal bit_cnt           : unsigned(2 downto 0);
+
+  -- Start and stop condition pulse signals
+  signal sta_p, sto_p      : std_logic;
 
-  -- Watchdog counter signals
-  signal watchdog_cnt    : unsigned(26 downto 0);
-  signal watchdog_rst    : std_logic;
-  signal rst_fr_watchdog : std_logic;
+  -- Master ACKed after it has read a byte from the slave
+  signal mst_acked         : std_logic;
+
+
+  signal sda_en : std_logic;
 
 --==============================================================================
 --  architecture begin
 --==============================================================================
 begin
 
+  sda_en_o  <= sda_en;
   --============================================================================
   -- I/O logic
   --============================================================================
@@ -187,7 +195,7 @@ begin
   cmp_scl_deglitch : gc_glitch_filt
     generic map
     (
-      g_len => 7
+      g_len => g_gf_len
     )
     port map
     (
@@ -203,9 +211,9 @@ begin
   begin
     if rising_edge(clk_i) then
       if (rst_n_i = '0') then
-        scl_deglitched_d0  <= '0';
-        scl_f_edge_p       <= '0';
-        scl_r_edge_p       <= '0';
+        scl_deglitched_d0 <= '0';
+        scl_f_edge_p      <= '0';
+        scl_r_edge_p      <= '0';
       else
         scl_deglitched_d0 <= scl_deglitched;
         scl_f_edge_p      <= (not scl_deglitched) and scl_deglitched_d0;
@@ -218,7 +226,7 @@ begin
   cmp_sda_deglitch : gc_glitch_filt
     generic map
     (
-      g_len => 7
+      g_len => g_gf_len
     )
     port map
     (
@@ -234,9 +242,9 @@ begin
   begin
     if rising_edge(clk_i) then
       if (rst_n_i = '0') then
-        sda_deglitched_d0  <= '0';
-        sda_f_edge_p       <= '0';
-        sda_r_edge_p       <= '0';
+        sda_deglitched_d0 <= '0';
+        sda_f_edge_p      <= '0';
+        sda_r_edge_p      <= '0';
       else
         sda_deglitched_d0 <= sda_deglitched;
         sda_f_edge_p      <= (not sda_deglitched) and sda_deglitched_d0;
@@ -246,30 +254,23 @@ begin
   end process p_sda_deglitched_d0;
 
   --============================================================================
-  -- Tick generation
+  -- Start and stop condition outputs
   --============================================================================
---  p_tick : process (clk_i) is
---  begin
---    if rising_edge(clk_i) then
---      if (rst_n_i = '0') then
---        tick_cnt <= '0';
---        tick_p   <= '0';
---      elsif (scl_f_edge_p = '1') then
---        tick_en <= '1';
---      else
---        if (tick_en = '1') then
---          tick_cnt <= tick_cnt + 1;
---          tick_p   <= '0';
---          if (tick_cnt = (tick_cnt'range => '1')) then
---            tick_p  <= '1';
---            tick_en <= '0';
---          end if;
---        else
---          tick_p <= '0';
---        end if;
---      end if;
---    end if;
---  end process p_tick;
+  p_sta_sto : process (clk_i) is
+  begin
+    if rising_edge(clk_i) then
+      if (rst_n_i = '0') then
+        sta_p <= '0';
+        sto_p <= '0';
+      else
+        sta_p <= sda_f_edge_p and scl_deglitched;
+        sto_p <= sda_r_edge_p and scl_deglitched;
+      end if;
+    end if;
+  end process p_sta_sto;
+
+  sta_p_o <= sta_p;
+  sto_p_o <= sto_p;
 
   --============================================================================
   -- FSM logic
@@ -277,28 +278,24 @@ begin
   p_fsm: process (clk_i) is
   begin
     if rising_edge(clk_i) then
-      if (rst_n_i = '0') or (rst_fr_watchdog = '1') then
-        state        <= IDLE;
-        watchdog_rst <= '1';
-        bit_cnt      <= (others => '0');
-        rxsr         <= (others => '0');
-        txsr         <= (others => '0');
-        sda_en_o     <= '0';
-        done_p_o     <= '0';
-        op_o         <= '0';
-        stat_o       <= c_i2cs_idle;
-
-      -- I2C start condition
-      elsif (sda_f_edge_p = '1') and (scl_deglitched = '1') then
-        state        <= ADDR;
-        bit_cnt      <= (others => '0');
-        watchdog_rst <= '0';
-
-      -- I2C stop condition
-      elsif (sda_r_edge_p = '1') and (scl_deglitched = '1') then
-        state    <= IDLE;
-        done_p_o <= '1';
-        stat_o   <= c_i2cs_idle;
+      if (rst_n_i = '0') then
+        state         <= IDLE;
+        inhibit       <= '0';
+        bit_cnt       <= (others => '0');
+        rxsr          <= (others => '0');
+        txsr          <= (others => '0');
+        mst_acked     <= '0';
+        sda_en      <= '0';
+        r_done_p_o    <= '0';
+        w_done_p_o    <= '0';
+        addr_good_p_o <= '0';
+        op_o          <= '0';
+
+      -- start and stop conditions take the FSM back to IDLE and reset the
+      -- FSM inhibit signal to read the address
+      elsif (sta_p = '1') or (sto_p = '1') then
+        state   <= IDLE;
+        inhibit <= '0';
 
       -- state machine logic
       else
@@ -307,27 +304,20 @@ begin
           -- IDLE
           ---------------------------------------------------------------------
           -- When idle, outputs and bit counters are cleared, while waiting
-          -- for a start condition.
+          -- for a falling edge on SCL. The falling edge has to be validated
+          -- by the inhibit signal, which states whether it is this or another
+          -- slave being addressed.
           ---------------------------------------------------------------------
           when IDLE =>
-            bit_cnt      <= (others => '0');
-            sda_en_o     <= '0';
-            done_p_o     <= '0';
-            watchdog_rst <= '1';
-            stat_o       <= c_i2cs_idle;
-
---          ---------------------------------------------------------------------
---          -- STA
---          ---------------------------------------------------------------------
---          -- When a start condition is received, the bit counter gets cleared
---          -- to prepare for receiving the address byte. On the falling edge of
---          -- SCL, we go into the address state.
---          ---------------------------------------------------------------------
---          when STA =>
---            bit_cnt <= (others => '0');
---            if (scl_f_edge_p = '1') then
---              state <= ADDR;
---            end if;
+            bit_cnt       <= (others => '0');
+            sda_en      <= '0';
+            mst_acked     <= '0';
+            r_done_p_o    <= '0';
+            w_done_p_o    <= '0';
+            addr_good_p_o <= '0';
+            if (scl_f_edge_p = '1') and (inhibit = '0') then
+              state <= ADDR;
+            end if;
 
           ---------------------------------------------------------------------
           -- ADDR
@@ -342,67 +332,65 @@ begin
             if (scl_r_edge_p = '1') then
               rxsr    <= rxsr(6 downto 0) & sda_deglitched;
               bit_cnt <= bit_cnt + 1;
+            end if;
 
+            if (scl_f_edge_p = '1') then
               -- Shifted in 8 bits, go to ADDR_ACK. Check to see if received
               -- address is ours and set op_o if so.
-              if (bit_cnt = 7) then
-                state <= ADDR_ACK;
-                if (rxsr(6 downto 0) = i2c_addr_i) then
-                  op_o     <= sda_deglitched;
-                  done_p_o <= '1';
-                  stat_o   <= c_i2cs_addr_good;
-                end if;
+              if (bit_cnt = 0) then
+                state <= ADDR_CHECK;
               end if;
             end if;
 
           ---------------------------------------------------------------------
-          -- ADDR_ACK
+          -- ADDR_CHECK
           ---------------------------------------------------------------------
-          -- Here, we check to see if the address is ours and ACK/NACK
-          -- accordingly. The next action is dependent upon the state of the
-          -- R/W bit received via I2C.
+          when ADDR_CHECK =>
+            -- if the address is ours, set the OP output and go to ACK state
+            if (rxsr(7 downto 1) = addr_i) then
+              op_o          <= rxsr(0);
+              addr_good_p_o <= '1';
+              state         <= ADDR_ACK;
+
+            -- if the address is not ours, the FSM should be inhibited so a
+            -- byte sent to another slave doesn't get interpreted as this
+            -- slave's address
+            else
+              inhibit <= '1';
+              state   <= IDLE;
+            end if;
+
+          ---------------------------------------------------------------------
+          -- ADDR_ACK
           ---------------------------------------------------------------------
           when ADDR_ACK =>
-            -- Clear done pulse
-            done_p_o <= '0';
-
-            -- we write the ACK bit, so enable output
-            sda_en_o <= i2c_ack_i;
-
-            -- If the received address is ours, send the ACK set by external
-            -- module and, on the falling edge of SCL, go to appropriate state
-            -- based on R/W bit.
-            if (rxsr(7 downto 1) = i2c_addr_i) then
-              if (scl_f_edge_p = '1') then
-                sda_en_o <= '0';
-                if (rxsr(0) = '0') then
-                  state <= RD;
-                else
-                  state <= WR_LOAD_TXSR;
-                end if;
+            addr_good_p_o <= '0';
+            sda_en      <= ack_i;
+            if (scl_f_edge_p = '1') then
+              if (rxsr(0) = '0') then
+                state <= RD;
+              else
+                state <= WR_LOAD_TXSR;
               end if;
-            -- If received address is not ours, NACK and go back to IDLE
-            else
-              sda_en_o <= '0';
-              state    <= IDLE;
             end if;
 
           ---------------------------------------------------------------------
           -- RD
           ---------------------------------------------------------------------
-          -- Shift in bits sent by the master.
+          -- Shift in bits sent by the master
           ---------------------------------------------------------------------
           when RD =>
-            -- Shifting occurs on falling edge of SCL
-            if (scl_f_edge_p = '1') then
+            sda_en <= '0';
+            if (scl_r_edge_p = '1') then
               rxsr    <= rxsr(6 downto 0) & sda_deglitched;
               bit_cnt <= bit_cnt + 1;
+            end if;
 
+            if (scl_f_edge_p = '1') then
               -- Received 8 bits, go to RD_ACK and signal external module
-              if (bit_cnt = 7) then
-                state    <= RD_ACK;
-                done_p_o <= '1';
-                stat_o   <= c_i2cs_rd_done;
+              if (bit_cnt = 0) then
+                state      <= RD_ACK;
+                r_done_p_o <= '1';
               end if;
             end if;
 
@@ -413,16 +401,15 @@ begin
           ---------------------------------------------------------------------
           when RD_ACK =>
             -- Clear done pulse
-            done_p_o <= '0';
+            r_done_p_o <= '0';
 
             -- we write the ACK bit, so enable output and send the ACK bit
-            sda_en_o <= i2c_ack_i;
+            sda_en <= ack_i;
 
             -- based on the ACK received by external command, we read the next
             -- bit (ACK) or go back to idle state (NACK)
             if (scl_f_edge_p = '1') then
-              sda_en_o <= '0';
-              if (i2c_ack_i = '1') then
+              if (ack_i = '1') then
                 state <= RD;
               else
                 state <= IDLE;
@@ -432,7 +419,7 @@ begin
           ---------------------------------------------------------------------
           -- WR_LOAD_TXSR
           ---------------------------------------------------------------------
-          -- Load TXSR with the input value.
+          -- Load TXSR with the input value
           ---------------------------------------------------------------------
           when WR_LOAD_TXSR =>
             txsr  <= tx_byte_i;
@@ -441,39 +428,48 @@ begin
           ---------------------------------------------------------------------
           -- WR
           ---------------------------------------------------------------------
-          -- Shift out the eight bits of TXSR.
+          -- Shift out the eight bits of TXSR
           ---------------------------------------------------------------------
           when WR =>
-            -- slave writes, so enable output
-            sda_en_o  <= txsr(7);
+            -- slave writes, SDA output enable is the negated value of the bit
+            -- to send (since on I2C, '1' is a release of the bus)
+            sda_en <= not txsr(7);
 
-            -- Shift TXSR on falling edge of SCL
-            if (scl_f_edge_p = '1') then
-              txsr    <= txsr(6 downto 0) & '0';
+            -- increment bit counter on rising edge
+            if (scl_r_edge_p = '1') then
               bit_cnt <= bit_cnt + 1;
+            end if;
+
+            -- Shift TXSR after falling edge of SCL
+            if (scl_f_edge_p = '1') then
+              txsr     <= txsr(6 downto 0) & '0';
 
-              --  Eight bits sent, disable SDA end go to WR_ACK
-              if (bit_cnt = 7) then
-                sda_en_o <= '0';
-                state    <= WR_ACK;
-                done_p_o <= '1';
-                stat_o   <= c_i2cs_wr_done;
+              -- Eight bits sent, disable SDA and go to WR_ACK
+              if (bit_cnt = 0) then
+                state      <= WR_ACK;
+                w_done_p_o <= '1';
               end if;
             end if;
 
           ---------------------------------------------------------------------
           -- WR_ACK
           ---------------------------------------------------------------------
-          -- The master drives the ACK bit here, so on the falling edge of
-          -- SCL, we check the ack bit. A '0' (ACK) means more bits should be sent,
-          -- so we load the next value of the TXSR. A '1' (NACK) means the
-          -- master is done reading and a STO follows, so we go back to IDLE
-          -- state.
+          -- Check the ACK bit received from the master and go back to writing
+          -- another byte if ACKed, or to IDLE if NACKed
           ---------------------------------------------------------------------
           when WR_ACK =>
-            done_p_o <= '0';
-            if (scl_f_edge_p = '1') then
+            sda_en   <= '0';
+            w_done_p_o <= '0';
+            if (scl_r_edge_p = '1') then
               if (sda_deglitched = '0') then
+                mst_acked <= '1';
+              else
+                mst_acked <= '0';
+              end if;
+            end if;
+
+            if (scl_f_edge_p = '1') then
+              if (mst_acked = '1') then
                 state <= WR_LOAD_TXSR;
               else
                 state <= IDLE;
@@ -481,7 +477,7 @@ begin
             end if;
 
           ---------------------------------------------------------------------
-          -- Any other state: go back to idle.
+          -- Any other state: go back to IDLE
           ---------------------------------------------------------------------
           when others =>
             state <= IDLE;
@@ -491,30 +487,6 @@ begin
     end if;
   end process p_fsm;
 
-  --============================================================================
-  -- Watchdog counter process
-  --  Resets the FSM after one second. The watchdog_rst signal is controlled by
-  --  the FSM and resets the watchdog if the I2C master still controls the
-  --  slave, signaled by the SCL line going low. If for one second the master
-  --  does not toggle the SCL line, the FSM gets reset.
-  --============================================================================
-  p_watchdog: process(clk_i)
-  begin
-    if rising_edge(clk_i) then
-      if (rst_n_i = '0') or (watchdog_rst = '1') then
-        watchdog_cnt    <= (others => '0');
-        rst_fr_watchdog <= '0';
-      else
-        watchdog_cnt    <= watchdog_cnt + 1;
-        rst_fr_watchdog <= '0';
-        if (watchdog_cnt = 124999999) then
-          watchdog_cnt    <= (others => '0');
-          rst_fr_watchdog <= '1';
-        end if;
-      end if;
-    end if;
-  end process p_watchdog;
-
 end architecture behav;
 --==============================================================================
 --  architecture end
diff --git a/modules/common/gencores_pkg.vhd b/modules/common/gencores_pkg.vhd
index ad09c551d603abe54bd01de0cdfc839d7c6bd5ff..d0ec6d4ba8cb29e2bb9b8724395d89f9ee7750eb 100644
--- a/modules/common/gencores_pkg.vhd
+++ b/modules/common/gencores_pkg.vhd
@@ -4,9 +4,10 @@
 -------------------------------------------------------------------------------
 -- File       : gencores_pkg.vhd
 -- Author     : Tomasz Wlostowski
+--              Theodor-Adrian Stana
 -- Company    : CERN
 -- Created    : 2009-09-01
--- Last update: 2013-07-02
+-- Last update: 2013-11-20
 -- Platform   : FPGA-generic
 -- Standard   : VHDL '93
 -------------------------------------------------------------------------------
@@ -38,6 +39,7 @@
 -- Date        Version  Author          Description
 -- 2009-09-01  0.9      twlostow        Created
 -- 2011-04-18  1.0      twlostow        Added comments & header
+-- 2013-11-20  1.1      tstana          Added glitch filter and I2C slave
 -------------------------------------------------------------------------------
 
 library ieee;
@@ -48,7 +50,9 @@ use work.genram_pkg.all;
 
 package gencores_pkg is
 
-
+  --============================================================================
+  -- Component instantiations
+  --============================================================================
   component gc_extend_pulse
     generic (
       g_width : natural);
@@ -201,7 +205,7 @@ package gencores_pkg is
       q_valid_o    : out std_logic;
       q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0));
   end component;
- 
+
   -- Power-On reset generation
   component gc_reset is
     generic(
@@ -240,7 +244,7 @@ package gencores_pkg is
       q_o       : out std_logic_vector(g_output_width-1 downto 0);
       q_valid_o : out std_logic;
       q_req_i   : in  std_logic);
-  end component;
+    end component;
   
   component gc_big_adder is
   generic(
@@ -256,8 +260,7 @@ package gencores_pkg is
     x2_o    : out std_logic_vector(g_data_bits-1 downto 0);
     c2_o    : out std_logic);
   end component;
-  
- ------------------------------------------------------------------------------
+  ------------------------------------------------------------------------------
   -- I2C slave
   ------------------------------------------------------------------------------
   constant c_i2cs_idle      : std_logic_vector(1 downto 0) := "00";
@@ -266,53 +269,57 @@ package gencores_pkg is
   constant c_i2cs_wr_done   : std_logic_vector(1 downto 0) := "11";
 
   component gc_i2c_slave is
+    generic
+    (
+      -- Length of glitch filter
+      -- 0 - SCL and SDA lines are passed only through synchronizer
+      -- 1 - one clk_i glitches filtered
+      -- 2 - two clk_i glitches filtered
+      g_gf_len : natural := 0
+    );
     port
     (
       -- Clock, reset ports
-      clk_i      : in  std_logic;
-      rst_n_i    : in  std_logic;
+      clk_i         : in  std_logic;
+      rst_n_i       : in  std_logic;
 
       -- I2C lines
-      scl_i      : in  std_logic;
-      scl_o      : out std_logic;
-      scl_en_o   : out std_logic;
-      sda_i      : in  std_logic;
-      sda_o      : out std_logic;
-      sda_en_o   : out std_logic;
+      scl_i         : in  std_logic;
+      scl_o         : out std_logic;
+      scl_en_o      : out std_logic;
+      sda_i         : in  std_logic;
+      sda_o         : out std_logic;
+      sda_en_o      : out std_logic;
 
       -- Slave address
-      i2c_addr_i : in  std_logic_vector(6 downto 0);
+      addr_i        : in  std_logic_vector(6 downto 0);
 
       -- ACK input, should be set after done_p_o = '1'
       -- (note that the bit is reversed wrt I2C ACK bit)
       -- '1' - ACK
       -- '0' - NACK
-      i2c_ack_i  : in  std_logic;
-
-      -- I2C bus operation, set after address detection
-      -- '0' - write
-      -- '1' - read
-      op_o       : out std_logic;
+      ack_i         : in  std_logic;
 
       -- Byte to send, should be loaded while done_p_o = '1'
-      tx_byte_i  : in  std_logic_vector(7 downto 0);
+      tx_byte_i     : in  std_logic_vector(7 downto 0);
 
       -- Received byte, valid after done_p_o = '1'
-      rx_byte_o  : out std_logic_vector(7 downto 0);
-
-      -- Done pulse signal, valid when
-      -- * received address matches i2c_addr_i, signaling valid op_o;
-      -- * a byte was received, signaling valid rx_byte_o and an ACK/NACK should be
-      -- sent to master;
-      -- * sent a byte, should set tx_byte_i.
-      done_p_o   : out std_logic;
-
-      -- I2C transfer state
-      -- "00" - Idle
-      -- "01" - Got address, matches i2c_addr_i
-      -- "10" - Read done, waiting ACK/NACK
-      -- "11" - Write done, waiting next byte
-      stat_o     : out std_logic_vector(1 downto 0)
+      rx_byte_o     : out std_logic_vector(7 downto 0);
+
+      -- Pulse outputs signaling various I2C actions
+      -- Start and stop conditions
+      sta_p_o       : out std_logic;
+      sto_p_o       : out std_logic;
+      -- Received address corresponds addr_i
+      addr_good_p_o : out std_logic;
+      -- Read and write done
+      r_done_p_o    : out std_logic;
+      w_done_p_o    : out std_logic;
+
+      -- I2C bus operation, set after address detection
+      -- '0' - write
+      -- '1' - read
+      op_o          : out std_logic
     );
   end component gc_i2c_slave;
 
@@ -342,10 +349,32 @@ package gencores_pkg is
     );
   end component gc_glitch_filt;
 
+  ------------------------------------------------------------------------------
+  -- FSM Watchdog Timer
+  ------------------------------------------------------------------------------
+  component gc_fsm_watchdog is
+    generic
+    (
+      -- Maximum value of watchdog timer in clk_i cycles
+      g_wdt_max : positive := 65535
+    );
+    port
+    (
+      -- Clock and active-low reset line
+      clk_i     : in  std_logic;
+      rst_n_i   : in  std_logic;
+
+      -- Active-high watchdog timer reset line, synchronous to clk_i
+      wdt_rst_i : in  std_logic;
+
+      -- Active-high reset output, synchronous to clk_i
+      fsm_rst_o : out std_logic
+    );
+  end component gc_fsm_watchdog;
 
   --============================================================================
-  -- Procedures
-  --============================================================================  procedure f_rr_arbitrate (
+  -- Procedures and functions
+  --============================================================================
   procedure f_rr_arbitrate (
     signal req       : in  std_logic_vector;
     signal pre_grant : in  std_logic_vector;
@@ -359,7 +388,7 @@ package body gencores_pkg is
 -- req = requests (1 = pending request),
 -- pre_grant = previous grant vector (1 cycle delay)
 -- grant = new grant vector
-  
+
   procedure f_rr_arbitrate (
     signal req       : in  std_logic_vector;
     signal pre_grant : in  std_logic_vector;
@@ -370,7 +399,7 @@ package body gencores_pkg is
     variable gnt   : std_logic_vector(req'length - 1 downto 0);
     variable gntM  : std_logic_vector(req'length - 1 downto 0);
     variable zeros : std_logic_vector(req'length - 1 downto 0);
-    
+
   begin
     zeros := (others => '0');
 
@@ -390,7 +419,7 @@ package body gencores_pkg is
     else
       grant <= pre_grant;
     end if;
-    
+
   end f_rr_arbitrate;
 
   function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector is
diff --git a/modules/wishbone/wb_i2c_bridge/wb_i2c_bridge.vhd b/modules/wishbone/wb_i2c_bridge/wb_i2c_bridge.vhd
index f168dfb24baba007ba4b1e043f1b2157e680f9bf..f0d61b26292abc692d8cec344de1a68769676fc4 100644
--- a/modules/wishbone/wb_i2c_bridge/wb_i2c_bridge.vhd
+++ b/modules/wishbone/wb_i2c_bridge/wb_i2c_bridge.vhd
@@ -66,24 +66,30 @@ entity wb_i2c_bridge is
     rst_n_i    : in  std_logic;
 
     -- I2C lines
-    sda_en_o   : out std_logic;
-    sda_i      : in  std_logic;
-    sda_o      : out std_logic;
-    scl_en_o   : out std_logic;
     scl_i      : in  std_logic;
     scl_o      : out std_logic;
+    scl_en_o   : out std_logic;
+    sda_i      : in  std_logic;
+    sda_o      : out std_logic;
+    sda_en_o   : out std_logic;
 
     -- I2C address
     i2c_addr_i : in  std_logic_vector(6 downto 0);
 
-    -- Transfer In Progress (TIP) and Error outputs
-    -- TIP : '1' when the I2C slave detects a matching I2C address, thus a
-    --           transfer is in progress
-    --       '0' when idle
-    -- ERR : '1' when the SysMon attempts to access an invalid WB slave
+    -- Status outputs
+    -- TIP  : Transfer In Progress
+    --        '1' when the I2C slave detects a matching I2C address, thus a
+    --            transfer is in progress
+    --        '0' when idle
+    -- ERR  : Error
+    --       '1' when the SysMon attempts to access an invalid WB slave
     --       '0' when idle
-    tip_o  : out std_logic;
-    err_o  : out std_logic;
+    -- WDTO : Watchdog timeout (single clock cycle pulse)
+    --        '1' -- timeout of watchdog occured
+    --        '0' -- when idle
+    tip_o      : out std_logic;
+    err_p_o    : out std_logic;
+    wdto_p_o   : out std_logic;
 
     -- Wishbone master signals
     wbm_stb_o  : out std_logic;
@@ -120,77 +126,75 @@ architecture behav of wb_i2c_bridge is
   -- Signal declarations
   --============================================================================
   -- Slave component signals
-  signal i2c_ack    : std_logic;
-  signal op         : std_logic;
-  signal start_op   : std_logic;
-  signal tx_byte    : std_logic_vector(7 downto 0);
-  signal rx_byte    : std_logic_vector(7 downto 0);
-  signal done       : std_logic;
-  signal done_d0    : std_logic;
-  signal stat       : std_logic_vector(1 downto 0);
+  signal slv_ack         : std_logic;
+  signal op              : std_logic;
+  signal tx_byte         : std_logic_vector(7 downto 0);
+  signal rx_byte         : std_logic_vector(7 downto 0);
+  signal slv_sta_p       : std_logic;
+  signal slv_sto_p       : std_logic;
+  signal slv_addr_good_p : std_logic;
+  signal slv_r_done_p    : std_logic;
+  signal slv_w_done_p    : std_logic;
 
   -- Wishbone temporary signals
-  signal wb_dat_out : std_logic_vector(31 downto 0);
-  signal wb_dat_in  : std_logic_vector(31 downto 0);
-  signal wb_adr     : std_logic_vector(15 downto 0);
-  signal wb_cyc     : std_logic;
-  signal wb_stb     : std_logic;
-  signal wb_we      : std_logic;
-  signal wb_ack     : std_logic;
-  signal wb_err     : std_logic;
-  signal wb_rty     : std_logic;
+  signal wb_dat_out      : std_logic_vector(31 downto 0);
+  signal wb_dat_in       : std_logic_vector(31 downto 0);
+  signal wb_adr          : std_logic_vector(15 downto 0);
+  signal wb_cyc          : std_logic;
+  signal wb_stb          : std_logic;
+  signal wb_we           : std_logic;
+  signal wb_ack          : std_logic;
+  signal wb_err          : std_logic;
+  signal wb_rty          : std_logic;
 
   -- FSM control signals
-  signal state        : t_state;
-  signal dat_byte_cnt : unsigned(1 downto 0);
-  signal adr_byte_cnt : unsigned(0 downto 0);
+  signal state           : t_state;
+  signal dat_byte_cnt    : unsigned(1 downto 0);
+  signal adr_byte_cnt    : unsigned(0 downto 0);
 
+  -- FSM watchdog signals
+  signal wdt_rst         : std_logic;
+  signal rst_fr_wdt      : std_logic;
+  signal rst_fr_wdt_d0   : std_logic;
+
+--==============================================================================
+--  architecture begin
+--==============================================================================
 begin
 
   --============================================================================
   -- Slave component instantiation and connection
   --============================================================================
   cmp_i2c_slave: gc_i2c_slave
+    generic map
+    (
+      g_gf_len => 8
+    )
     port map
     (
-      clk_i      => clk_i,
-      rst_n_i    => rst_n_i,
-
-      -- I2C lines
-      scl_i      => scl_i,
-      scl_o      => scl_o,
-      scl_en_o   => scl_en_o,
-      sda_i      => sda_i,
-      sda_o      => sda_o,
-      sda_en_o   => sda_en_o,
-
-      -- Slave address
-      i2c_addr_i => i2c_addr_i,
-
-      -- ACK input, should be set after done_p_o = '1'
-      -- '0' - ACK
-      -- '1' - NACK
-      i2c_ack_i  => i2c_ack,
-
-      -- I2C bus operation, set after address detection
-      -- '0' - write
-      -- '1' - read
-      op_o       => op,
-
-      -- Byte to send, should be loaded while done_p_o = '1'
-      tx_byte_i  => tx_byte,
-
-      -- Received byte, valid after done_p_o = '1'
-      rx_byte_o  => rx_byte,
-
-      -- Done signal, valid when
-      -- * received address matches i2c_addr_i, signaling valid op_o;
-      -- * a byte was received, signaling valid rx_byte_o and an ACK/NACK should be
-      -- sent to master;
-      -- * sent a byte, should set tx_byte_i.
-      done_p_o   => done,
-
-      stat_o     => stat
+      clk_i         => clk_i,
+      rst_n_i       => rst_n_i,
+
+      scl_i         => scl_i,
+      scl_o         => scl_o,
+      scl_en_o      => scl_en_o,
+      sda_i         => sda_i,
+      sda_o         => sda_o,
+      sda_en_o      => sda_en_o,
+
+      addr_i        => i2c_addr_i,
+
+      ack_i         => slv_ack,
+
+      tx_byte_i     => tx_byte,
+      rx_byte_o     => rx_byte,
+
+      sta_p_o       => open,
+      sto_p_o       => slv_sto_p,
+      addr_good_p_o => slv_addr_good_p,
+      r_done_p_o    => slv_r_done_p,
+      w_done_p_o    => slv_w_done_p,
+      op_o          => op
     );
 
   --============================================================================
@@ -218,7 +222,7 @@ begin
   p_fsm: process (clk_i) is
   begin
     if rising_edge(clk_i) then
-      if (rst_n_i = '0') then
+      if (rst_n_i = '0') or (rst_fr_wdt = '1') then
         state        <= IDLE;
         wb_adr       <= (others => '0');
         wb_dat_out   <= (others => '0');
@@ -226,13 +230,16 @@ begin
         wb_cyc       <= '0';
         wb_stb       <= '0';
         wb_we        <= '0';
-        start_op     <= '0';
-        i2c_ack      <= '0';
+        slv_ack      <= '0';
         tip_o        <= '0';
-        err_o        <= '0';
+        err_p_o      <= '0';
+        wdt_rst      <= '1';
         adr_byte_cnt <= (others => '0');
         dat_byte_cnt <= (others => '0');
 
+      elsif (slv_sto_p = '1') then
+        state <= IDLE;
+
       else
         case state is
           ---------------------------------------------------------------------
@@ -245,15 +252,17 @@ begin
           -- address, start_op will be '0' (write).
           ---------------------------------------------------------------------
           when IDLE =>
-            err_o   <= '0';
-            tip_o   <= '0';
-            i2c_ack <= '0';
+            err_p_o      <= '0';
+            tip_o        <= '0';
+            slv_ack      <= '0';
+            adr_byte_cnt <= (others => '0');
             dat_byte_cnt <= (others => '0');
-            if (done = '1') and (stat = c_i2cs_addr_good) then
+            wdt_rst      <= '1';
+            if (slv_addr_good_p = '1') then
               tip_o    <= '1';
-              i2c_ack  <= '1';
+              slv_ack  <= '1';
+              wdt_rst  <= '0';
               state    <= SYSMON_WB_ADR;
-              start_op <= op;
             end if;
 
           ---------------------------------------------------------------------
@@ -263,17 +272,12 @@ begin
           -- them. The second byte's ACK is also controlled by the next state.
           ---------------------------------------------------------------------
           when SYSMON_WB_ADR =>
-            if (done = '1') then
-              if (stat = c_i2cs_rd_done) then
-                wb_adr       <= wb_adr(7 downto 0) & rx_byte;
-                i2c_ack      <= '1';
-                adr_byte_cnt <= adr_byte_cnt + 1;
-                if (adr_byte_cnt = 1) then
-                  state <= SIM_WB_TRANSF;
-                end if;
-              else
-                i2c_ack <= '0';
-                state   <= IDLE;
+            if (slv_r_done_p = '1') then
+              wb_adr       <= wb_adr(7 downto 0) & rx_byte;
+              slv_ack      <= '1';
+              adr_byte_cnt <= adr_byte_cnt + 1;
+              if (adr_byte_cnt = 1) then
+                state <= SIM_WB_TRANSF;
               end if;
             end if;
 
@@ -288,13 +292,13 @@ begin
             wb_cyc <= '1';
             wb_stb <= '1';
             if (wb_ack = '1') then
-              i2c_ack <= '1';
+              slv_ack <= '1';
               wb_cyc  <= '0';
               wb_stb  <= '0';
               state   <= OPER;
             elsif (wb_err = '1') then
-              err_o   <= '1';
-              i2c_ack <= '0';
+              err_p_o <= '1';
+              slv_ack <= '0';
               wb_cyc  <= '0';
               wb_stb  <= '0';
               state   <= IDLE;
@@ -317,19 +321,14 @@ begin
           -- output are cleared to avoid conflicts with future transfers.
           ---------------------------------------------------------------------
           when OPER =>
-            if (done = '1') then
-              if (stat = c_i2cs_rd_done) then
-                wb_dat_out   <= rx_byte & wb_dat_out(31 downto 8);
-                dat_byte_cnt <= dat_byte_cnt + 1;
-                i2c_ack      <= '1';
-                state        <= SYSMON_WR;
-              elsif (stat = c_i2cs_addr_good) and (op /= start_op) then
-                i2c_ack <= '1';
-                state   <= SYSMON_RD_WB;
-              else
-                i2c_ack <= '0';
-                state   <= IDLE;
-              end if;
+            if (slv_r_done_p = '1') then
+              wb_dat_out   <= rx_byte & wb_dat_out(31 downto 8);
+              dat_byte_cnt <= dat_byte_cnt + 1;
+              slv_ack      <= '1';
+              state        <= SYSMON_WR;
+            elsif (slv_addr_good_p = '1') and (op = '1') then
+              slv_ack <= '1';
+              state   <= SYSMON_RD_WB;
             end if;
 
           ---------------------------------------------------------------------
@@ -340,18 +339,15 @@ begin
           -- write transfer is initiated in the next state.
           ---------------------------------------------------------------------
           when SYSMON_WR =>
-            if (done = '1') then
-              if (stat = c_i2cs_rd_done) then
-                wb_dat_out   <= rx_byte & wb_dat_out(31 downto 8);
-                dat_byte_cnt <= dat_byte_cnt + 1;
-                i2c_ack      <= '1';
-                if (dat_byte_cnt = 3) then
-                  state <= SYSMON_WR_WB;
-                end if;
-              else
-                i2c_ack <= '0';
-                state   <= IDLE;
+            if (slv_r_done_p = '1') then
+              wb_dat_out   <= rx_byte & wb_dat_out(31 downto 8);
+              dat_byte_cnt <= dat_byte_cnt + 1;
+              slv_ack      <= '1';
+              if (dat_byte_cnt = 3) then
+                state <= SYSMON_WR_WB;
               end if;
+--            elsif (slv_sto_p = '1') then
+--              state <= IDLE;
             end if;
 
           ---------------------------------------------------------------------
@@ -370,7 +366,7 @@ begin
               wb_we  <= '0';
               state  <= SYSMON_WR; --IDLE;
             elsif (wb_err = '1') then
-              err_o   <= '1';
+              err_p_o <= '1';
               state   <= IDLE;
             end if;
 
@@ -391,10 +387,10 @@ begin
               wb_stb    <= '0';
               state     <= SYSMON_RD;
             elsif (wb_err = '1') then
-              err_o  <= '1';
-              wb_cyc <= '0';
-              wb_stb <= '0';
-              state  <= IDLE;
+              err_p_o <= '1';
+              wb_cyc  <= '0';
+              wb_stb  <= '0';
+              state   <= IDLE;
             end if;
 
           ---------------------------------------------------------------------
@@ -403,18 +399,15 @@ begin
           -- Shift out the bytes over I2C and go back to IDLE state.
           ---------------------------------------------------------------------
           when SYSMON_RD =>
-            if (done = '1') then
-              if (stat = c_i2cs_wr_done) then
-                wb_dat_in    <= x"00" & wb_dat_in(31 downto 8);
-                dat_byte_cnt <= dat_byte_cnt + 1;
-                i2c_ack      <= '1';
-                if (dat_byte_cnt = 3) then
-                  state <= IDLE;
-                end if;
-              else
-                i2c_ack <= '0';
-                state   <= IDLE;
+            if (slv_w_done_p = '1') then
+              wb_dat_in    <= x"00" & wb_dat_in(31 downto 8);
+              dat_byte_cnt <= dat_byte_cnt + 1;
+              slv_ack      <= '1';
+              if (dat_byte_cnt = 3) then
+                state <= IDLE;
               end if;
+--            elsif (slv_sto_p = '1') then
+--              state <= IDLE;
             end if;
 
           ---------------------------------------------------------------------
@@ -428,4 +421,48 @@ begin
     end if;
   end process p_fsm;
 
+  --============================================================================
+  -- FSM watchdog timer
+  --============================================================================
+  -- * in the case of writemregs command, a maximum of 35 bytes can be written
+  --     - 1 I2C address byte
+  --     - 2 register (Wishbone) address bytes
+  --     - 8*4 Wishbone register values
+  -- * we will therefore set the watchdog max. value to allow for 36 bytes to
+  -- be sent, considering a maximum clk_i frequency of 20 MHz (period = 50 ns)
+  -- and an SCL frequency of 100 kHz
+  -- * 100 us / 50 ns = 2000 clock cycles to send one byte
+  -- * 2000 * 36 bytes = 72000 clock cycles to send 36 bytes
+  -- * g_wdt_max = 72000
+  cmp_watchdog : gc_fsm_watchdog
+    generic map
+    (
+      g_wdt_max => 72000
+    )
+    port map
+    (
+      clk_i     => clk_i,
+      rst_n_i   => rst_n_i,
+      wdt_rst_i => wdt_rst,
+      fsm_rst_o => rst_fr_wdt
+    );
+
+  -- Process to set the timeout status pulse
+  p_wdto_outp : process (clk_i)
+  begin
+    if rising_edge(clk_i) then
+      if (rst_n_i = '0') then
+        rst_fr_wdt_d0 <= '0';
+        wdto_p_o      <= '0';
+      else
+        rst_fr_wdt_d0 <= rst_fr_wdt;
+        wdto_p_o      <= rst_fr_wdt and (not rst_fr_wdt_d0);
+      end if;
+    end if;
+  end process p_wdto_outp;
+
 end behav;
+--==============================================================================
+--  architecture end
+--==============================================================================
+
diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd
index 42228b582e2d2a5320eb2530142bed9fc2577024..e919fce1075c66262cbb3dfd756ac8ad86b2e319 100644
--- a/modules/wishbone/wishbone_pkg.vhd
+++ b/modules/wishbone/wishbone_pkg.vhd
@@ -910,24 +910,30 @@ package wishbone_pkg is
       rst_n_i    : in  std_logic;
 
       -- I2C lines
-      sda_en_o   : out std_logic;
-      sda_i      : in  std_logic;
-      sda_o      : out std_logic;
-      scl_en_o   : out std_logic;
       scl_i      : in  std_logic;
       scl_o      : out std_logic;
+      scl_en_o   : out std_logic;
+      sda_i      : in  std_logic;
+      sda_o      : out std_logic;
+      sda_en_o   : out std_logic;
 
       -- I2C address
       i2c_addr_i : in  std_logic_vector(6 downto 0);
 
-      -- Transfer In Progress (TIP) and Error outputs
-      -- TIP : '1' when the I2C slave detects a matching I2C address, thus a
-      --           transfer is in progress
-      --       '0' when idle
-      -- ERR : '1' when the SysMon attempts to access an invalid WB slave
+      -- Status outputs
+      -- TIP  : Transfer In Progress
+      --        '1' when the I2C slave detects a matching I2C address, thus a
+      --            transfer is in progress
+      --        '0' when idle
+      -- ERR  : Error
+      --       '1' when the SysMon attempts to access an invalid WB slave
       --       '0' when idle
-      tip_o  : out std_logic;
-      err_o  : out std_logic;
+      -- WDTO : Watchdog timeout (single clock cycle pulse)
+      --        '1' -- timeout of watchdog occured
+      --        '0' -- when idle
+      tip_o      : out std_logic;
+      err_p_o    : out std_logic;
+      wdto_p_o   : out std_logic;
 
       -- Wishbone master signals
       wbm_stb_o  : out std_logic;
diff --git a/sim/wb_i2c_bridge/i2c_bus_model.vhd b/sim/wb_i2c_bridge/i2c_bus_model.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..0acc69aa3223bc6a86e257c0c3182dfce6fc717a
--- /dev/null
+++ b/sim/wb_i2c_bridge/i2c_bus_model.vhd
@@ -0,0 +1,89 @@
+--==============================================================================
+-- CERN (BE-CO-HT)
+-- I2C bus model
+--==============================================================================
+--
+-- author: Theodor Stana (t.stana@cern.ch)
+--
+-- date of creation: 2013-11-27
+--
+-- version: 1.0
+--
+-- description:
+--    A very simple I2C bus model for use in simulation, implementing the
+--    wired-AND on the I2C protocol.
+--
+--    Masters and slaves should implement the buffers internally and connect the
+--    SCL and SDA lines to the input ports of this model, as below:
+--        - masters should connect to mscl_i and msda_i
+--        - slaves should connect to sscl_i and ssda_i
+--
+-- dependencies:
+--
+-- references:
+--
+--==============================================================================
+-- GNU LESSER GENERAL PUBLIC LICENSE
+--==============================================================================
+-- This source file is free software; you can redistribute it and/or modify it
+-- under the terms of the GNU Lesser General Public License as published by the
+-- Free Software Foundation; either version 2.1 of the License, or (at your
+-- option) any later version. This source is distributed in the hope that it
+-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+-- See the GNU Lesser General Public License for more details. You should have
+-- received a copy of the GNU Lesser General Public License along with this
+-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
+--==============================================================================
+-- last changes:
+--    2013-11-27   Theodor Stana     File created
+--==============================================================================
+-- TODO: -
+--==============================================================================
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+entity i2c_bus_model is
+  generic
+  (
+    g_nr_masters : positive := 1;
+    g_nr_slaves  : positive := 1
+  );
+  port
+  (
+    -- Input ports from master lines
+    mscl_i : in  std_logic_vector(g_nr_masters-1 downto 0);
+    msda_i : in  std_logic_vector(g_nr_masters-1 downto 0);
+
+    -- Input ports from slave lines
+    sscl_i : in  std_logic_vector(g_nr_slaves-1 downto 0);
+    ssda_i : in  std_logic_vector(g_nr_slaves-1 downto 0);
+
+    -- SCL and SDA line outputs
+    scl_o  : out std_logic;
+    sda_o  : out std_logic
+  );
+end entity i2c_bus_model;
+
+
+architecture behav of i2c_bus_model is
+
+--==============================================================================
+--  architecture begin
+--==============================================================================
+begin
+
+  scl_o <= '1' when (mscl_i = (mscl_i'range => '1')) and
+                    (sscl_i = (sscl_i'range => '1')) else
+           '0';
+  sda_o <= '1' when (msda_i = (msda_i'range => '1')) and
+                    (ssda_i = (ssda_i'range => '1')) else
+           '0';
+
+end architecture behav;
+--==============================================================================
+--  architecture end
+--==============================================================================
diff --git a/sim/wb_i2c_bridge/i2c_master_bit_ctrl.vhd b/sim/wb_i2c_bridge/i2c_master_bit_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a095fde0e882d3b0d6322145e9396759b223b9c2
--- /dev/null
+++ b/sim/wb_i2c_bridge/i2c_master_bit_ctrl.vhd
@@ -0,0 +1,576 @@
+---------------------------------------------------------------------
+----                                                             ----
+----  WISHBONE revB2 I2C Master Core; bit-controller             ----
+----                                                             ----
+----                                                             ----
+----  Author: Richard Herveille                                  ----
+----          richard@asics.ws                                   ----
+----          www.asics.ws                                       ----
+----                                                             ----
+----  Downloaded from: http://www.opencores.org/projects/i2c/    ----
+----                                                             ----
+---------------------------------------------------------------------
+----                                                             ----
+---- Copyright (C) 2000 Richard Herveille                        ----
+----                    richard@asics.ws                         ----
+----                                                             ----
+---- This source file may be used and distributed without        ----
+---- restriction provided that this copyright statement is not   ----
+---- removed from the file and that any derivative work contains ----
+---- the original copyright notice and the associated disclaimer.----
+----                                                             ----
+----     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ----
+---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ----
+---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ----
+---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ----
+---- 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.                                 ----
+----                                                             ----
+---------------------------------------------------------------------
+
+--  CVS Log
+--
+--  $Id: i2c_master_bit_ctrl.vhd,v 1.17 2009-02-04 20:17:34 rherveille Exp $
+--
+--  $Date: 2009-02-04 20:17:34 $
+--  $Revision: 1.17 $
+--  $Author: rherveille $
+--  $Locker:  $
+--  $State: Exp $
+--
+-- Change History:
+--               $Log: not supported by cvs2svn $
+--               Revision 1.16  2009/01/20 20:40:36  rherveille
+--               Fixed type iscl_oen instead of scl_oen
+--
+--               Revision 1.15  2009/01/20 10:34:51  rherveille
+--               Added SCL clock synchronization logic
+--               Fixed slave_wait signal generation
+--
+--               Revision 1.14  2006/10/11 12:10:13  rherveille
+--               Added missing semicolons ';' on endif
+--
+--               Revision 1.13  2006/10/06 10:48:24  rherveille
+--               fixed short scl high pulse after clock stretch
+--
+--               Revision 1.12  2004/05/07 11:53:31  rherveille
+--               Fixed previous fix :) Made a variable vs signal mistake.
+--
+--               Revision 1.11  2004/05/07 11:04:00  rherveille
+--               Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit.
+--
+--               Revision 1.10  2004/02/27 07:49:43  rherveille
+--               Fixed a bug in the arbitration-lost signal generation. VHDL version only.
+--
+--               Revision 1.9  2003/08/12 14:48:37  rherveille
+--               Forgot an 'end if' :-/
+--
+--               Revision 1.8  2003/08/09 07:01:13  rherveille
+--               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
+--               Fixed a potential bug in the byte controller's host-acknowledge generation.
+--
+--               Revision 1.7  2003/02/05 00:06:02  rherveille
+--               Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles.
+--
+--               Revision 1.6  2003/02/01 02:03:06  rherveille
+--               Fixed a few 'arbitration lost' bugs. VHDL version only.
+--
+--               Revision 1.5  2002/12/26 16:05:47  rherveille
+--               Core is now a Multimaster I2C controller.
+--
+--               Revision 1.4  2002/11/30 22:24:37  rherveille
+--               Cleaned up code
+--
+--               Revision 1.3  2002/10/30 18:09:53  rherveille
+--               Fixed some reported minor start/stop generation timing issuess.
+--
+--               Revision 1.2  2002/06/15 07:37:04  rherveille
+--               Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment.
+--
+--               Revision 1.1  2001/11/05 12:02:33  rherveille
+--               Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version.
+--               Code updated, is now up-to-date to doc. rev.0.4.
+--               Added headers.
+--
+
+
+--
+-------------------------------------
+-- Bit controller section
+------------------------------------
+--
+-- Translate simple commands into SCL/SDA transitions
+-- Each command has 5 states, A/B/C/D/idle
+--
+-- start:    SCL  ~~~~~~~~~~~~~~\____
+--           SDA  XX/~~~~~~~\______
+--                x | A | B | C | D | i
+--
+-- repstart  SCL  ______/~~~~~~~\___
+--           SDA  __/~~~~~~~\______
+--                x | A | B | C | D | i
+--
+-- stop      SCL  _______/~~~~~~~~~~~
+--           SDA  ==\___________/~~~~~
+--                x | A | B | C | D | i
+--
+--- write    SCL  ______/~~~~~~~\____
+--           SDA  XXX===============XX
+--                x | A | B | C | D | i
+--
+--- read     SCL  ______/~~~~~~~\____
+--           SDA  XXXXXXX=XXXXXXXXXXX
+--                x | A | B | C | D | i
+--
+
+-- Timing:      Normal mode     Fast mode
+-----------------------------------------------------------------
+-- Fscl         100KHz          400KHz
+-- Th_scl       4.0us           0.6us   High period of SCL
+-- Tl_scl       4.7us           1.3us   Low period of SCL
+-- Tsu:sta      4.7us           0.6us   setup time for a repeated start condition
+-- Tsu:sto      4.0us           0.6us   setup time for a stop conditon
+-- Tbuf         4.7us           1.3us   Bus free time between a stop and start condition
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity i2c_master_bit_ctrl is
+    port (
+          clk    : in std_logic;
+          rst    : in std_logic;
+          nReset : in std_logic;
+          ena    : in std_logic;                     -- core enable signal
+
+          clk_cnt : in unsigned(15 downto 0);        -- clock prescale value
+
+          cmd     : in std_logic_vector(3 downto 0);
+          cmd_ack : out std_logic;                   -- command completed
+          busy    : out std_logic;                   -- i2c bus busy
+          al      : out std_logic;                   -- arbitration lost
+
+          din  : in std_logic;
+          dout : out std_logic;
+
+          -- i2c lines
+          scl_i   : in std_logic;                    -- i2c clock line input
+          scl_o   : out std_logic;                   -- i2c clock line output
+          scl_oen : out std_logic;                   -- i2c clock line output enable, active low
+          sda_i   : in std_logic;                    -- i2c data line input
+          sda_o   : out std_logic;                   -- i2c data line output
+          sda_oen : out std_logic                    -- i2c data line output enable, active low
+    );
+end entity i2c_master_bit_ctrl;
+
+architecture structural of i2c_master_bit_ctrl is
+    constant I2C_CMD_NOP    : std_logic_vector(3 downto 0) := "0000";
+    constant I2C_CMD_START  : std_logic_vector(3 downto 0) := "0001";
+    constant I2C_CMD_STOP   : std_logic_vector(3 downto 0) := "0010";
+    constant I2C_CMD_READ   : std_logic_vector(3 downto 0) := "0100";
+    constant I2C_CMD_WRITE  : std_logic_vector(3 downto 0) := "1000";
+
+    type states is (idle, start_a, start_b, start_c, start_d, start_e,
+                    stop_a, stop_b, stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);
+    signal c_state : states;
+
+    signal iscl_oen, isda_oen   : std_logic;             -- internal I2C lines
+    signal sda_chk              : std_logic;             -- check SDA status (multi-master arbitration)
+    signal dscl_oen             : std_logic;             -- delayed scl_oen signals
+    signal sSCL, sSDA           : std_logic;             -- synchronized SCL and SDA inputs
+    signal dSCL, dSDA           : std_logic;             -- delayed versions ofsSCL and sSDA
+    signal clk_en               : std_logic;             -- statemachine clock enable
+    signal scl_sync, slave_wait : std_logic;             -- clock generation signals
+    signal ial                  : std_logic;             -- internal arbitration lost signal
+    signal cnt                  : unsigned(15 downto 0); -- clock divider counter (synthesis)
+
+begin
+    -- whenever the slave is not ready it can delay the cycle by pulling SCL low
+    -- delay scl_oen
+    process (clk, nReset)
+    begin
+        if (nReset = '0') then
+            dscl_oen <= '0';
+        elsif (clk'event and clk = '1') then
+            dscl_oen <= iscl_oen;
+        end if;
+    end process;
+
+    -- slave_wait is asserted when master wants to drive SCL high, but the slave pulls it low
+    -- slave_wait remains asserted until the slave releases SCL
+    process (clk, nReset)
+    begin
+        if (nReset = '0') then
+            slave_wait <= '0';
+        elsif (clk'event and clk = '1') then
+               slave_wait <= (iscl_oen and not dscl_oen and not sSCL) or (slave_wait and not sSCL);
+        end if;
+    end process;
+
+    -- master drives SCL high, but another master pulls it low
+    -- master start counting down its low cycle now (clock synchronization)
+    scl_sync <= dSCL and not sSCL and iscl_oen;
+
+    -- generate clk enable signal
+    gen_clken: process(clk, nReset)
+    begin
+        if (nReset = '0') then
+            cnt    <= (others => '0');
+            clk_en <= '1';
+        elsif (clk'event and clk = '1') then
+               if ((rst = '1') or (cnt = 0) or (ena = '0') or (scl_sync = '1')) then
+                   cnt    <= clk_cnt;
+                   clk_en <= '1';
+               elsif (slave_wait = '1') then
+                   cnt    <= cnt;
+                   clk_en <= '0';
+               else
+                   cnt    <= cnt -1;
+                   clk_en <= '0';
+               end if;
+        end if;
+    end process gen_clken;
+
+
+    -- generate bus status controller
+    bus_status_ctrl: block
+      signal cSCL, cSDA    : std_logic_vector( 1 downto 0); -- capture SDA and SCL
+      signal fSCL, fSDA    : std_logic_vector( 2 downto 0); -- filter inputs for SCL and SDA
+      signal filter_cnt    : unsigned(13 downto 0);         -- clock divider for filter
+      signal sta_condition : std_logic;                     -- start detected
+      signal sto_condition : std_logic;                     -- stop detected
+      signal cmd_stop      : std_logic;                     -- STOP command
+      signal ibusy         : std_logic;                     -- internal busy signal
+    begin
+        -- capture SCL and SDA
+        capture_scl_sda: process(clk, nReset)
+        begin
+            if (nReset = '0') then
+                cSCL <= "00";
+                cSDA <= "00";
+            elsif (clk'event and clk = '1') then
+                if (rst = '1') then
+                    cSCL <= "00";
+                    cSDA <= "00";
+                else
+                    cSCL <= (cSCL(0) & scl_i);
+                    cSDA <= (cSDA(0) & sda_i);
+                end if;
+            end if;
+        end process capture_scl_sda;
+
+        -- filter SCL and SDA; (attempt to) remove glitches
+        filter_divider: process(clk, nReset)
+        begin
+            if (nReset = '0') then
+                filter_cnt <= (others => '0');
+            elsif (clk'event and clk = '1') then
+                if ( (rst = '1') or (ena = '0') ) then
+                    filter_cnt <= (others => '0');
+                elsif (filter_cnt = 0) then
+                    filter_cnt <= clk_cnt(15 downto 2);
+                else
+                    filter_cnt <= filter_cnt -1;
+                end if;
+            end if;
+        end process filter_divider;
+
+        filter_scl_sda: process(clk, nReset)
+        begin
+            if (nReset = '0') then
+                fSCL <= (others => '1');
+                fSDA <= (others => '1');
+            elsif (clk'event and clk = '1') then
+                if (rst = '1') then
+                    fSCL <= (others => '1');
+                    fSDA <= (others => '1');
+                elsif (filter_cnt = 0) then
+                    fSCL <= (fSCL(1 downto 0) & cSCL(1));
+                    fSDA <= (fSDA(1 downto 0) & cSDA(1));
+                end if;
+            end if;
+        end process filter_scl_sda;
+
+       -- generate filtered SCL and SDA signals
+       scl_sda: process(clk, nReset)
+       begin
+           if (nReset = '0') then
+               sSCL <= '1';
+               sSDA <= '1';
+
+               dSCL <= '1';
+               dSDA <= '1';
+           elsif (clk'event and clk = '1') then
+               if (rst = '1') then
+                   sSCL <= '1';
+                   sSDA <= '1';
+
+                   dSCL <= '1';
+                   dSDA <= '1';
+               else
+                  sSCL <= (fSCL(2) and fSCL(1)) or
+                          (fSCL(2) and fSCL(0)) or
+                          (fSCL(1) and fSCL(0));
+                  sSDA <= (fSDA(2) and fSDA(1)) or
+                          (fSDA(2) and fSDA(0)) or
+                          (fSDA(1) and fSDA(0));
+
+                  dSCL <= sSCL;
+                  dSDA <= sSDA;
+               end if;
+           end if;
+       end process scl_sda;
+
+
+       -- detect start condition => detect falling edge on SDA while SCL is high
+       -- detect stop condition  => detect rising edge on SDA while SCL is high
+       detect_sta_sto: process(clk, nReset)
+       begin
+           if (nReset = '0') then
+               sta_condition <= '0';
+               sto_condition <= '0';
+           elsif (clk'event and clk = '1') then
+               if (rst = '1') then
+                   sta_condition <= '0';
+                   sto_condition <= '0';
+               else
+                   sta_condition <= (not sSDA and dSDA) and sSCL;
+                   sto_condition <= (sSDA and not dSDA) and sSCL;
+               end if;
+           end if;
+       end process detect_sta_sto;
+
+
+       -- generate i2c-bus busy signal
+       gen_busy: process(clk, nReset)
+       begin
+           if (nReset = '0') then
+               ibusy <= '0';
+           elsif (clk'event and clk = '1') then
+               if (rst = '1') then
+                   ibusy <= '0';
+               else
+                   ibusy <= (sta_condition or ibusy) and not sto_condition;
+               end if;
+           end if;
+       end process gen_busy;
+       busy <= ibusy;
+
+
+       -- generate arbitration lost signal
+       -- aribitration lost when:
+       -- 1) master drives SDA high, but the i2c bus is low
+       -- 2) stop detected while not requested (detect during 'idle' state)
+       gen_al: process(clk, nReset)
+       begin
+           if (nReset = '0') then
+               cmd_stop  <= '0';
+               ial       <= '0';
+           elsif (clk'event and clk = '1') then
+               if (rst = '1') then
+                   cmd_stop  <= '0';
+                   ial       <= '0';
+               else
+                   if (clk_en = '1') then
+                       if (cmd = I2C_CMD_STOP) then
+                           cmd_stop <= '1';
+                       else
+                           cmd_stop <= '0';
+                       end if;
+                   end if;
+
+                   if (c_state = idle) then
+                       ial <= (sda_chk and not sSDA and isda_oen) or (sto_condition and not cmd_stop);
+                   else
+                       ial <= (sda_chk and not sSDA and isda_oen);
+                   end if;
+               end if;
+          end if;
+       end process gen_al;
+       al <= ial;
+
+
+       -- generate dout signal, store dout on rising edge of SCL
+       gen_dout: process(clk, nReset)
+       begin
+           if (nReset = '0') then
+               dout <= '0';
+           elsif (clk'event and clk = '1') then
+               if (sSCL = '1' and dSCL = '0') then
+                   dout <= sSDA;
+               end if;
+           end if;
+       end process gen_dout;
+    end block bus_status_ctrl;
+
+
+    -- generate statemachine
+    nxt_state_decoder : process (clk, nReset)
+    begin
+        if (nReset = '0') then
+            c_state  <= idle;
+            cmd_ack  <= '0';
+            iscl_oen <= '1';
+            isda_oen <= '1';
+            sda_chk  <= '0';
+        elsif (clk'event and clk = '1') then
+               if (rst = '1' or ial = '1') then
+                   c_state  <= idle;
+                   cmd_ack  <= '0';
+                   iscl_oen <= '1';
+                   isda_oen <= '1';
+                   sda_chk  <= '0';
+               else
+                   cmd_ack <= '0'; -- default no acknowledge
+
+                   if (clk_en = '1') then
+                       case (c_state) is
+                             -- idle
+                             when idle =>
+                                 case cmd is
+                                     when I2C_CMD_START => c_state <= start_a;
+                                     when I2C_CMD_STOP  => c_state <= stop_a;
+                                     when I2C_CMD_WRITE => c_state <= wr_a;
+                                     when I2C_CMD_READ  => c_state <= rd_a;
+                                     when others        => c_state <= idle; -- NOP command
+                                 end case;
+
+                                 iscl_oen <= iscl_oen; -- keep SCL in same state
+                                 isda_oen <= isda_oen; -- keep SDA in same state
+                                 sda_chk  <= '0';      -- don't check SDA
+
+                             -- start
+                             when start_a =>
+                                 c_state  <= start_b;
+                                 iscl_oen <= iscl_oen; -- keep SCL in same state (for repeated start)
+                                 isda_oen <= '1';      -- set SDA high
+                                 sda_chk  <= '0';      -- don't check SDA
+
+                             when start_b =>
+                                 c_state  <= start_c;
+                                 iscl_oen <= '1'; -- set SCL high
+                                 isda_oen <= '1'; -- keep SDA high
+                                 sda_chk  <= '0'; -- don't check SDA
+
+                             when start_c =>
+                                 c_state  <= start_d;
+                                 iscl_oen <= '1'; -- keep SCL high
+                                 isda_oen <= '0'; -- set SDA low
+                                 sda_chk  <= '0'; -- don't check SDA
+
+                             when start_d =>
+                                 c_state  <= start_e;
+                                 iscl_oen <= '1'; -- keep SCL high
+                                 isda_oen <= '0'; -- keep SDA low
+                                 sda_chk  <= '0'; -- don't check SDA
+
+                             when start_e =>
+                                 c_state  <= idle;
+                                 cmd_ack  <= '1'; -- command completed
+                                 iscl_oen <= '0'; -- set SCL low
+                                 isda_oen <= '0'; -- keep SDA low
+                                 sda_chk  <= '0'; -- don't check SDA
+
+                             -- stop
+                            when stop_a =>
+                                c_state  <= stop_b;
+                                iscl_oen <= '0'; -- keep SCL low
+                                isda_oen <= '0'; -- set SDA low
+                                sda_chk  <= '0'; -- don't check SDA
+
+                            when stop_b =>
+                                c_state  <= stop_c;
+                                iscl_oen <= '1'; -- set SCL high
+                                isda_oen <= '0'; -- keep SDA low
+                                sda_chk  <= '0'; -- don't check SDA
+
+                            when stop_c =>
+                                c_state  <= stop_d;
+                                iscl_oen <= '1'; -- keep SCL high
+                                isda_oen <= '0'; -- keep SDA low
+                                sda_chk  <= '0'; -- don't check SDA
+
+                            when stop_d =>
+                                c_state  <= idle;
+                                cmd_ack  <= '1'; -- command completed
+                                iscl_oen <= '1'; -- keep SCL high
+                                isda_oen <= '1'; -- set SDA high
+                                sda_chk  <= '0'; -- don't check SDA
+
+                            -- read
+                            when rd_a =>
+                                c_state  <= rd_b;
+                                iscl_oen <= '0'; -- keep SCL low
+                                isda_oen <= '1'; -- tri-state SDA
+                                sda_chk  <= '0'; -- don't check SDA
+
+                            when rd_b =>
+                                c_state  <= rd_c;
+                                iscl_oen <= '1'; -- set SCL high
+                                isda_oen <= '1'; -- tri-state SDA
+                                sda_chk  <= '0'; -- don't check SDA
+
+                            when rd_c =>
+                                c_state  <= rd_d;
+                                iscl_oen <= '1'; -- keep SCL high
+                                isda_oen <= '1'; -- tri-state SDA
+                                sda_chk  <= '0'; -- don't check SDA
+
+                            when rd_d =>
+                                c_state  <= idle;
+                                cmd_ack  <= '1'; -- command completed
+                                iscl_oen <= '0'; -- set SCL low
+                                isda_oen <= '1'; -- tri-state SDA
+                                sda_chk  <= '0'; -- don't check SDA
+
+                            -- write
+                            when wr_a =>
+                                c_state  <= wr_b;
+                                iscl_oen <= '0'; -- keep SCL low
+                                isda_oen <= din; -- set SDA
+                                sda_chk  <= '0'; -- don't check SDA (SCL low)
+
+                            when wr_b =>
+                                c_state  <= wr_c;
+                                iscl_oen <= '1'; -- set SCL high
+                                isda_oen <= din; -- keep SDA
+                                sda_chk  <= '0'; -- don't check SDA yet
+                                                 -- Allow some more time for SDA and SCL to settle
+
+                            when wr_c =>
+                                c_state  <= wr_d;
+                                iscl_oen <= '1'; -- keep SCL high
+                                isda_oen <= din; -- keep SDA
+                                sda_chk  <= '1'; -- check SDA
+
+                            when wr_d =>
+                                c_state  <= idle;
+                                cmd_ack  <= '1'; -- command completed
+                                iscl_oen <= '0'; -- set SCL low
+                                isda_oen <= din; -- keep SDA
+                                sda_chk  <= '0'; -- don't check SDA (SCL low)
+
+                            when others =>
+
+                       end case;
+                   end if;
+               end if;
+        end if;
+    end process nxt_state_decoder;
+
+
+    -- assign outputs
+    scl_o   <= '0';
+    scl_oen <= iscl_oen;
+    sda_o   <= '0';
+    sda_oen <= isda_oen;
+end architecture structural;
+
diff --git a/sim/wb_i2c_bridge/i2c_master_byte_ctrl.vhd b/sim/wb_i2c_bridge/i2c_master_byte_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..e1691032544c15215f32e95480512ee91bc04d59
--- /dev/null
+++ b/sim/wb_i2c_bridge/i2c_master_byte_ctrl.vhd
@@ -0,0 +1,368 @@
+---------------------------------------------------------------------
+----                                                             ----
+----  WISHBONE revB2 compl. I2C Master Core; byte-controller     ----
+----                                                             ----
+----                                                             ----
+----  Author: Richard Herveille                                  ----
+----          richard@asics.ws                                   ----
+----          www.asics.ws                                       ----
+----                                                             ----
+----  Downloaded from: http://www.opencores.org/projects/i2c/    ----
+----                                                             ----
+---------------------------------------------------------------------
+----                                                             ----
+---- Copyright (C) 2000 Richard Herveille                        ----
+----                    richard@asics.ws                         ----
+----                                                             ----
+---- This source file may be used and distributed without        ----
+---- restriction provided that this copyright statement is not   ----
+---- removed from the file and that any derivative work contains ----
+---- the original copyright notice and the associated disclaimer.----
+----                                                             ----
+----     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ----
+---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ----
+---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ----
+---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ----
+---- 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.                                 ----
+----                                                             ----
+---------------------------------------------------------------------
+
+--  CVS Log
+--
+--  $Id: i2c_master_byte_ctrl.vhd,v 1.5 2004-02-18 11:41:48 rherveille Exp $
+--
+--  $Date: 2004-02-18 11:41:48 $
+--  $Revision: 1.5 $
+--  $Author: rherveille $
+--  $Locker:  $
+--  $State: Exp $
+--
+-- Change History:
+--               $Log: not supported by cvs2svn $
+--               Revision 1.4  2003/08/09 07:01:13  rherveille
+--               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
+--               Fixed a potential bug in the byte controller's host-acknowledge generation.
+--
+--               Revision 1.3  2002/12/26 16:05:47  rherveille
+--               Core is now a Multimaster I2C controller.
+--
+--               Revision 1.2  2002/11/30 22:24:37  rherveille
+--               Cleaned up code
+--
+--               Revision 1.1  2001/11/05 12:02:33  rherveille
+--               Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version.
+--               Code updated, is now up-to-date to doc. rev.0.4.
+--               Added headers.
+--
+
+
+
+
+--
+------------------------------------------
+-- Byte controller section
+------------------------------------------
+--
+library ieee;
+use ieee.std_logic_1164.all;
+--use ieee.std_logic_arith.all;
+use ieee.numeric_std.all;
+
+entity i2c_master_byte_ctrl is
+	port (
+		clk    : in std_logic;
+		rst    : in std_logic; -- synchronous active high reset (WISHBONE compatible)
+		nReset : in std_logic;	-- asynchornous active low reset (FPGA compatible)
+		ena    : in std_logic; -- core enable signal
+
+		clk_cnt : in unsigned(15 downto 0);	-- 4x SCL
+
+		-- input signals
+		start,
+		stop,
+		read,
+		write,
+		ack_in : std_logic;
+		din    : in std_logic_vector(7 downto 0);
+
+		-- output signals
+		cmd_ack  : out std_logic; -- command done
+		ack_out  : out std_logic;
+		i2c_busy : out std_logic; -- arbitration lost
+		i2c_al   : out std_logic; -- i2c bus busy
+		dout     : out std_logic_vector(7 downto 0);
+
+		-- i2c lines
+		scl_i   : in std_logic;  -- i2c clock line input
+		scl_o   : out std_logic; -- i2c clock line output
+		scl_oen : out std_logic; -- i2c clock line output enable, active low
+		sda_i   : in std_logic;  -- i2c data line input
+		sda_o   : out std_logic; -- i2c data line output
+		sda_oen : out std_logic  -- i2c data line output enable, active low
+	);
+end entity i2c_master_byte_ctrl;
+
+architecture structural of i2c_master_byte_ctrl is
+	component i2c_master_bit_ctrl is
+	port (
+		clk    : in std_logic;
+		rst    : in std_logic;
+		nReset : in std_logic;
+		ena    : in std_logic;				-- core enable signal
+
+		clk_cnt : in unsigned(15 downto 0);		-- clock prescale value
+
+		cmd     : in std_logic_vector(3 downto 0);
+		cmd_ack : out std_logic; -- command done
+		busy    : out std_logic; -- i2c bus busy
+		al      : out std_logic; -- arbitration lost
+
+		din  : in std_logic;
+		dout : out std_logic;
+
+		-- i2c lines
+		scl_i   : in std_logic;  -- i2c clock line input
+		scl_o   : out std_logic; -- i2c clock line output
+		scl_oen : out std_logic; -- i2c clock line output enable, active low
+		sda_i   : in std_logic;  -- i2c data line input
+		sda_o   : out std_logic; -- i2c data line output
+		sda_oen : out std_logic  -- i2c data line output enable, active low
+	);
+	end component i2c_master_bit_ctrl;
+
+	-- commands for bit_controller block
+	constant I2C_CMD_NOP  	: std_logic_vector(3 downto 0) := "0000";
+	constant I2C_CMD_START	: std_logic_vector(3 downto 0) := "0001";
+	constant I2C_CMD_STOP	 : std_logic_vector(3 downto 0) := "0010";
+	constant I2C_CMD_READ	 : std_logic_vector(3 downto 0) := "0100";
+	constant I2C_CMD_WRITE	: std_logic_vector(3 downto 0) := "1000";
+
+	-- signals for bit_controller
+	signal core_cmd : std_logic_vector(3 downto 0);
+	signal core_ack, core_txd, core_rxd : std_logic;
+	signal al : std_logic;
+
+	-- signals for shift register
+	signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
+	signal shift, ld : std_logic;
+
+	-- signals for state machine
+	signal go, host_ack : std_logic;
+	signal dcnt : unsigned(2 downto 0); -- data counter
+	signal cnt_done : std_logic;
+	    type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
+	    signal c_state : states;
+
+begin
+	-- hookup bit_controller
+	bit_ctrl: i2c_master_bit_ctrl port map(
+		clk     => clk,
+		rst     => rst,
+		nReset  => nReset,
+		ena     => ena,
+		clk_cnt => clk_cnt,
+		cmd     => core_cmd,
+		cmd_ack => core_ack,
+		busy    => i2c_busy,
+		al      => al,
+		din     => core_txd,
+		dout    => core_rxd,
+		scl_i   => scl_i,
+		scl_o   => scl_o,
+		scl_oen => scl_oen,
+		sda_i   => sda_i,
+		sda_o   => sda_o,
+		sda_oen => sda_oen
+	);
+	i2c_al <= al;
+
+	-- generate host-command-acknowledge
+	cmd_ack <= host_ack;
+
+	-- generate go-signal
+	go <= (read or write or stop) and not host_ack;
+
+	-- assign Dout output to shift-register
+	dout <= sr;
+
+	-- generate shift register
+	shift_register: process(clk, nReset)
+	begin
+	    if (nReset = '0') then
+	      sr <= (others => '0');
+	    elsif (clk'event and clk = '1') then
+	      if (rst = '1') then
+	        sr <= (others => '0');
+	      elsif (ld = '1') then
+	        sr <= din;
+	      elsif (shift = '1') then
+	        sr <= (sr(6 downto 0) & core_rxd);
+	      end if;
+	    end if;
+	end process shift_register;
+
+	-- generate data-counter
+	data_cnt: process(clk, nReset)
+	begin
+	    if (nReset = '0') then
+	      dcnt <= (others => '0');
+	    elsif (clk'event and clk = '1') then
+	      if (rst = '1') then
+	        dcnt <= (others => '0');
+	      elsif (ld = '1') then
+	        dcnt <= (others => '1');  -- load counter with 7
+	      elsif (shift = '1') then
+	        dcnt <= dcnt -1;
+	      end if;
+	    end if;
+	end process data_cnt;
+
+	cnt_done <= '1' when (dcnt = 0) else '0';
+
+	--
+	-- state machine
+	--
+	statemachine : block
+	begin
+	    --
+	    -- command interpreter, translate complex commands into simpler I2C commands
+	    --
+	    nxt_state_decoder: process(clk, nReset)
+	    begin
+	        if (nReset = '0') then
+	          core_cmd <= I2C_CMD_NOP;
+	          core_txd <= '0';
+	          shift    <= '0';
+	          ld       <= '0';
+	          host_ack <= '0';
+	          c_state  <= st_idle;
+	          ack_out  <= '0';
+	        elsif (clk'event and clk = '1') then
+	          if (rst = '1' or al = '1') then
+	            core_cmd <= I2C_CMD_NOP;
+	            core_txd <= '0';
+	            shift    <= '0';
+	            ld       <= '0';
+	            host_ack <= '0';
+	            c_state  <= st_idle;
+	            ack_out  <= '0';
+	          else
+	            -- initialy reset all signal
+	            core_txd <= sr(7);
+	            shift    <= '0';
+	            ld       <= '0';
+	            host_ack <= '0';
+
+	            case c_state is
+	              when st_idle =>
+	                 if (go = '1') then
+	                   if (start = '1') then
+	                     c_state  <= st_start;
+	                     core_cmd <= I2C_CMD_START;
+	                   elsif (read = '1') then
+	                     c_state  <= st_read;
+	                     core_cmd <= I2C_CMD_READ;
+	                   elsif (write = '1') then
+	                     c_state  <= st_write;
+	                     core_cmd <= I2C_CMD_WRITE;
+	                   else -- stop
+	                     c_state  <= st_stop;
+	                     core_cmd <= I2C_CMD_STOP;
+	                   end if;
+
+	                   ld <= '1';
+	                 end if;
+
+	              when st_start =>
+	                 if (core_ack = '1') then
+	                   if (read = '1') then
+	                     c_state  <= st_read;
+	                     core_cmd <= I2C_CMD_READ;
+	                   else
+	                     c_state  <= st_write;
+	                     core_cmd <= I2C_CMD_WRITE;
+	                   end if;
+
+	                   ld <= '1';
+	                 end if;
+
+	              when st_write =>
+	                 if (core_ack = '1') then
+	                   if (cnt_done = '1') then
+	                     c_state  <= st_ack;
+	                     core_cmd <= I2C_CMD_READ;
+	                   else
+	                     c_state  <= st_write;       -- stay in same state
+	                     core_cmd <= I2C_CMD_WRITE;  -- write next bit
+	                     shift    <= '1';
+	                   end if;
+	                 end if;
+
+	              when st_read =>
+	                 if (core_ack = '1') then
+	                   if (cnt_done = '1') then
+	                     c_state  <= st_ack;
+	                     core_cmd <= I2C_CMD_WRITE;
+	                   else
+	                     c_state  <= st_read;      -- stay in same state
+	                     core_cmd <= I2C_CMD_READ; -- read next bit
+	                   end if;
+
+	                   shift    <= '1';
+	                   core_txd <= ack_in;
+	                 end if;
+
+	              when st_ack =>
+	                 if (core_ack = '1') then
+	                   -- check for stop; Should a STOP command be generated ?
+	                   if (stop = '1') then
+	                     c_state  <= st_stop;
+	                     core_cmd <= I2C_CMD_STOP;
+	                   else
+	                     c_state  <= st_idle;
+	                     core_cmd <= I2C_CMD_NOP;
+
+	                     -- generate command acknowledge signal
+	                     host_ack <= '1';
+	                   end if;
+
+	                   -- assign ack_out output to core_rxd (contains last received bit)
+	                   ack_out  <= core_rxd;
+
+	                   core_txd <= '1';
+	                 else
+	                   core_txd <= ack_in;
+	                 end if;
+
+	              when st_stop =>
+	                 if (core_ack = '1') then
+	                   c_state  <= st_idle;
+	                   core_cmd <= I2C_CMD_NOP;
+
+	                   -- generate command acknowledge signal
+	                   host_ack <= '1';
+	                 end if;
+
+	              when others => -- illegal states
+	                 c_state  <= st_idle;
+	                 core_cmd <= I2C_CMD_NOP;
+	                 report ("Byte controller entered illegal state.");
+
+	            end case;
+
+	          end if;
+	        end if;
+	    end process nxt_state_decoder;
+
+	end block statemachine;
+
+end architecture structural;
+
diff --git a/sim/wb_i2c_bridge/run.do b/sim/wb_i2c_bridge/run.do
new file mode 100644
index 0000000000000000000000000000000000000000..e93d07883d5ff1085c6892976e6006159e6f70a9
--- /dev/null
+++ b/sim/wb_i2c_bridge/run.do
@@ -0,0 +1,30 @@
+vlib work
+
+vcom -explicit -93 "../../modules/genrams/genram_pkg.vhd"
+vcom -explicit -93 "../../modules/common/gencores_pkg.vhd"
+vcom -explicit -93 "../../modules/wishbone/wishbone_pkg.vhd"
+vcom -explicit -93 "../../modules/common/gc_sync_ffs.vhd"
+vcom -explicit -93 "../../modules/common/gc_glitch_filt.vhd"
+vcom -explicit -93 "../../modules/common/gc_fsm_watchdog.vhd"
+vcom -explicit -93 "../../modules/common/gc_i2c_slave.vhd"
+
+vcom -explicit -93 "../../modules/wishbone/wb_i2c_bridge/wb_i2c_bridge.vhd"
+
+vcom -explicit -93 "i2c_master_bit_ctrl.vhd"
+vcom -explicit -93 "i2c_master_byte_ctrl.vhd"
+
+vcom -explicit -93 "i2c_bus_model.vhd"
+
+vcom -explicit -93 "tb_wb_i2c_bridge.vhd"
+#vcom -explicit -93 "tb_gc_i2c_slave.vhd"
+
+vsim -t 1ps -voptargs="+acc" -lib work work.tb_wb_i2c_bridge
+
+radix -hexadecimal
+#add wave *
+do wave.do
+#do busmdl.do
+#do wave-i2cs.do
+
+run 20 ms
+wave zoomfull
diff --git a/sim/wb_i2c_bridge/tb_gc_i2c_slave.vhd b/sim/wb_i2c_bridge/tb_gc_i2c_slave.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..fd6846797eb01c331a5c313ab3e415d52af67100
--- /dev/null
+++ b/sim/wb_i2c_bridge/tb_gc_i2c_slave.vhd
@@ -0,0 +1,505 @@
+--==============================================================================
+-- CERN (BE-CO-HT)
+-- Testbench for old repeater design
+--==============================================================================
+--
+-- author: Theodor Stana (t.stana@cern.ch)
+--
+-- date of creation: 2013-02-28
+--
+-- version: 1.0
+--
+-- description:
+--
+-- dependencies:
+--
+-- references:
+--
+--==============================================================================
+-- GNU LESSER GENERAL PUBLIC LICENSE
+--==============================================================================
+-- This source file is free software; you can redistribute it and/or modify it
+-- under the terms of the GNU Lesser General Public License as published by the
+-- Free Software Foundation; either version 2.1 of the License, or (at your
+-- option) any later version. This source is distributed in the hope that it
+-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+-- See the GNU Lesser General Public License for more details. You should have
+-- received a copy of the GNU Lesser General Public License along with this
+-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
+--==============================================================================
+-- last changes:
+--    2013-02-28   Theodor Stana     t.stana@cern.ch     File created
+--==============================================================================
+-- TODO: -
+--==============================================================================
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.gencores_pkg.all;
+
+entity tb_gc_i2c_slave is
+end entity tb_gc_i2c_slave;
+
+
+architecture behav of tb_gc_i2c_slave is
+
+  --============================================================================
+  -- Type declarations
+  --============================================================================
+  type t_state_mst is
+    (
+      MST_IDLE,
+      MST_W1, MST_W1_ACK,
+      MST_W2, MST_W2_ACK,
+      MST_W3, MST_W3_ACK,
+      MST_R1, MST_R1_ACK,
+      MST_R2,
+      MST_R3,
+      MST_SUCCESS,
+      MST_ERR
+    );
+
+
+  type t_state_slv is
+    (
+      SLV_IDLE,
+      SLV_DETOP,
+      SLV_R1, SLV_R1_ACK,
+      SLV_R2, SLV_R2_ACK,
+      SLV_W1, SLV_W1_ACK,
+      SLV_W2, SLV_W2_ACK
+    );
+
+  --============================================================================
+  -- Constant declarations
+  --============================================================================
+  constant c_clk_per : time := 50 ns;
+  constant c_reset_width : time := 31 ns;
+
+  --============================================================================
+  -- Component declarations
+  --============================================================================
+  -- I2C master
+  component i2c_master_byte_ctrl is
+    port
+    (
+      clk    : in std_logic;
+      rst    : in std_logic; -- synchronous active high reset (WISHBONE compatible)
+      nReset : in std_logic;	-- asynchornous active low reset (FPGA compatible)
+      ena    : in std_logic; -- core enable signal
+
+      clk_cnt : in unsigned(15 downto 0);	-- 4x SCL
+
+      -- input signals
+      start,
+      stop,
+      read,
+      write,
+      ack_in : std_logic;
+      din    : in std_logic_vector(7 downto 0);
+
+      -- output signals
+      cmd_ack  : out std_logic; -- command done
+      ack_out  : out std_logic;
+      i2c_busy : out std_logic; -- arbitration lost
+      i2c_al   : out std_logic; -- i2c bus busy
+      dout     : out std_logic_vector(7 downto 0);
+
+      -- i2c lines
+      scl_i   : in std_logic;  -- i2c clock line input
+      scl_o   : out std_logic; -- i2c clock line output
+      scl_oen : out std_logic; -- i2c clock line output enable, active low
+      sda_i   : in std_logic;  -- i2c data line input
+      sda_o   : out std_logic; -- i2c data line output
+      sda_oen : out std_logic  -- i2c data line output enable, active low
+    );
+  end component i2c_master_byte_ctrl;
+
+  --============================================================================
+  -- Signal declarations
+  --============================================================================
+  signal clk, rst_n  : std_logic := '0';
+  signal rst         : std_logic;
+
+  signal scl_to_slv  : std_logic;
+  signal scl_fr_slv  : std_logic;
+  signal scl_en_slv  : std_logic;
+  signal sda_to_slv  : std_logic;
+  signal sda_fr_slv  : std_logic;
+  signal sda_en_slv  : std_logic;
+
+  signal slv_ack     : std_logic;
+  signal slv_op      : std_logic;
+
+  signal scl_to_mst  : std_logic;
+  signal scl_fr_mst  : std_logic;
+  signal scl_en_mst  : std_logic;
+  signal sda_to_mst  : std_logic;
+  signal sda_fr_mst  : std_logic;
+  signal sda_en_mst  : std_logic;
+
+  signal addr        : std_logic_vector(6 downto 0);
+
+  signal txb, rxb    : std_logic_vector(7 downto 0);
+  signal rcvd        : std_logic_vector(7 downto 0);
+
+  signal slv_r_done_p    : std_logic;
+  signal slv_w_done_p    : std_logic;
+  signal slv_addr_good_p : std_logic;
+  signal slv_sta_p       : std_logic;
+  signal slv_sto_p       : std_logic;
+
+  signal mst_sta     : std_logic;
+  signal mst_sto     : std_logic;
+  signal mst_rd      : std_logic;
+  signal mst_wr      : std_logic;
+  signal mst_ack     : std_logic;
+
+  signal mst_dat_in  : std_logic_vector(7 downto 0);
+  signal mst_dat_out : std_logic_vector(7 downto 0);
+
+  signal mst_cmd_ack : std_logic;
+  signal ack_fr_slv  : std_logic;
+
+  signal state_mst   : t_state_mst;
+  signal state_slv   : t_state_slv;
+
+  signal cnt         : unsigned(2 downto 0);
+  signal once        : boolean;
+  signal tmp         : std_logic_vector(7 downto 0);
+
+--==============================================================================
+--  architecture begin
+--==============================================================================
+begin
+
+  -- CLOCK GENERATION
+  p_clk: process
+  begin
+    clk <= not clk;
+    wait for c_clk_per/2;
+  end process p_clk;
+
+  -- RESET GENERATION
+  rst <= not rst_n;
+  p_rst_n: process
+  begin
+    rst_n <= '0';
+    wait for c_reset_width;
+    rst_n <= '1';
+    wait;
+  end process p_rst_n;
+
+  -- DUT INSTANTIATION
+  DUT: gc_i2c_slave
+    port map
+    (
+      clk_i         => clk,
+      rst_n_i       => rst_n,
+
+      scl_i         => scl_to_slv,
+      scl_o         => scl_fr_slv,
+      scl_en_o      => scl_en_slv,
+      sda_i         => sda_to_slv,
+      sda_o         => sda_fr_slv,
+      sda_en_o      => sda_en_slv,
+
+      addr_i        => addr,
+
+      ack_i         => slv_ack,
+
+      tx_byte_i     => txb,
+      rx_byte_o     => rxb,
+
+      sta_p_o       => slv_sta_p,
+      sto_p_o       => slv_sto_p,
+      addr_good_p_o => slv_addr_good_p,
+      r_done_p_o    => slv_r_done_p,
+      w_done_p_o    => slv_w_done_p,
+      op_o          => slv_op
+    );
+
+  scl_to_slv <= scl_fr_mst when scl_en_mst = '0' else
+                scl_fr_slv when scl_en_slv = '1' else
+                '1';
+  sda_to_slv <= sda_fr_slv when sda_en_slv = '1' else
+                sda_fr_mst when sda_en_mst = '0' else
+                '1';
+
+  -- MASTER INSTANTIATION
+  cmp_master: i2c_master_byte_ctrl
+    port map
+    (
+      clk      => clk,
+      rst      => rst,
+      nReset   => rst_n,
+      ena      => '1',
+
+      clk_cnt  => x"00FA",
+
+      -- input signals
+      start    => mst_sta,
+      stop     => mst_sto,
+      read     => mst_rd,
+      write    => mst_wr,
+      ack_in   => mst_ack,
+      din      => mst_dat_in,
+
+      -- output signals
+      cmd_ack  => mst_cmd_ack,
+      ack_out  => ack_fr_slv,
+      i2c_busy => open,
+      i2c_al   => open,
+      dout     => mst_dat_out,
+
+      -- i2c lines
+      scl_i    => scl_to_mst,
+      scl_o    => scl_fr_mst,
+      scl_oen  => scl_en_mst,
+      sda_i    => sda_to_mst,
+      sda_o    => sda_fr_mst,
+      sda_oen  => sda_en_mst
+    );
+
+  -- BUS MODEL
+  scl_to_mst <= scl_fr_mst when scl_en_mst = '0' else
+                scl_fr_slv when scl_en_slv = '1' else
+                '1';
+
+  sda_to_mst <= sda_fr_slv when sda_en_slv = '1' else
+                sda_fr_mst when sda_en_mst = '0' else
+                '1';
+
+  -- STIMULI
+  addr <= "1011110";
+
+  -- I2C SLAVE FSM
+  p_slv_fsm: process (clk) is
+  begin
+    if rising_edge(clk) then
+      if (rst_n = '0') then
+        state_slv <= SLV_IDLE;
+        slv_ack   <= '0';
+        txb       <= (others => '0');
+      else
+        case state_slv is
+
+          -- IDLE, wait for slave to do something
+          when SLV_IDLE =>
+            if (slv_addr_good_p = '1') then
+              slv_ack   <= '1';
+              state_slv <= SLV_DETOP;
+            end if;
+
+          -- master sent something to our slave, see what
+          -- we have to do...
+          when SLV_DETOP =>
+            if (slv_op = '0') then
+              state_slv <= SLV_R1;
+            else
+              state_slv <= SLV_W1;
+            end if;
+
+          -- SLV_R1
+          -- when done = '1', the slave goes into
+          -- WAIT_ACK state, so we must provide ACK.
+          when SLV_R1 =>
+            if (slv_r_done_p = '1') then
+              state_slv <= SLV_R1_ACK;
+              rcvd      <= rxb;
+            end if;
+
+          -- tell the slave to ACK, go back to IDLE
+          when SLV_R1_ACK =>
+            slv_ack   <= '1';
+            state_slv <= SLV_R2;
+
+          -- reading second byte from master, wait until
+          -- done = '1', and go to R2_ACK state
+          when SLV_R2 =>
+            if (slv_r_done_p = '1') then
+              state_slv <= SLV_R2_ACK;
+              rcvd      <= rxb;
+            end if;
+
+          -- R2_ACK
+          when SLV_R2_ACK =>
+            slv_ack   <= '1';
+            state_slv <= SLV_IDLE;
+
+          -- loopback received byte
+          when SLV_W1 =>
+            txb <= rcvd;
+            if (slv_w_done_p = '1') then
+              state_slv <= SLV_W2;
+            end if;
+
+          -- loopback received byte
+          when SLV_W2 =>
+            txb <= rcvd;
+            if (slv_w_done_p = '1') then
+              state_slv <= SLV_IDLE;
+            end if;
+
+          when others =>
+            state_slv <= SLV_IDLE;
+
+        end case;
+
+      end if;
+    end if;
+  end process p_slv_fsm;
+
+  -- I2C MASTER FSM
+  tmp <= mst_dat_out;
+
+  p_mst_fsm: process (clk) is
+  begin
+    if rising_edge(clk) then
+      if (rst_n = '0') then
+        state_mst      <= MST_IDLE;
+        mst_sta    <= '0';
+        mst_wr     <= '0';
+        mst_sto    <= '0';
+        mst_rd     <= '0';
+        mst_dat_in <= (others => '0');
+        mst_ack    <= '1';
+        cnt        <= (others => '0');
+        once       <= true;
+      else
+        case state_mst is
+
+          when MST_IDLE =>
+            state_mst <= MST_W1;
+
+          when MST_W1 =>
+            mst_sta <= '1';
+            mst_wr  <= '1';
+            mst_dat_in <= addr & '0';
+            if (mst_cmd_ack = '1') then
+              mst_sta <= '0';
+              mst_wr  <= '0';
+              state_mst <= MST_W1_ACK;
+            end if;
+
+          when MST_W1_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                state_mst <= MST_W2;
+              else
+                state_mst <= MST_ERR;
+              end if;
+            end if;
+
+          when MST_W2 =>
+            mst_wr <= '1';
+            mst_dat_in <= x"33";
+            if (mst_cmd_ack = '1') then
+              mst_wr <= '0';
+              state_mst <= MST_W2_ACK;
+            end if;
+
+          when MST_W2_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                state_mst <= MST_W3;
+              else
+                state_mst <= MST_ERR;
+              end if;
+            end if;
+
+          when MST_W3 =>
+            mst_wr <= '1';
+            mst_dat_in <= x"12";
+            if (mst_cmd_ack = '1') then
+              mst_wr  <= '0';
+              mst_sto <= '0';
+              state_mst <= MST_W3_ACK;
+            end if;
+
+          when MST_W3_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                state_mst <= MST_R1;
+              else
+                state_mst <= MST_ERR;
+              end if;
+            end if;
+
+          when MST_R1 =>
+            mst_sta <= '1';
+            mst_wr  <= '1';
+            mst_dat_in <= addr & '1';
+            if (mst_cmd_ack = '1') then
+              mst_sta <= '0';
+              mst_wr  <= '0';
+              state_mst <= MST_R1_ACK;
+            end if;
+
+          when MST_R1_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                state_mst <= MST_R2;
+              else
+                state_mst <= MST_ERR;
+              end if;
+            end if;
+
+          when MST_R2 =>
+            mst_rd <= '1';
+            --mst_sto   <= '1';
+            mst_ack <= '0';
+            if (mst_cmd_ack = '1') then
+              mst_rd  <= '0';
+              mst_sto <= '0';
+              if (tmp = x"12") then
+                state_mst <= MST_R3;
+              else
+                state_mst <= MST_ERR;
+              end if;
+            end if;
+
+          when MST_R3 =>
+            mst_rd  <= '1';
+            mst_sto <= '1';
+            mst_ack <= '0';
+            if (mst_cmd_ack = '1') then
+              mst_rd  <= '0';
+              mst_sto <= '0';
+              if (tmp = x"12") then
+                state_mst <= MST_SUCCESS;
+              else
+                state_mst <= MST_ERR;
+              end if;
+            end if;
+
+          when MST_SUCCESS =>
+            if (once) then
+              report("Success!");
+              once <= false;
+            end if;
+
+          when MST_ERR =>
+            if (once) then
+              report("Error!");
+              once <= false;
+            end if;
+
+          when others =>
+            state_mst <= MST_ERR;
+
+        end case;
+      end if;
+    end if;
+  end process p_mst_fsm;
+end architecture behav;
+--==============================================================================
+--  architecture end
+--==============================================================================
diff --git a/sim/wb_i2c_bridge/tb_wb_i2c_bridge.vhd b/sim/wb_i2c_bridge/tb_wb_i2c_bridge.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..10ba53e0098e54191a02c23ae95dff0f6f590a3e
--- /dev/null
+++ b/sim/wb_i2c_bridge/tb_wb_i2c_bridge.vhd
@@ -0,0 +1,698 @@
+--==============================================================================
+-- CERN (BE-CO-HT)
+-- Testbench for old repeater design
+--==============================================================================
+--
+-- author: Theodor Stana (t.stana@cern.ch)
+--
+-- date of creation: 2013-02-28
+--
+-- version: 1.0
+--
+-- description:
+--
+-- dependencies:
+--
+-- references:
+--
+--==============================================================================
+-- GNU LESSER GENERAL PUBLIC LICENSE
+--==============================================================================
+-- This source file is free software; you can redistribute it and/or modify it
+-- under the terms of the GNU Lesser General Public License as published by the
+-- Free Software Foundation; either version 2.1 of the License, or (at your
+-- option) any later version. This source is distributed in the hope that it
+-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+-- See the GNU Lesser General Public License for more details. You should have
+-- received a copy of the GNU Lesser General Public License along with this
+-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
+--==============================================================================
+-- last changes:
+--    2013-02-28   Theodor Stana     t.stana@cern.ch     File created
+--==============================================================================
+-- TODO: -
+--==============================================================================
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.wishbone_pkg.all;
+
+entity tb_wb_i2c_bridge is
+end entity tb_wb_i2c_bridge;
+
+
+architecture behav of tb_wb_i2c_bridge is
+
+  --============================================================================
+  -- Type declarations
+  --============================================================================
+  type t_state is
+    (
+      IDLE,
+      I2C_ADDR, I2C_ADDR_ACK,
+
+      WB_ADDR_B0, WB_ADDR_B0_ACK,
+      WB_ADDR_B1, WB_ADDR_B1_ACK,
+
+      ST_OP,
+
+      RD_RESTART, RD_RESTART_ACK,
+      RD, RD_ACK,
+
+      WR, WR_ACK,
+
+      STO,
+
+      SUCCESS,
+      ERR
+    );
+
+  type t_reg is array(0 to 3) of std_logic_vector(31 downto 0);
+
+  --============================================================================
+  -- Constant declarations
+  --============================================================================
+  constant c_clk_per : time := 50 ns;
+  constant c_reset_width : time := 112 ns;
+
+  constant c_nr_masters : positive := 1;
+  constant c_nr_slaves  : positive := 2;
+
+  constant c_sval : unsigned := x"424c4f24";
+  constant c_eval : unsigned := c_sval + x"A";
+
+  --============================================================================
+  -- Component declarations
+  --============================================================================
+  -- I2C master
+  component i2c_master_byte_ctrl is
+    port
+    (
+      clk    : in std_logic;
+      rst    : in std_logic; -- synchronous active high reset (WISHBONE compatible)
+      nReset : in std_logic;	-- asynchornous active low reset (FPGA compatible)
+      ena    : in std_logic; -- core enable signal
+
+      clk_cnt : in unsigned(15 downto 0);	-- 4x SCL
+
+      -- input signals
+      start,
+      stop,
+      read,
+      write,
+      ack_in : std_logic;
+      din    : in std_logic_vector(7 downto 0);
+
+      -- output signals
+      cmd_ack  : out std_logic; -- command done
+      ack_out  : out std_logic;
+      i2c_busy : out std_logic; -- arbitration lost
+      i2c_al   : out std_logic; -- i2c bus busy
+      dout     : out std_logic_vector(7 downto 0);
+
+      -- i2c lines
+      scl_i   : in std_logic;  -- i2c clock line input
+      scl_o   : out std_logic; -- i2c clock line output
+      scl_oen : out std_logic; -- i2c clock line output enable, active low
+      sda_i   : in std_logic;  -- i2c data line input
+      sda_o   : out std_logic; -- i2c data line output
+      sda_oen : out std_logic  -- i2c data line output enable, active low
+    );
+  end component i2c_master_byte_ctrl;
+
+  -- I2C bus model
+  component i2c_bus_model is
+    generic
+    (
+      g_nr_masters : positive := 1;
+      g_nr_slaves  : positive := 1
+    );
+    port
+    (
+      -- Input ports from master lines
+      mscl_i : in  std_logic_vector(g_nr_masters-1 downto 0);
+      msda_i : in  std_logic_vector(g_nr_masters-1 downto 0);
+
+      -- Input ports from slave lines
+      sscl_i : in  std_logic_vector(g_nr_slaves-1 downto 0);
+      ssda_i : in  std_logic_vector(g_nr_slaves-1 downto 0);
+
+      -- SCL and SDA line outputs
+      scl_o  : out std_logic;
+      sda_o  : out std_logic
+    );
+  end component i2c_bus_model;
+
+  --============================================================================
+  -- Signal declarations
+  --============================================================================
+  -- Clock, reset signals
+  signal clk, rst_n    : std_logic := '0';
+  signal rst           : std_logic;
+
+  -- Slave-side I2C signals
+  signal scl_to_slv    : std_logic;
+  signal scl_fr_slv    : std_logic;
+  signal scl_en_slv    : std_logic;
+  signal sda_to_slv    : std_logic;
+  signal sda_fr_slv    : std_logic;
+  signal sda_en_slv    : std_logic;
+
+  signal scl_to_slv_1  : std_logic;
+  signal scl_fr_slv_1  : std_logic;
+  signal scl_en_slv_1  : std_logic;
+  signal sda_to_slv_1  : std_logic;
+  signal sda_fr_slv_1  : std_logic;
+  signal sda_en_slv_1  : std_logic;
+
+  -- SCL and SDA signals from slaves
+  signal sscl, ssda    : std_logic_vector(c_nr_slaves-1 downto 0);
+
+  -- Master-side I2C signals
+  signal scl_to_mst    : std_logic;
+  signal scl_fr_mst    : std_logic;
+  signal scl_en_mst    : std_logic;
+  signal sda_to_mst    : std_logic;
+  signal sda_fr_mst    : std_logic;
+  signal sda_en_mst    : std_logic;
+
+  -- SCL and SDA signals from master
+  signal mscl, msda    : std_logic_vector(c_nr_masters-1 downto 0);
+
+  -- I2C bus signals
+  signal scl, sda      : std_logic;
+
+  -- I2C address, done
+  signal slv_addr      : std_logic_vector(6 downto 0);
+  signal i2c_tip       : std_logic;
+  signal i2c_err       : std_logic;
+  signal i2c_tip_1     : std_logic;
+  signal i2c_err_1     : std_logic;
+
+  -- I2C master signals
+  signal mst_sta       : std_logic;
+  signal mst_sto       : std_logic;
+  signal mst_rd        : std_logic;
+  signal mst_wr        : std_logic;
+  signal mst_ack       : std_logic;
+  signal mst_dat_in    : std_logic_vector(7 downto 0);
+  signal mst_dat_out   : std_logic_vector(7 downto 0);
+  signal mst_cmd_ack   : std_logic;
+  signal ack_fr_slv    : std_logic;
+
+  -- Master FSM signals
+  signal state         : t_state;
+  signal mst_fsm_op    : std_logic;
+  signal mst_fsm_start : std_logic;
+  signal stim_cnt      : unsigned(31 downto 0);
+
+  -- misc signals
+  signal cnt           : unsigned(2 downto 0);
+  signal once          : boolean;
+
+  signal byte_cnt      : unsigned(1 downto 0);
+  signal rcvd          : std_logic_vector(31 downto 0);
+  signal read4         : std_logic;
+  signal send          : std_logic_vector(31 downto 0);
+  signal wrote         : std_logic;
+  signal adr           : std_logic_vector(31 downto 0);
+
+  -- Wishbone signals
+  signal wb_stb        : std_logic;
+  signal wb_cyc        : std_logic;
+  signal wb_sel        : std_logic_vector(3 downto 0);
+  signal wb_we         : std_logic;
+  signal wb_dat_m2s    : std_logic_vector(31 downto 0);
+  signal wb_dat_s2m    : std_logic_vector(31 downto 0);
+  signal wb_adr        : std_logic_vector(31 downto 0);
+  signal wb_ack        : std_logic;
+
+  signal reg           : t_reg;
+
+  signal wb_stb_1      : std_logic;
+  signal wb_cyc_1      : std_logic;
+  signal wb_sel_1      : std_logic_vector(3 downto 0);
+  signal wb_we_1       : std_logic;
+  signal wb_dat_m2s_1  : std_logic_vector(31 downto 0);
+  signal wb_dat_s2m_1  : std_logic_vector(31 downto 0);
+  signal wb_adr_1      : std_logic_vector(31 downto 0);
+  signal wb_ack_1      : std_logic;
+
+  signal reg_1         : t_reg;
+
+--==============================================================================
+--  architecture begin
+--==============================================================================
+begin
+
+  --============================================================================
+  -- Reset and clock generation
+  --============================================================================
+  -- clock
+  p_clk: process
+  begin
+    clk <= not clk;
+    wait for c_clk_per/2;
+  end process p_clk;
+
+  -- reset
+  rst <= not rst_n;
+  p_rst_n: process
+  begin
+    rst_n <= '0';
+    wait for c_reset_width;
+    rst_n <= '1';
+    wait;
+  end process p_rst_n;
+
+  --============================================================================
+  -- DUT instantiation
+  --============================================================================
+  ------------------------------------------------------------------------------
+  -- SLAVE 1
+  ------------------------------------------------------------------------------
+  -- First, the instantiation itself
+  DUT : wb_i2c_bridge
+    port map
+    (
+      -- Clock, reset
+      clk_i      => clk,
+      rst_n_i    => rst_n,
+
+      -- I2C lines
+      scl_i      => scl,
+      scl_o      => scl_fr_slv,
+      scl_en_o   => scl_en_slv,
+      sda_i      => sda,
+      sda_o      => sda_fr_slv,
+      sda_en_o   => sda_en_slv,
+
+      -- I2C address and status
+      i2c_addr_i => "1011110",
+      tip_o      => i2c_tip,
+      err_p_o    => i2c_err,
+
+      -- Wishbone master signals
+      wbm_stb_o  => wb_stb,
+      wbm_cyc_o  => wb_cyc,
+      wbm_sel_o  => wb_sel,
+      wbm_we_o   => wb_we,
+      wbm_dat_i  => wb_dat_s2m,
+      wbm_dat_o  => wb_dat_m2s,
+      wbm_adr_o  => wb_adr,
+      wbm_ack_i  => wb_ack,
+      wbm_rty_i  => '0',
+      wbm_err_i  => '0'
+    );
+
+  -- Then, the tri-state buffer for the I2C lines
+  sscl(0) <= scl_fr_slv when (scl_en_slv = '1') else
+             '1';
+  ssda(0) <= sda_fr_slv when (sda_en_slv = '1') else
+             '1';
+
+  ------------------------------------------------------------------------------
+  -- SLAVE 2
+  ------------------------------------------------------------------------------
+  -- First, the instantiation itself
+  DUT_1 : wb_i2c_bridge
+    port map
+    (
+      -- Clock, reset
+      clk_i      => clk,
+      rst_n_i    => rst_n,
+
+      -- I2C lines
+      scl_i      => scl,
+      scl_o      => scl_fr_slv_1,
+      scl_en_o   => scl_en_slv_1,
+      sda_i      => sda,
+      sda_o      => sda_fr_slv_1,
+      sda_en_o   => sda_en_slv_1,
+
+      -- I2C address and status
+      i2c_addr_i => "1011101",
+      tip_o      => i2c_tip_1,
+      err_p_o    => i2c_err_1,
+
+      -- Wishbone master signals
+      wbm_stb_o  => wb_stb_1,
+      wbm_cyc_o  => wb_cyc_1,
+      wbm_sel_o  => wb_sel_1,
+      wbm_we_o   => wb_we_1,
+      wbm_dat_i  => wb_dat_s2m_1,
+      wbm_dat_o  => wb_dat_m2s_1,
+      wbm_adr_o  => wb_adr_1,
+      wbm_ack_i  => wb_ack_1,
+      wbm_rty_i  => '0',
+      wbm_err_i  => '0'
+    );
+
+  -- Then, the tri-state buffer for the I2C lines
+  sscl(1) <= scl_fr_slv_1 when (scl_en_slv_1 = '1') else
+             '1';
+  ssda(1) <= sda_fr_slv_1 when (sda_en_slv_1 = '1') else
+             '1';
+
+  --============================================================================
+  -- Master instantiation
+  --============================================================================
+  -- First, the component instantiation
+  cmp_master: i2c_master_byte_ctrl
+    port map
+    (
+      clk      => clk,
+      rst      => rst,
+      nReset   => rst_n,
+      ena      => '1',
+
+      clk_cnt  => x"0027",
+
+      -- input signals
+      start    => mst_sta,
+      stop     => mst_sto,
+      read     => mst_rd,
+      write    => mst_wr,
+      ack_in   => mst_ack,
+      din      => mst_dat_in,
+
+      -- output signals
+      cmd_ack  => mst_cmd_ack,
+      ack_out  => ack_fr_slv,
+      i2c_busy => open,
+      i2c_al   => open,
+      dout     => mst_dat_out,
+
+      -- i2c lines
+      scl_i    => scl,
+      scl_o    => scl_fr_mst,
+      scl_oen  => scl_en_mst,
+      sda_i    => sda,
+      sda_o    => sda_fr_mst,
+      sda_oen  => sda_en_mst
+    );
+
+  -- Then, the tri-state buffers on the line
+  mscl(0) <= scl_fr_mst when (scl_en_mst = '0') else
+             '1';
+  msda(0) <= sda_fr_mst when (sda_en_mst = '0') else
+             '1';
+
+  --============================================================================
+  -- Bus model instantiation and connection to master and slaves
+  --============================================================================
+  cmp_i2c_bus : i2c_bus_model
+    generic map
+    (
+      g_nr_masters => c_nr_masters,
+      g_nr_slaves  => c_nr_slaves
+    )
+    port map
+    (
+      mscl_i => mscl,
+      msda_i => msda,
+      sscl_i => sscl,
+      ssda_i => ssda,
+      scl_o  => scl,
+      sda_o  => sda
+    );
+
+  --============================================================================
+  -- I2C Master FSM
+  --============================================================================
+  -- This FSM controls the signals to the master component to implement the I2C
+  -- protocol defined together with ELMA. The FSM is controlled by the
+  -- stimuli process below
+  p_mst_fsm : process (clk) is
+  begin
+    if rising_edge(clk) then
+      if (rst_n = '0') then
+        state      <= IDLE;
+        mst_sta    <= '0';
+        mst_wr     <= '0';
+        mst_sto    <= '0';
+        mst_rd     <= '0';
+        mst_dat_in <= (others => '0');
+        mst_ack    <= '0';
+        cnt        <= (others => '0');
+        once       <= true;
+        byte_cnt   <= (others => '0');
+        rcvd       <= (others => '0');
+        wrote      <= '0';
+        send       <= (others => '0');
+      else
+        case state is
+
+          when IDLE =>
+            if (mst_fsm_start = '1') then
+              state <= I2C_ADDR;
+              send  <= std_logic_vector(stim_cnt);
+            end if;
+
+          when I2C_ADDR =>
+            mst_sta   <= '1';
+            mst_wr    <= '1';
+            mst_dat_in <= slv_addr & '0';
+            if (mst_cmd_ack = '1') then
+              mst_sta <= '0';
+              mst_wr  <= '0';
+              state   <= I2C_ADDR_ACK;
+            end if;
+
+          when I2C_ADDR_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                state <= WB_ADDR_B0;
+              else
+                state <= ERR;
+              end if;
+            end if;
+
+          when WB_ADDR_B0 =>
+            mst_wr <= '1';
+            mst_dat_in <= adr(15 downto 8);
+            if (mst_cmd_ack = '1') then
+              mst_wr <= '0';
+              state  <= WB_ADDR_B0_ACK;
+            end if;
+
+          when WB_ADDR_B0_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                state <= WB_ADDR_B1;
+              else
+                state <= ERR;
+              end if;
+            end if;
+
+          when WB_ADDR_B1 =>
+            mst_wr <= '1';
+            mst_dat_in <= adr(7 downto 0);
+            if (mst_cmd_ack = '1') then
+              mst_wr <= '0';
+              state  <= WB_ADDR_B1_ACK;
+            end if;
+
+          when WB_ADDR_B1_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                state <= ST_OP;
+              else
+                state <= ERR;
+              end if;
+            end if;
+
+          when ST_OP =>
+            if (mst_fsm_op = '1') then
+              state <= RD_RESTART;
+            else
+              state <= WR;
+            end if;
+
+          when RD_RESTART =>
+            mst_wr <= '1';
+            mst_dat_in <= slv_addr & '1';
+            mst_sta <= '1';
+            if (mst_cmd_ack = '1') then
+              mst_sta <= '0';
+              mst_wr  <= '0';
+              state <= RD_RESTART_ACK;
+            end if;
+
+          when RD_RESTART_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                state <= RD;
+              else
+                state <= ERR;
+              end if;
+            end if;
+
+          when RD =>
+            mst_rd <= '1';
+            mst_ack <= '0';
+            if (byte_cnt = 3) then
+              mst_ack <= '1';
+            end if;
+            if (mst_cmd_ack = '1') then
+              mst_rd <= '0';
+              byte_cnt <= byte_cnt + 1;
+              rcvd     <= mst_dat_out & rcvd(31 downto 8);
+              mst_ack  <= '0';
+              state    <= RD;
+              if (byte_cnt = 3) then
+                state  <= STO;
+              end if;
+            end if;
+
+          when RD_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              byte_cnt <= byte_cnt + 1;
+              rcvd     <= mst_dat_out & rcvd(31 downto 8);
+              mst_ack  <= '0';
+              state    <= RD;
+              if (byte_cnt = 3) then
+                state  <= STO;
+              end if;
+            end if;
+
+          when WR =>
+            mst_wr <= '1';
+            mst_dat_in <= send(7 downto 0);
+            if (mst_cmd_ack = '1') then
+              mst_wr <= '0';
+              state  <= WR_ACK;
+            end if;
+
+          when WR_ACK =>
+            cnt <= cnt + 1;
+            if (cnt = 7) then
+              if (ack_fr_slv = '0') then
+                byte_cnt <= byte_cnt + 1;
+                send     <= x"00" & send(31 downto 8);
+                state    <= WR;
+                if (byte_cnt = 3) then
+                  state  <= STO;
+                end if;
+              else
+                state <= ERR;
+              end if;
+            end if;
+
+          when STO =>
+            mst_sto <= '1';
+            if (mst_cmd_ack = '1') then
+              mst_sto <= '0';
+              state   <= IDLE;
+            end if;
+
+          when ERR =>
+            if (once) then
+              report("Error!");
+              once <= false;
+            end if;
+
+          when others =>
+            state <= ERR;
+
+        end case;
+      end if;
+    end if;
+  end process p_mst_fsm;
+
+  --============================================================================
+  -- Wishbone slaves
+  --============================================================================
+  -- First slave
+  p_wb_slv: process (clk) is
+  begin
+    if rising_edge(clk) then
+      if (rst_n = '0') then
+        reg <= (
+               x"00000000",
+               x"00000000",
+               x"00000000",
+               x"00000000"
+             );
+        wb_ack <= '0';
+        wb_dat_s2m <= (others => '0');
+      else
+        wb_ack <= '0';
+        if (wb_cyc = '1') and (wb_stb = '1') then
+          wb_ack <= '1';
+          wb_dat_s2m <= reg(to_integer(unsigned(wb_adr)));
+          if (wb_we = '1') then
+            reg(to_integer(unsigned(wb_adr))) <= wb_dat_m2s;
+          end if;
+        end if;
+      end if;
+    end if;
+  end process p_wb_slv;
+
+  -- Second slave
+  p_wb_slv_1: process (clk) is
+  begin
+    if rising_edge(clk) then
+      if (rst_n = '0') then
+        reg_1 <= (
+                   x"00000000",
+                   x"00000000",
+                   x"00000000",
+                   x"00000000"
+                 );
+        wb_ack_1 <= '0';
+        wb_dat_s2m_1 <= (others => '0');
+      else
+        wb_ack_1 <= '0';
+        if (wb_cyc_1 = '1') and (wb_stb_1 = '1') then
+          wb_ack_1 <= '1';
+          wb_dat_s2m_1 <= reg_1(to_integer(unsigned(wb_adr_1)));
+          if (wb_we_1 = '1') then
+            reg_1(to_integer(unsigned(wb_adr_1))) <= wb_dat_m2s_1;
+          end if;
+        end if;
+      end if;
+    end if;
+  end process p_wb_slv_1;
+
+  --============================================================================
+  -- A stimuli process to control the I2C FSM
+  --============================================================================
+  p_stim : process (rst_n, state)
+  begin
+    if (rst_n = '0') then
+      stim_cnt      <= c_sval; --(others => '0');
+      mst_fsm_start <= '0';
+      mst_fsm_op    <= '0';
+      slv_addr      <= "1011110";
+      adr           <= (others => '0');
+    elsif (state = IDLE) then
+      stim_cnt      <= stim_cnt + 1;
+      mst_fsm_start <= '1';
+      adr(1 downto 0) <= std_logic_vector(stim_cnt(1 downto 0));
+      if (stim_cnt(0) = '1') then
+        slv_addr <= "1011110";
+      else
+        slv_addr <= "1011101";
+      end if;
+      case to_integer(stim_cnt) is
+        when to_integer(c_sval) to to_integer(c_eval) =>
+          mst_fsm_op <= '0';
+        when others =>
+          mst_fsm_op <= '1';
+      end case;
+    end if;
+  end process p_stim;
+
+end architecture behav;
+--==============================================================================
+--  architecture end
+--==============================================================================
diff --git a/sim/wb_i2c_bridge/wave-i2cs.do b/sim/wb_i2c_bridge/wave-i2cs.do
new file mode 100644
index 0000000000000000000000000000000000000000..dd39ab49985b32911d187aab55dac6fb72fab6a2
--- /dev/null
+++ b/sim/wb_i2c_bridge/wave-i2cs.do
@@ -0,0 +1,64 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate /tb_gc_i2c_slave/clk
+add wave -noupdate /tb_gc_i2c_slave/state_mst
+add wave -noupdate /tb_gc_i2c_slave/state_slv
+add wave -noupdate /tb_gc_i2c_slave/scl_to_slv
+add wave -noupdate /tb_gc_i2c_slave/sda_to_slv
+add wave -noupdate /tb_gc_i2c_slave/sda_fr_slv
+add wave -noupdate /tb_gc_i2c_slave/scl_fr_mst
+add wave -noupdate /tb_gc_i2c_slave/sda_to_mst
+add wave -noupdate /tb_gc_i2c_slave/sda_fr_mst
+add wave -noupdate -divider BUS
+add wave -noupdate /tb_gc_i2c_slave/scl_to_slv
+add wave -noupdate /tb_gc_i2c_slave/scl_fr_slv
+add wave -noupdate /tb_gc_i2c_slave/sda_to_slv
+add wave -noupdate /tb_gc_i2c_slave/sda_fr_slv
+add wave -noupdate /tb_gc_i2c_slave/scl_to_mst
+add wave -noupdate /tb_gc_i2c_slave/scl_fr_mst
+add wave -noupdate /tb_gc_i2c_slave/sda_to_mst
+add wave -noupdate /tb_gc_i2c_slave/sda_fr_mst
+add wave -noupdate -divider loopback
+add wave -noupdate /tb_gc_i2c_slave/txb
+add wave -noupdate /tb_gc_i2c_slave/rxb
+add wave -noupdate /tb_gc_i2c_slave/rcvd
+add wave -noupdate /tb_gc_i2c_slave/tmp
+add wave -noupdate -divider slave
+add wave -noupdate /tb_gc_i2c_slave/DUT/scl_i
+add wave -noupdate /tb_gc_i2c_slave/DUT/sda_i
+add wave -noupdate /tb_gc_i2c_slave/DUT/tick_p
+add wave -noupdate /tb_gc_i2c_slave/DUT/tick_en
+add wave -noupdate /tb_gc_i2c_slave/DUT/tick_cnt
+add wave -noupdate /tb_gc_i2c_slave/DUT/ack_i
+add wave -noupdate /tb_gc_i2c_slave/DUT/sda_en_o
+add wave -noupdate /tb_gc_i2c_slave/DUT/tx_byte_i
+add wave -noupdate /tb_gc_i2c_slave/DUT/rx_byte_o
+add wave -noupdate /tb_gc_i2c_slave/DUT/state
+add wave -noupdate /tb_gc_i2c_slave/DUT/txsr
+add wave -noupdate /tb_gc_i2c_slave/DUT/rxsr
+add wave -noupdate /tb_gc_i2c_slave/DUT/bit_cnt
+add wave -noupdate /tb_gc_i2c_slave/cnt
+add wave -noupdate /tb_gc_i2c_slave/DUT/op_o
+add wave -noupdate /tb_gc_i2c_slave/DUT/sta_p_o
+add wave -noupdate /tb_gc_i2c_slave/DUT/sto_p_o
+add wave -noupdate /tb_gc_i2c_slave/DUT/addr_good_p_o
+add wave -noupdate /tb_gc_i2c_slave/DUT/r_done_p_o
+add wave -noupdate /tb_gc_i2c_slave/DUT/w_done_p_o
+add wave -noupdate /tb_gc_i2c_slave/DUT/op_o
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {2555133080 ps} 0}
+configure wave -namecolwidth 400
+configure wave -valuecolwidth 100
+configure wave -justifyvalue left
+configure wave -signalnamewidth 0
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+configure wave -timelineunits ns
+update
+WaveRestoreZoom {0 ps} {4200 us}
diff --git a/sim/wb_i2c_bridge/wave.do b/sim/wb_i2c_bridge/wave.do
new file mode 100644
index 0000000000000000000000000000000000000000..026cf98384b1144307c2b37f5318d93553773639
--- /dev/null
+++ b/sim/wb_i2c_bridge/wave.do
@@ -0,0 +1,32 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate /tb_wb_i2c_bridge/clk
+add wave -noupdate /tb_wb_i2c_bridge/scl
+add wave -noupdate /tb_wb_i2c_bridge/sscl
+add wave -noupdate /tb_wb_i2c_bridge/sda
+add wave -noupdate -expand /tb_wb_i2c_bridge/ssda
+add wave -noupdate /tb_wb_i2c_bridge/state
+add wave -noupdate /tb_wb_i2c_bridge/stim_cnt
+add wave -noupdate /tb_wb_i2c_bridge/send
+add wave -noupdate -expand /tb_wb_i2c_bridge/reg
+add wave -noupdate -expand /tb_wb_i2c_bridge/reg_1
+add wave -noupdate /tb_wb_i2c_bridge/rcvd
+add wave -noupdate /tb_wb_i2c_bridge/DUT/cmp_i2c_slave/state
+add wave -noupdate /tb_wb_i2c_bridge/DUT_1/cmp_i2c_slave/state
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 2} {728700000 ps} 0}
+configure wave -namecolwidth 400
+configure wave -valuecolwidth 100
+configure wave -justifyvalue left
+configure wave -signalnamewidth 0
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+configure wave -timelineunits ns
+update
+WaveRestoreZoom {0 ps} {1640625 ns}