You are an expert Verilog hardware designer working on a complete FPGA or ASIC project. You are given the full source code of a Verilog project. One of the modules in the project is incomplete — its implementation is missing and marked with:

// >>> Module Implementation Begin

// <<< Module Implementation End

Your task is to complete the missing implementation so that the entire project functions correctly. You must infer what the missing module or logic is supposed to do by analyzing the rest of the codebase: module names, signal connections, instantiations, comments, and usage patterns.

Follow these rules:

1. Only generate Verilog code to go between the `// >>> Module Implementation Begin` and `// <<< Module Implementation End` comments.
2. Use Verilog-2001 syntax. Ensure the code is synthesizable.
3. Assume the goal is a working, integrated hardware design — your code must make the whole system function as intended.
4. Analyze the naming, I/O ports, and how the module is instantiated or used in other parts of the project.
5. Implement correct behavior based on design context. Do not guess randomly — reason it out.
6. Avoid vendor-specific features unless explicitly required.
7. Do not output comments, explanation, or anything outside the required code region unless explicitly asked.

Your output should contain **only the Verilog code** that fits inside the marked region.

/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */
`default_nettype none

module tt_um_I2C (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // will go high when the design is enabled
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

reg MOD_bi;
reg temp_data_in;
reg temp_clk_in; 
reg temp_data_out;
reg temp_clk_out;
reg temp_data_oe;
reg temp_clk_oe;
reg temp_data_out2;
reg temp_clk_out2;
reg temp_data_oe2;
reg temp_clk_oe2;

assign MOD_bi = ui_in[3];
/*  tt_um_I2C_SPI_Wrapper wrapper_inst(
    .i2c_data_in(ui_in[0]),
    .i2c_clk_in(ui_in[1]),
    .miso_i(ui_in[2]),
    .clk(i2c_wb_clk_i),
    .rst_n(i2c_wb_rst_i),
    .sck_o(uo_out[0]),
    .mosi_o(uo_out[1])
  );*/

    tt_um_I2C_SPI_Wrapper wrapper_inst(
        .i2c_data_in(temp_data_in),
        .i2c_clk_in(temp_clk_in),
    .miso_i(ui_in[2]),
    .i2c_wb_clk_i(clk),
    .i2c_wb_rst_i(rst_n),
    .sck_o(uo_out[0]),
        .mosi_o(uo_out[1]),
        .i2c_wb_err_i(ui_in[5]),
        .i2c_wb_rty_i(ui_in[6]),
        .i2c_data_out(temp_data_out),
        .i2c_clk_out(temp_clk_out),
        .i2c_data_oe(temp_data_oe),
        .i2c_clk_oe(temp_clk_oe)
      
        
  );

 /*   .i2c_data_out(uio_out[0]),
        .i2c_clk_out(uio_out[1]),
        .i2c_data_in(uio_in[0]),
        .i2c_clk_in(uio_in[1]),
        .i2c_data_oe(uio_oe[0]),
        .i2c_clk_oe(uio_oe[1]) */
  // All output pins must be assigned. If not used, assign to 0.

        assign uio_out[0] = temp_data_out2;
        assign uio_out[1] = temp_clk_out2;
        assign uio_oe[0] = temp_data_oe2;
        assign uio_oe[1] = temp_clk_oe2;
		
		assign uo_out[2] = temp_data_out;
        assign uo_out[3] = temp_clk_out;
        assign uo_out[4] = temp_data_oe;
        assign uo_out[5] = temp_clk_oe;
			

always @* begin
    if (MOD_bi) begin
       temp_data_in = uio_in[0];
       temp_clk_in = uio_in[1];
      //  uio_in[0] <= ui_in[0];
     //   uio_in[1] <= ui_in[1];
        temp_data_out2 <= temp_data_out;
        temp_clk_out2 <= temp_clk_out;
        temp_data_oe2 <= temp_data_oe;
        temp_clk_oe2 <= temp_clk_oe;

    end
    else begin
         // Assign default values if MOD_bi is 0
        temp_data_in = ui_in[0];
        temp_clk_in = ui_in[1];
        temp_data_out2 <= 0;
        temp_clk_out2 <= 0;
        temp_data_oe2 <= 0;
        temp_clk_oe2 <= 0;
    end
end

    
  assign uo_out[6]  = 0;
  assign uo_out[7]  = 0;


assign uio_out[2] =0;
assign uio_out[3] =0;
assign uio_out[4] =0;
assign uio_out[5]=0;
   
  assign uio_out[6] = 0;
  assign uio_out[7] = 0;


  assign uio_oe[2]  = 0;
  assign uio_oe[3]  = 0;
  assign uio_oe[4]  = 0;
  assign uio_oe[5]  = 0;
  assign uio_oe[6]  = 0;
  assign uio_oe[7]  = 0;

endmodule



  


`timescale 1ns/100ps
module tt_um_I2C_SPI_Wrapper (
    // SPI interface
     output wire        sck_o,         // serial clock output
     output wire       mosi_o,        // MasterOut SlaveIN
     input  wire       miso_i,         // MasterIn SlaveOut

    // I2C interface
    input   wire           i2c_data_in,
    input   wire           i2c_clk_in,
  
    input wire        i2c_wb_clk_i,
    input wire        i2c_wb_rst_i,

    output wire       i2c_data_out,
    output wire       i2c_clk_out,
    output wire       i2c_data_oe,
    output wire       i2c_clk_oe,

      // Wishbone error and retry inputs
    input wire i2c_wb_err_i,
    input wire i2c_wb_rty_i
);

//SPI Interface

  wire       spi_clk_i;         // clock
  wire       spi_rst_i;         // reset (asynchronous active low)
  wire       spi_cyc_i;         // cycle
  wire       spi_stb_i;         // strobe
    wire [7:0] spi_adr_i;         // ad;dress
  wire       spi_we_i;          // write enable
  wire [7:0] spi_dat_i;         // data input
  wire  [7:0] spi_dat_o;         // data output
  wire        spi_ack_o;         // normal bus termination
  wire        spi_inta_o;        // interrupt output

//I2C interface


    wire [7:0]  i2c_wb_data_i;
    wire  [7:0]  i2c_wb_data_o;
    wire  [7:0]  i2c_wb_addr_o;
    wire  [3:0]  i2c_wb_sel_o;
    wire         i2c_wb_we_o;
    wire         i2c_wb_cyc_o;
    wire         i2c_wb_stb_o;
    wire        i2c_wb_ack_i;
  
    




    // SPI module instantiation
    simple_spi_top spi_inst (
        .clk_i(spi_clk_i),
        .rst_i(spi_rst_i),
        .cyc_i(spi_cyc_i),
        .stb_i(spi_stb_i),
        .adr_i(spi_adr_i),
        .we_i(spi_we_i),
        .dat_i(spi_dat_i),
        .dat_o(spi_dat_o),
        .ack_o(spi_ack_o),
        .inta_o(spi_inta_o),
        .sck_o(sck_o),
        .mosi_o(mosi_o),
        .miso_i(miso_i)
    );

    // I2C to Wishbone module instantiation
    i2c_to_wb_top i2c_inst (
        .i2c_data_in(i2c_data_in),
        .i2c_clk_in(i2c_clk_in),
        .i2c_data_out(i2c_data_out),
        .i2c_clk_out(i2c_clk_out),
        .i2c_data_oe(i2c_data_oe),
        .i2c_clk_oe(i2c_clk_oe),
        .wb_data_i(i2c_wb_data_i),
        .wb_data_o(i2c_wb_data_o),
        .wb_addr_o(i2c_wb_addr_o),
        .wb_sel_o(i2c_wb_sel_o),
        .wb_we_o(i2c_wb_we_o),
        .wb_cyc_o(i2c_wb_cyc_o),
        .wb_stb_o(i2c_wb_stb_o),
        .wb_ack_i(i2c_wb_ack_i),
        .wb_err_i(i2c_wb_err_i),
        .wb_rty_i(i2c_wb_rty_i),
        .wb_clk_i(i2c_wb_clk_i),
        .wb_rst_i(i2c_wb_rst_i)
    );

// Connect SPI Wishbone interface to I2C to Wishbone interface
assign i2c_wb_data_i = spi_dat_o;
assign spi_dat_i = i2c_wb_data_o;
assign spi_adr_i= i2c_wb_addr_o;
// Assuming single byte transfers for simplicity
assign spi_clk_i = i2c_wb_clk_i;
assign spi_rst_i = i2c_wb_rst_i;
assign spi_we_i = i2c_wb_we_o;
assign spi_cyc_i = i2c_wb_cyc_o;
assign spi_stb_i = i2c_wb_stb_o;
assign i2c_wb_ack_i = spi_ack_o;

//spi_inta_o


endmodule


/////////////////////////////////////////////////////////////////////
////                                                             ////
////  OpenCores                    MC68HC11E based SPI interface ////
////                                                             ////
////  Author: Richard Herveille                                  ////
////          richard@asics.ws                                   ////
////          www.asics.ws                                       ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
//// Copyright (C) 2002 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: simple_spi_top.v,v 1.5 2004-02-28 15:59:50 rherveille Exp $
//
//  $Date: 2004-02-28 15:59:50 $
//  $Revision: 1.5 $
//  $Author: rherveille $
//  $Locker:  $
//  $State: Exp $
//
// Change History:
//               $Log: not supported by cvs2svn $
//               Revision 1.4  2003/08/01 11:41:54  rherveille
//               Fixed some timing bugs.
//
//               Revision 1.3  2003/01/09 16:47:59  rherveille
//               Updated clkcnt size and decoding due to new SPR bit assignments.
//
//               Revision 1.2  2003/01/07 13:29:52  rherveille
//               Changed SPR bits coding.
//
//               Revision 1.1.1.1  2002/12/22 16:07:15  rherveille
//               Initial release
//
//



//
// Motorola MC68HC11E based SPI interface
//
// Currently only MASTER mode is supported
//

// synopsys translate_off
`timescale 1ns/100ps
// synopsys translate_on

module simple_spi_top(
  // 8bit WISHBONE bus slave interface
  input  wire       clk_i,         // clock
  input  wire       rst_i,         // reset (asynchronous active low)
  input  wire       cyc_i,         // cycle
  input  wire       stb_i,         // strobe
 input  wire [7:0] adr_i,         // address
  input  wire       we_i,          // write enable
  input  wire [7:0] dat_i,         // data input
  output reg  [7:0] dat_o,         // data output
  output reg        ack_o,         // normal bus termination
  output reg        inta_o,        // interrupt output

  // SPI port
  output reg        sck_o,         // serial clock output
  output wire       mosi_o,        // MasterOut SlaveIN
  input  wire       miso_i         // MasterIn SlaveOut
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule





//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// 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 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.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////


`timescale 1ns/100ps


module
  i2c_to_wb_top
  #(
    parameter DW = 8,
    parameter AW = 8
  )
  (
    input               i2c_data_in,
    input               i2c_clk_in,
    output              i2c_data_out,
    output              i2c_clk_out,
    output              i2c_data_oe,
    output              i2c_clk_oe,

    input   [(DW-1):0]  wb_data_i,
    output  [(DW-1):0]  wb_data_o,
    output  [(AW-1):0]  wb_addr_o,
    output  [3:0]       wb_sel_o,
    output              wb_we_o,
    output              wb_cyc_o,
    output              wb_stb_o,
    input               wb_ack_i,
    input               wb_err_i,
    input               wb_rty_i,

    input               wb_clk_i,
    input               wb_rst_i
  );

  // --------------------------------------------------------------------
  //  wires
  wire tip_addr_byte;
  wire tip_read_byte;
  wire tip_write_byte;
  wire tip_wr_ack;
  wire tip_rd_ack;
  wire tip_addr_ack;

//   wire i2c_ack_out = 1'b0;
  wire i2c_ack_out;
  wire i2c_ack_done;

  wire [7:0]  i2c_byte_out;
  wire        i2c_parallel_load;


  // --------------------------------------------------------------------
  //  glitch filter

  wire gf_i2c_data_in;
  wire gf_i2c_data_in_rise;
  wire gf_i2c_data_in_fall;

  glitch_filter
    i_gf_i2c_data_in(
    .in(i2c_data_in),
    .out(gf_i2c_data_in),

    .rise(gf_i2c_data_in_rise),
    .fall(gf_i2c_data_in_fall),

    .clk(wb_clk_i),
    .rst(wb_rst_i)
  );

  wire gf_i2c_clk_in;
  wire gf_i2c_clk_in_rise;
  wire gf_i2c_clk_in_fall;

  glitch_filter
    i_gf_i2c_clk_in(
    .in(i2c_clk_in),
    .out(gf_i2c_clk_in),

    .rise(gf_i2c_clk_in_rise),
    .fall(gf_i2c_clk_in_fall),

    .clk(wb_clk_i),
    .rst(wb_rst_i)
  );


  // --------------------------------------------------------------------
  //  i2c data shift register w/ parallel load

  reg  [8:0]  i2c_data_in_r;                    // add throw away bit for serial_out
  wire        serial_out = i2c_data_in_r[8];

  always @(posedge wb_clk_i)
    if( i2c_parallel_load )
      i2c_data_in_r[7:0] <= i2c_byte_out;
    else if( (tip_write_byte & gf_i2c_clk_in_rise) | (tip_read_byte & gf_i2c_clk_in_fall) )
      i2c_data_in_r <= {i2c_data_in_r[7:0], gf_i2c_data_in};


  // --------------------------------------------------------------------
  //  main state machine
  i2c_to_wb_fsm
    i_i2c_to_wb_fsm
    (
      .i2c_data(gf_i2c_data_in),
      .i2c_data_rise(gf_i2c_data_in_rise),
      .i2c_data_fall(gf_i2c_data_in_fall),

      .i2c_clk(gf_i2c_clk_in),
      .i2c_clk_rise(gf_i2c_clk_in_rise),
      .i2c_clk_fall(gf_i2c_clk_in_fall),

      .i2c_r_w_bit(i2c_data_in_r[0]),
      .i2c_ack_out(i2c_ack_out),
      .i2c_ack_done(i2c_ack_done),

      .tip_addr_byte(tip_addr_byte),
      .tip_read_byte(tip_read_byte),
      .tip_write_byte(tip_write_byte),
      .tip_wr_ack(tip_wr_ack),
      .tip_rd_ack(tip_rd_ack),
      .tip_addr_ack(tip_addr_ack),

      .state_out(),
      .i2c_error(),

      .wb_clk_i(wb_clk_i),
      .wb_rst_i(wb_rst_i)
    );


  // --------------------------------------------------------------------
  //  i2c_to_wb_config
  i2c_to_wb_config
    i_i2c_to_wb_config
    (
      .i2c_byte_in(i2c_data_in_r[7:0]),
      .tip_addr_ack(tip_addr_ack),
      .i2c_ack_out(i2c_ack_out),

      .wb_clk_i(wb_clk_i),
      .wb_rst_i(wb_rst_i)
    );


  // --------------------------------------------------------------------
  //  i2c_to_wb_if
  i2c_to_wb_if #( .DW(DW), .AW(AW) )
    i_i2c_to_wb_if(
      .i2c_data(gf_i2c_data_in),
      .i2c_ack_done(i2c_ack_done),
      .i2c_byte_in(i2c_data_in_r[7:0]),
      .i2c_byte_out(i2c_byte_out),
      .i2c_parallel_load(i2c_parallel_load),
      .tip_wr_ack(tip_wr_ack),
      .tip_rd_ack(tip_rd_ack),
      .tip_addr_ack(tip_addr_ack),

      .wb_data_i(wb_data_i),
      .wb_data_o(wb_data_o),
      .wb_addr_o(wb_addr_o),
      .wb_sel_o(wb_sel_o),
      .wb_we_o(wb_we_o),
      .wb_cyc_o(wb_cyc_o),
      .wb_stb_o(wb_stb_o),
      .wb_ack_i(wb_ack_i),
      .wb_err_i(wb_err_i),
      .wb_rty_i(wb_rty_i),

      .wb_clk_i(wb_clk_i),
      .wb_rst_i(wb_rst_i)
    );


  // --------------------------------------------------------------------
  //  i2c_data out sync

  reg i2c_data_oe_r;
  always @(posedge wb_clk_i)
    if( wb_rst_i )
      i2c_data_oe_r <= 1'b0;
    else if( gf_i2c_clk_in_fall )
      i2c_data_oe_r <= tip_read_byte | tip_wr_ack;

  reg i2c_data_mux_select_r;
  always @(posedge wb_clk_i)
    if( gf_i2c_clk_in_fall )
      i2c_data_mux_select_r <= tip_wr_ack;


  // --------------------------------------------------------------------
  //  outputs

  assign i2c_data_out = i2c_data_mux_select_r ? i2c_ack_out : serial_out;
  assign i2c_data_oe  = i2c_data_oe_r;
  assign i2c_clk_out  = 1'b1;
  assign i2c_clk_oe   = 1'b0;

endmodule



//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// 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 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.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////


`timescale 1ns/100ps


module
  i2c_to_wb_if
  #(
    parameter DW = 8,
    parameter AW = 8
  )
  (
    input                   i2c_data,
    input                   i2c_ack_done,
    input       [7:0]       i2c_byte_in,
    output reg  [7:0]       i2c_byte_out,
    output                  i2c_parallel_load,
    input                   tip_wr_ack,
    input                   tip_rd_ack,
    input                   tip_addr_ack,

    input       [(DW-1):0]  wb_data_i,
    output      [(DW-1):0]  wb_data_o,
    output      [(AW-1):0]  wb_addr_o,
    output  reg [3:0]       wb_sel_o,
    output                  wb_we_o,
    output                  wb_cyc_o,
    output                  wb_stb_o,
    input                   wb_ack_i,
    input                   wb_err_i,
    input                   wb_rty_i,

    input                   wb_clk_i,
    input                   wb_rst_i
  );


  // --------------------------------------------------------------------
  //  wires
  wire i2c_r_w_bit = i2c_byte_in[0];


  // --------------------------------------------------------------------
  //  state machine

  localparam   STATE_IDLE       = 5'b00001;
  localparam   STATE_WRITE      = 5'b00010;
  localparam   STATE_WRITE_WAIT = 5'b00100;
  localparam   STATE_READ       = 5'b01000;
  localparam   STATE_READ_WAIT  = 5'b10000;

  reg [4:0] state;
  reg [4:0] next_state;

  always @(posedge wb_clk_i or posedge wb_rst_i)
    if(wb_rst_i)
      state <= STATE_IDLE;
    else
      state <= next_state;

  always @(*)
    case( state )
      STATE_IDLE:       if( tip_addr_ack & i2c_ack_done )
                          if(i2c_r_w_bit)
                            next_state = STATE_READ;
                          else
                            next_state = STATE_WRITE_WAIT;
                        else
                          next_state = STATE_IDLE;

      STATE_WRITE:      if( wb_ack_i )
                          next_state = STATE_WRITE_WAIT;
                        else
                          next_state = STATE_WRITE;

      STATE_WRITE_WAIT: if( tip_addr_ack )
                          next_state = STATE_IDLE;
                        else
                          if( tip_wr_ack & i2c_ack_done )
                            next_state = STATE_WRITE;
                          else  
                            next_state = STATE_WRITE_WAIT;

      STATE_READ:       if( wb_ack_i )
                          next_state = STATE_READ_WAIT;
                        else
                          next_state = STATE_READ;

      STATE_READ_WAIT:  if( tip_addr_ack )
                          next_state = STATE_IDLE;
                        else
                          if( tip_rd_ack & i2c_ack_done )
                            if(i2c_data)
                              next_state = STATE_IDLE;
                            else  
                              next_state = STATE_READ;
                          else  
                            next_state = STATE_READ_WAIT;

      default:          next_state = STATE_IDLE;
    endcase


  // --------------------------------------------------------------------
  //  wishbone offset address

  reg [7:0] i2c_offset_r;
  always @(posedge wb_clk_i)
    if( tip_addr_ack )
      if(i2c_r_w_bit)
        i2c_offset_r <= 8'h00;
      else
        i2c_offset_r <= 8'hff;
    else if( i2c_ack_done )
      i2c_offset_r <= i2c_offset_r + 1;


  // --------------------------------------------------------------------
  //  byte lane select

  always @(*)
    case( i2c_offset_r[1:0] )
      2'b00:  wb_sel_o = 4'b0001;
      2'b01:  wb_sel_o = 4'b0010;
      2'b10:  wb_sel_o = 4'b0100;
      2'b11:  wb_sel_o = 4'b1000;
    endcase

  always @(*)
    case( wb_sel_o )
      4'b0001:  i2c_byte_out = wb_data_i[1:0];
      4'b0010:  i2c_byte_out = wb_data_i[3:2];
      4'b0100:  i2c_byte_out = wb_data_i[5:4];
      4'b1000:  i2c_byte_out = wb_data_i[7:6];
      default:  i2c_byte_out = wb_data_i[1:0];
    endcase


  // --------------------------------------------------------------------
  //  outputs
  
  assign i2c_parallel_load = (state == STATE_READ);

  assign wb_addr_o[7:0] = i2c_offset_r;
  assign wb_data_o      = {i2c_byte_in, i2c_byte_in, i2c_byte_in, i2c_byte_in};
  assign wb_cyc_o       = (state == STATE_WRITE) | (state == STATE_READ);
  assign wb_stb_o       = (state == STATE_WRITE) | (state == STATE_READ);
  assign wb_we_o        = (state == STATE_WRITE);


endmodule



//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// 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 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.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////


`timescale 1ns/100ps


module
  i2c_to_wb_fsm
  (
    input         i2c_data,
    input         i2c_data_rise,
    input         i2c_data_fall,

    input         i2c_clk,
    input         i2c_clk_rise,
    input         i2c_clk_fall,

    input         i2c_r_w_bit,
    input         i2c_ack_out,
    output        i2c_ack_done,

    output        tip_addr_byte,
    output        tip_read_byte,
    output        tip_write_byte,
    output        tip_wr_ack,
    output        tip_rd_ack,
    output        tip_addr_ack,

    output  [7:0] state_out,
    output        i2c_error,

    input         wb_clk_i,
    input         wb_rst_i
  );

  // --------------------------------------------------------------------
  //  wires
  wire xmt_byte_done;

  wire tip_ack;


  // --------------------------------------------------------------------
  //  start & stop & ack

  wire start_detected = i2c_data_fall & i2c_clk;
  wire stop_detected  = i2c_data_rise & i2c_clk;


  // --------------------------------------------------------------------
  //  state machine

  localparam   STATE_IDLE       = 8'b00000001;
  localparam   STATE_ADDR_BYTE  = 8'b00000010;
  localparam   STATE_ADDR_ACK   = 8'b00000100;
  localparam   STATE_WRITE      = 8'b00001000;
  localparam   STATE_WR_ACK     = 8'b00010000;
  localparam   STATE_READ       = 8'b00100000;
  localparam   STATE_RD_ACK     = 8'b01000000;
  localparam   STATE_ERROR      = 8'b10000000;

  reg [7:0] state;
  reg [7:0] next_state;

  always @(posedge wb_clk_i or posedge wb_rst_i)
    if(wb_rst_i)
      state <= STATE_IDLE;
    else
      state <= next_state;

  always @(*)
    case( state )
      STATE_IDLE:       if( start_detected )
                          next_state = STATE_ADDR_BYTE;
                        else
                          next_state = STATE_IDLE;

      STATE_ADDR_BYTE:  if( xmt_byte_done )
                          next_state = STATE_ADDR_ACK;
                        else if( stop_detected )
                          next_state = STATE_ERROR;
                        else
                          next_state = STATE_ADDR_BYTE;

      STATE_ADDR_ACK:   if(i2c_ack_out)
                          next_state = STATE_IDLE;
                        else
                          if( i2c_ack_done )
                            if( i2c_r_w_bit )
                              next_state = STATE_READ;
                            else
                              next_state = STATE_WRITE;
                          else if( start_detected | stop_detected )
                            next_state = STATE_ERROR;
                          else
                            next_state = STATE_ADDR_ACK;

      STATE_WRITE:      if( xmt_byte_done )
                          next_state = STATE_WR_ACK;
                        else if( start_detected )
                          next_state = STATE_ADDR_BYTE;
                        else if( stop_detected )
                          next_state = STATE_IDLE;
                        else
                          next_state = STATE_WRITE;

      STATE_WR_ACK:     if( i2c_ack_done )
                          next_state = STATE_WRITE;
                        else if( start_detected | stop_detected )
                          next_state = STATE_ERROR;
                        else
                          next_state = STATE_WR_ACK;

      STATE_READ:       if( xmt_byte_done )
                          next_state = STATE_RD_ACK;
                        else if( start_detected )
                          next_state = STATE_ADDR_BYTE;
                        else if( stop_detected )
                          next_state = STATE_IDLE;
                        else
                          next_state = STATE_READ;

      STATE_RD_ACK:     if( i2c_ack_done )
                          if(i2c_data)
                            next_state = STATE_IDLE;
                          else
                            next_state = STATE_READ;
                        else if( start_detected | stop_detected )
                          next_state = STATE_ERROR;
                        else
                          next_state = STATE_RD_ACK;

      STATE_ERROR:      next_state = STATE_IDLE;

      default:          next_state = STATE_ERROR;
    endcase


  // --------------------------------------------------------------------
  //  bit counter
  reg [3:0] bit_count;

  assign  xmt_byte_done = (bit_count == 4'h7) & i2c_clk_rise;
  assign  tip_ack       = (bit_count == 4'h8);
  assign  i2c_ack_done  = tip_ack & i2c_clk_rise;

  always @(posedge wb_clk_i)
    if( wb_rst_i | i2c_ack_done | start_detected )
      bit_count <= 4'hf;
    else if( i2c_clk_fall )
      bit_count <= bit_count + 1;


  // --------------------------------------------------------------------
  //  debug
  wire i2c_start_error = (state == STATE_ADDR_BYTE) & start_detected;


  // --------------------------------------------------------------------
  //  outputs

  assign state_out = state;

  assign  tip_addr_byte   = (state == STATE_ADDR_BYTE);
  assign  tip_addr_ack    = (state == STATE_ADDR_ACK);
  assign  tip_read_byte   = (state == STATE_READ);
  assign  tip_write_byte  = tip_addr_byte               | (state == STATE_WRITE);
  assign  tip_wr_ack      = tip_addr_ack                | (state == STATE_WR_ACK);
  assign  tip_rd_ack      = (state == STATE_RD_ACK);

  assign i2c_error = (state == STATE_ERROR) | i2c_start_error;

endmodule




//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// 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 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.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////


`timescale 1ns/100ps


module
  i2c_to_wb_config
  (
    input   [7:0]       i2c_byte_in,
    input               tip_addr_ack,
    output              i2c_ack_out,
    
    input               wb_clk_i,
    input               wb_rst_i  
  );

  
  // --------------------------------------------------------------------
  //  address decoder  
  reg i2c_addr_ack_out_r;
  
  always @(*)
    casez( i2c_byte_in )
      8'b1111_000?: i2c_addr_ack_out_r = 1'b0;
      default:      i2c_addr_ack_out_r = 1'b1;
    endcase
    
    
  // --------------------------------------------------------------------
  //  outputs  
  assign i2c_ack_out = tip_addr_ack ? i2c_addr_ack_out_r : 1'b0;
//   assign i2c_ack_out = 1'b0;
  
    
endmodule



//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// 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 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.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////


`timescale 1ns/100ps


module
  glitch_filter
  #(
    parameter SIZE = 3
  ) 
  (
    input in,
    output reg out,
    
    output rise,
    output fall,
    
    input clk,
    input rst  
  );
  
  
  // --------------------------------------------------------------------
  //  in sync flop
  reg in_reg;
  always @(posedge clk)
    in_reg <= in;


  // --------------------------------------------------------------------
  //  glitch filter
  reg [(SIZE-1):0] buffer;
  always @(posedge clk)
    buffer <= { buffer[(SIZE-2):0], in_reg };
    
  wire all_hi = &{in_reg, buffer};
  wire all_lo = ~|{in_reg, buffer};
  
  wire out_en = (all_hi & in_reg) | (all_lo & ~in_reg);
  
  always @(posedge clk)
    if( out_en )
      out <= buffer[(SIZE-1)];


  // --------------------------------------------------------------------
  //  outputs  
  assign fall = all_lo & out;
  assign rise = all_hi & ~out;

  
endmodule



/////////////////////////////////////////////////////////////////////
////                                                             ////
//// FIFO 4 entries deep                                         ////
////                                                             ////
//// Authors: Rudolf Usselmann, Richard Herveille                ////
////          rudi@asics.ws     richard@asics.ws                 ////
////                                                             ////
////                                                             ////
//// Download from: http://www.opencores.org/projects/sasc       ////
////                http://www.opencores.org/projects/simple_spi ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
//// Copyright (C) 2000-2002 Rudolf Usselmann, Richard Herveille ////
////                         www.asics.ws                        ////
////                         rudi@asics.ws, 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: fifo4.v,v 1.1.1.1 2002-12-22 16:07:14 rherveille Exp $
//
//  $Date: 2002-12-22 16:07:14 $
//  $Revision: 1.1.1.1 $
//  $Author: rherveille $
//  $Locker:  $
//  $State: Exp $
//
// Change History:
//               $Log: not supported by cvs2svn $
//

// synopsys translate_off
`timescale 1ns/100ps
// synopsys translate_on


// 4 entry deep fast fifo
module fifo4(clk, rst, clr,  din, we, dout, re, full, empty);

parameter dw = 8;

input		clk, rst;
input		clr;
input   [dw:1]	din;
input		we;
output  [dw:1]	dout;
input		re;
output		full, empty;


////////////////////////////////////////////////////////////////////
//
// Local Wires
//

reg     [dw:1]	mem[0:3];
reg     [1:0]   wp;
reg     [1:0]   rp;
wire    [1:0]   wp_p1;
wire    [1:0]   wp_p2;
wire    [1:0]   rp_p1;
wire		full, empty;
reg		gb;

////////////////////////////////////////////////////////////////////
//
// Misc Logic
//

always @(posedge clk or negedge rst)
	if(!rst)	wp <= 2'h0; //#1 2'h0;
        else
		if(clr)		wp <= 2'h0;// #1 2'h0;
        else
		if(we)		wp <= wp_p1;//#1 wp_p1;

assign wp_p1 = wp + 2'h1;
assign wp_p2 = wp + 2'h2;

always @(posedge clk or negedge rst)
	if(!rst)	rp <=  2'h0; //#1 2'h0;
        else
	if(clr)		rp <=  2'h0;//#1 2'h0;
        else
		if(re)		rp <= rp_p1;//#1 rp_p1;

assign rp_p1 = rp + 2'h1;

// Fifo Output
assign  dout = mem[ rp ];

// Fifo Input
always @(posedge clk)
	if(we)	mem[ wp ] <=  din;//#1 din;

// Status
assign empty = (wp == rp) & !gb;
assign full  = (wp == rp) &  gb;

// Guard Bit ...
always @(posedge clk)
	if(!rst)			gb <= 1'b0;//#1 1'b0;
	else
	if(clr)				gb <= 1'b0;//#1 1'b0;
	else
	if((wp_p1 == rp) & we)		gb <= 1'b1;//#1 1'b1;
	else
	if(re)				gb <= 1'b1;//#1 1'b0;

endmodule


Reference solution:
rtl/generated.v: 
  //
  // Module body
  //
  reg  [7:0] spcr;       // Serial Peripheral Control Register ('HC11 naming)
  wire [7:0] spsr;       // Serial Peripheral Status register ('HC11 naming)
  reg  [7:0] sper;       // Serial Peripheral Extension register
  reg  [7:0] treg, rreg; // Transmit/Receive register

  // fifo signals
  wire [7:0] rfdout;
  reg        wfre, rfwe;
  wire       rfre, rffull, rfempty;
  wire [7:0] wfdout;
  wire       wfwe, wffull, wfempty;

  // misc signals
  wire      tirq;     // transfer interrupt (selected number of transfers done)
  wire      wfov;     // write fifo overrun (writing while fifo full)
  reg [1:0] state;    // statemachine state
  reg [2:0] bcnt;

  //
  // Wishbone interface
  wire wb_acc = cyc_i & stb_i;       // WISHBONE access
  wire wb_wr  = wb_acc & we_i;       // WISHBONE write access

  // dat_i
  always @(posedge clk_i or negedge rst_i)
    if (~rst_i)
      begin
          spcr <= 8'h10; //#1 8'h10;  // set master bit
          sper <= 8'h00;//#1 8'h00;
      end
    else if (wb_wr)
      begin
        if (adr_i == 2'b00)
          spcr <= dat_i | 8'h10;//#1 dat_i | 8'h10; // always set master bit

        if (adr_i == 2'b11)
          sper <= dat_i;//#1 dat_i;
      end

  // write fifo
  assign wfwe = wb_acc & (adr_i == 2'b10) & ack_o &  we_i;
  assign wfov = wfwe & wffull;

  // dat_o
  always @(posedge clk_i)
    case(adr_i) // synopsys full_case parallel_case
      2'b00: dat_o <= spcr;//#1 spcr;
      2'b01: dat_o <= spsr;//#1 spsr;
      2'b10: dat_o <=  rfdout;//#1 rfdout;
      2'b11: dat_o <= sper;//#1 sper;
    endcase

  // read fifo
  assign rfre = wb_acc & (adr_i == 2'b10) & ack_o & ~we_i;

  // ack_o
  always @(posedge clk_i or negedge rst_i)
    if (~rst_i)
      ack_o <=  1'b0;// #1 1'b0;
    else
      ack_o <=  wb_acc & !ack_o;//#1 wb_acc & !ack_o;

  // decode Serial Peripheral Control Register
  wire       spie = spcr[7];   // Interrupt enable bit
  wire       spe  = spcr[6];   // System Enable bit
  wire       dwom = spcr[5];   // Port D Wired-OR Mode Bit
  wire       mstr = spcr[4];   // Master Mode Select Bit
  wire       cpol = spcr[3];   // Clock Polarity Bit
  wire       cpha = spcr[2];   // Clock Phase Bit
  wire [1:0] spr  = spcr[1:0]; // Clock Rate Select Bits

  // decode Serial Peripheral Extension Register
  wire [1:0] icnt = sper[7:6]; // interrupt on transfer count
  wire [1:0] spre = sper[1:0]; // extended clock rate select

  wire [3:0] espr = {spre, spr};

  // generate status register
  wire wr_spsr = wb_wr & (adr_i == 2'b01);

  reg spif;
  always @(posedge clk_i)
    if (~spe)
      spif <= 1'b0;//#1 1'b0;
    else
      spif <= (tirq | spif) & ~(wr_spsr & dat_i[7]);//#1 (tirq | spif) & ~(wr_spsr & dat_i[7]);

  reg wcol;
  always @(posedge clk_i)
    if (~spe)
      wcol <= 1'b0;//#1 1'b0;
    else
      wcol <= (wfov | wcol) & ~(wr_spsr & dat_i[6]);//#1 (wfov | wcol) & ~(wr_spsr & dat_i[6]);

  assign spsr[7]   = spif;
  assign spsr[6]   = wcol;
  assign spsr[5:4] = 2'b00;
  assign spsr[3]   = wffull;
  assign spsr[2]   = wfempty;
  assign spsr[1]   = rffull;
  assign spsr[0]   = rfempty;
  

  // generate IRQ output (inta_o)
  always @(posedge clk_i)
    inta_o <= spif & spie; //#1 spif & spie;

  //
  // hookup read/write buffer fifo
  fifo4 #(8)
  rfifo(
	.clk   ( clk_i   ),
	.rst   ( rst_i   ),
	.clr   ( ~spe    ),
	.din   ( treg    ),
	.we    ( rfwe    ),
	.dout  ( rfdout  ),
	.re    ( rfre    ),
	.full  ( rffull  ),
	.empty ( rfempty )
  ),
  wfifo(
	.clk   ( clk_i   ),
	.rst   ( rst_i   ),
	.clr   ( ~spe    ),
	.din   ( dat_i   ),
	.we    ( wfwe    ),
	.dout  ( wfdout  ),
	.re    ( wfre    ),
	.full  ( wffull  ),
	.empty ( wfempty )
  );

  //
  // generate clk divider
  reg [11:0] clkcnt;
  always @(posedge clk_i)
    if(spe & (|clkcnt & |state))
      clkcnt <= clkcnt - 11'h1;//#1 clkcnt - 11'h1;
    else
      case (espr) // synopsys full_case parallel_case
        4'b0000: clkcnt <= 12'h0;//#1 12'h0;   // 2   -- original M68HC11 coding
        4'b0001: clkcnt <= 12'h1;  //#1 12'h1;   // 4   -- original M68HC11 coding
        4'b0010: clkcnt <= 12'h3; //#1 12'h3;   // 16  -- original M68HC11 coding
        4'b0011: clkcnt <= 12'hf; //#1 12'hf;   // 32  -- original M68HC11 coding
        4'b0100: clkcnt <= 12'h1f; //#1 12'h1f;  // 8
        4'b0101: clkcnt <= 12'h7; //#1 12'h7;   // 64
        4'b0110: clkcnt <= 12'h3f; //#1 12'h3f;  // 128
        4'b0111: clkcnt <= 12'h7f; //#1 12'h7f;  // 256
        4'b1000: clkcnt <= 12'hff; //#1 12'hff;  // 512
        4'b1001: clkcnt <= 12'h1ff; //#1 12'h1ff; // 1024
        4'b1010: clkcnt <= 12'h3ff; //#1 12'h3ff; // 2048
        4'b1011: clkcnt <= 12'h7ff; //#1 12'h7ff; // 4096
      endcase

  // generate clock enable signal
  wire ena = ~|clkcnt;

  // transfer statemachine
  always @(posedge clk_i)
    if (~spe)
      begin
          state <= 2'b00;//#1 2'b00; // idle
          bcnt  <= 3'h0;//#1 3'h0;
          treg  <=  8'h00;//#1 8'h00;
          wfre  <= 1'b0;//#1 1'b0;
          rfwe  <= 1'b0;//#1 1'b0;
          sck_o <= 1'b0;//#1 1'b0;
      end
    else
      begin
         wfre <= 1'b0;//#1 1'b0;
         rfwe <= 1'b0;//#1 1'b0;

         case (state) //synopsys full_case parallel_case
           2'b00: // idle state
              begin
                  bcnt  <= 3'h7;//#1 3'h7;   // set transfer counter
                  treg  <= wfdout;//#1 wfdout; // load transfer register
                  sck_o <= cpol;//#1 cpol;   // set sck

                  if (~wfempty) begin
                    wfre  <= 1'b1;//#1 1'b1;
                    state <= 2'b01;//#1 2'b01;
			  if (cpha) sck_o <=  ~sck_o;//#1 ~sck_o;
                  end
              end

           2'b01: // clock-phase2, next data
              if (ena) begin
                sck_o   <= ~sck_o; //#1 ~sck_o;
                state   <=  2'b11;//#1 2'b11;
              end

           2'b11: // clock phase1
              if (ena) begin
                treg <= {treg[6:0], miso_i};//#1 {treg[6:0], miso_i};
                bcnt <= bcnt -3'h1; //#1 bcnt -3'h1;

                if (~|bcnt) begin
                  state <= 2'b00;//#1 2'b00;
                  sck_o <= cpol;//#1 cpol;
                  rfwe  <= 1'b1;//#1 1'b1;
                end else begin
                  state <= 2'b01;//#1 2'b01;
                  sck_o <= ~sck_o;//#1 ~sck_o;
                end
              end

           2'b10: state <= 2'b00;//#1 2'b00;
         endcase
      end

  assign mosi_o = treg[7];


  // count number of transfers (for interrupt generation)
  reg [1:0] tcnt; // transfer count
  always @(posedge clk_i)
    if (~spe)
      tcnt <= icnt;//#1 icnt;
    else if (rfwe) // rfwe gets asserted when all bits have been transfered
      if (|tcnt)
        tcnt <= tcnt - 2'h1;//#1 tcnt - 2'h1;
      else
        tcnt <= icnt;//#1 icnt;

  assign tirq = ~|tcnt & rfwe;