diff --git a/i2c_slave_opencores/.gitignore b/i2c_slave_opencores/.gitignore
new file mode 100644
index 0000000..4ee54fa
--- /dev/null
+++ b/i2c_slave_opencores/.gitignore
@@ -0,0 +1,4 @@
+*.vcd
+sim/*.vcd
+sim/*.wlf
+sim/testHarness
diff --git a/i2c_slave_opencores/README.md b/i2c_slave_opencores/README.md
new file mode 100644
index 0000000..95bff49
--- /dev/null
+++ b/i2c_slave_opencores/README.md
@@ -0,0 +1,7 @@
+# i2c_slave_opencores
+
+I2C Verilog Testbench für einen CO2 Sensor
+
+Beispiel ist von OpenCores
+
+https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/i2c_slave_opencores
\ No newline at end of file
diff --git a/i2c_slave_opencores/bench/i2cSlaveTB_defines.v b/i2c_slave_opencores/bench/i2cSlaveTB_defines.v
new file mode 100644
index 0000000..31ae560
--- /dev/null
+++ b/i2c_slave_opencores/bench/i2cSlaveTB_defines.v
@@ -0,0 +1,17 @@
+// ---------------------------- i2cSlaveTB_defines.v -----------------
+`define SEND_START 1'b1
+`define SEND_STOP 1'b1
+`define NULL 1'b0
+`define ACK 1'b0
+`define NACK 1'b1
+
+`define DEV_I2C_ADDR 8'hcc
+
+`define PRER_LO_REG 3'b000
+`define PRER_HI_REG 3'b001
+`define CTR_REG 3'b010
+`define RXR_REG 3'b011
+`define TXR_REG 3'b011
+`define CR_REG 3'b100
+`define SR_REG 3'b100
+
diff --git a/i2c_slave_opencores/bench/multiByteReadWrite.v b/i2c_slave_opencores/bench/multiByteReadWrite.v
new file mode 100644
index 0000000..3048bfd
--- /dev/null
+++ b/i2c_slave_opencores/bench/multiByteReadWrite.v
@@ -0,0 +1,168 @@
+// ------------------ multiByteReadWrite.v ----------------------
+`include "timescale.v"
+`include "i2cSlaveTB_defines.v"
+
+
+module multiByteReadWrite();
+reg ack;
+reg [31:0] readData;
+reg [7:0] dataByteRead;
+//reg [7:0] dataMSB;
+
+// ------------------ write ----------------------
+task write;
+input [7:0] i2cAddr;
+input [15:0] regAddr;
+input [31:0] data;
+input stop;
+
+begin
+ $write("I2C Write: At [0x%0x] = 0x%0x\n", regAddr, data);
+
+ //i2c address
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, i2cAddr);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h90); //STA, WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("I2C device address sent, SR = 0x%x\n", dataByteRead );
+
+ //slave reg address high byte
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr[15:8]);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Slave reg address sent, SR = 0x%x\n", dataByteRead );
+
+ //slave reg address low byte
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr[7:0]);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Slave reg address sent, SR = 0x%x\n", dataByteRead );
+
+ //data[31:24]
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, data[31:24]);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Data[31:24] sent, SR = 0x%x\n", dataByteRead );
+
+ //data[23:16]
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, data[23:16]);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Data[23:16] sent, SR = 0x%x\n", dataByteRead );
+
+ //data[15:8]
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, data[15:8]);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h10); //WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Data[15:8] sent, SR = 0x%x\n", dataByteRead );
+
+ //data[7:0]
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, data[7:0]);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , {1'b0, stop, 6'b010000}); //STO?, WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Data[7:0] sent, SR = 0x%x\n", dataByteRead );
+
+end
+endtask
+
+// ------------------ read ----------------------
+task read;
+input [7:0] i2cAddr;
+input [15:0] regAddr;
+input [31:0] expectedData;
+output [31:0] data;
+input stop;
+
+begin
+
+ //i2c address
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, i2cAddr); //write
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h90); //STA, WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("I2C device address sent, SR = 0x%x\n", dataByteRead );
+ #5000;
+
+ //slave reg address high byte
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr[15:8]);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , {1'b0, stop, 6'b010000}); //STO?, WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Slave reg address sent, SR = 0x%x\n", dataByteRead );
+ #5000;
+ //slave reg address low byte
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr[7:0]);
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , {1'b0, stop, 6'b010000}); //STO?, WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Slave reg address sent, SR = 0x%x\n", dataByteRead );
+ #5000;
+
+ //i2c address
+ testHarness.u_wb_master_model.wb_write(1, `TXR_REG, {i2cAddr[7:1], 1'b1}); //read
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h90); //STA, WR
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("I2C device address sent, SR = 0x%x\n", dataByteRead );
+
+ //data[31:24]
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h20); //RD, ACK
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Data[31:24] rxed, SR = 0x%x\n", dataByteRead );
+ testHarness.u_wb_master_model.wb_read(1, `RXR_REG, readData[31:24]);
+
+ //data[23:16]
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h20); //RD, ACK
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Data[23:16] rxed, SR = 0x%x\n", dataByteRead );
+ testHarness.u_wb_master_model.wb_read(1, `RXR_REG, readData[23:16]);
+
+ //data[15:8]
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , 8'h20); //RD, ACK
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Data[15:8] rxed, SR = 0x%x\n", dataByteRead );
+ testHarness.u_wb_master_model.wb_read(1, `RXR_REG, readData[15:8]);
+
+ //data[7:0]
+ testHarness.u_wb_master_model.wb_write(1, `CR_REG , {1'b0, 1'b0, 6'b101000}); //STO, RD, NAK
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ while (dataByteRead[1] == 1'b1) //while trans in progress
+ testHarness.u_wb_master_model.wb_read(1, `SR_REG , dataByteRead);
+ //$write("Data[7:0] rxed, SR = 0x%x\n", dataByteRead );
+ testHarness.u_wb_master_model.wb_read(1, `RXR_REG, readData[7:0]);
+
+ data = readData;
+ if (data != expectedData) begin
+ $write("***** I2C Read ERROR: At 0x%0x. Expected 0x%0x, got 0x%0x\n", regAddr, expectedData, data);
+ //$stop;
+ end
+ else
+ $write("[read] I2C Read: At [0x%x] = 0x%0x\n", regAddr, data);
+end
+endtask
+
+endmodule
+
diff --git a/i2c_slave_opencores/bench/testCase0.v b/i2c_slave_opencores/bench/testCase0.v
new file mode 100644
index 0000000..dd6b5b9
--- /dev/null
+++ b/i2c_slave_opencores/bench/testCase0.v
@@ -0,0 +1,57 @@
+// ---------------------------------- testcase0.v ----------------------------
+`include "timescale.v"
+`include "i2cSlave_define.v"
+`include "i2cSlaveTB_defines.v"
+
+module testCase0();
+
+reg ack;
+reg [7:0] data;
+reg [15:0] dataWord;
+reg [7:0] dataRead;
+reg [7:0] dataWrite;
+integer i;
+integer j;
+
+initial
+begin
+ $write("\n\n");
+ testHarness.reset;
+ testHarness.tb_readEn <= 1'b0;
+ testHarness.tb_writeEn <= 1'b0;
+
+ // set i2c master clock scale reg PRER = (48MHz / (5 * 400KHz) ) - 1
+ $write("Testing register read/write\n");
+ testHarness.u_wb_master_model.wb_write(1, `PRER_LO_REG , 8'h17);
+ testHarness.u_wb_master_model.wb_write(1, `PRER_HI_REG , 8'h00);
+ testHarness.u_wb_master_model.wb_cmp(1, `PRER_LO_REG , 8'h17);
+
+ // enable i2c master
+ testHarness.u_wb_master_model.wb_write(1, `CTR_REG , 8'h80);
+
+
+ multiByteReadWrite.write({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, `SEND_STOP);
+ multiByteReadWrite.read({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, dataWord, `NULL);
+ #100;
+
+ testHarness.tb_addr <= 16'h1234;
+ testHarness.tb_dataIn <= 16'h5555;
+
+ #10 testHarness.tb_writeEn <= 1'b1;
+ #10 testHarness.tb_readEn <= 1'b1;
+ #10 testHarness.tb_writeEn <= 1'b0;
+ #10 testHarness.tb_readEn <= 1'b0;
+
+ #100;
+ multiByteReadWrite.read({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, dataWord, `NULL);
+
+ #100;
+ multiByteReadWrite.write({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, `SEND_STOP);
+ multiByteReadWrite.read({`I2C_ADDRESS, 1'b0}, 16'h1234, 32'h89abcdef, dataWord, `NULL);
+
+ $write("Finished all tests\n");
+ $finish;
+
+end
+endmodule
+
diff --git a/i2c_slave_opencores/bench/testHarness.v b/i2c_slave_opencores/bench/testHarness.v
new file mode 100644
index 0000000..2b3e06c
--- /dev/null
+++ b/i2c_slave_opencores/bench/testHarness.v
@@ -0,0 +1,122 @@
+// -------------------------- testHarness.v -----------------------
+`include "timescale.v"
+
+module testHarness ();
+
+reg rst;
+reg clk;
+reg i2cHostClk;
+wire sda;
+wire scl;
+wire sdaOutEn;
+wire sdaOut;
+wire sdaIn;
+wire [2:0] adr;
+wire [7:0] masterDout;
+wire [7:0] masterDin;
+wire we;
+wire stb;
+wire cyc;
+wire ack;
+wire scl_pad_i;
+wire scl_pad_o;
+wire scl_padoen_o;
+wire sda_pad_i;
+wire sda_pad_o;
+wire sda_padoen_o;
+
+// tb passthrough
+reg tb_readEn;
+reg tb_writeEn;
+reg [15:0] tb_addr;
+reg [15:0] tb_dataIn;
+wire [15:0] tb_dataOut;
+
+initial begin
+$dumpfile("wave.vcd");
+$dumpvars(0, testHarness);
+end
+
+i2cSlave u_i2cSlave(
+ .clk(clk),
+ .rst(rst),
+ .sda(sda),
+ .scl(scl),
+ .tb_readEn(tb_readEn),
+ .tb_writeEn(tb_writeEn),
+ .tb_addr(tb_addr),
+ .tb_dataIn(tb_dataIn),
+ .tb_dataOut(tb_dataOut)
+);
+
+i2c_master_top #(.ARST_LVL(1'b1)) u_i2c_master_top (
+ .wb_clk_i(clk),
+ .wb_rst_i(rst),
+ .arst_i(rst),
+ .wb_adr_i(adr),
+ .wb_dat_i(masterDout),
+ .wb_dat_o(masterDin),
+ .wb_we_i(we),
+ .wb_stb_i(stb),
+ .wb_cyc_i(cyc),
+ .wb_ack_o(ack),
+ .wb_inta_o(),
+ .scl_pad_i(scl_pad_i),
+ .scl_pad_o(scl_pad_o),
+ .scl_padoen_o(scl_padoen_o),
+ .sda_pad_i(sda_pad_i),
+ .sda_pad_o(sda_pad_o),
+ .sda_padoen_o(sda_padoen_o)
+);
+
+wb_master_model #(.dwidth(8), .awidth(3)) u_wb_master_model (
+ .clk(clk),
+ .rst(rst),
+ .adr(adr),
+ .din(masterDin),
+ .dout(masterDout),
+ .cyc(cyc),
+ .stb(stb),
+ .we(we),
+ .sel(),
+ .ack(ack),
+ .err(1'b0),
+ .rty(1'b0)
+);
+
+assign sda = (sda_padoen_o == 1'b0) ? sda_pad_o : 1'bz;
+assign sda_pad_i = sda;
+pullup(sda);
+
+assign scl = (scl_padoen_o == 1'b0) ? scl_pad_o : 1'bz;
+assign scl_pad_i = scl;
+pullup(scl);
+
+
+// ****************************** Clock section ******************************
+//approx 48MHz clock
+`define CLK_HALF_PERIOD 10
+always begin
+ #`CLK_HALF_PERIOD clk <= 1'b0;
+ #`CLK_HALF_PERIOD clk <= 1'b1;
+end
+
+
+// ****************************** reset ******************************
+task reset;
+begin
+ rst <= 1'b1;
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ rst <= 1'b0;
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+end
+endtask
+
+endmodule
diff --git a/i2c_slave_opencores/doc/Philips_I2C_spec.pdf b/i2c_slave_opencores/doc/Philips_I2C_spec.pdf
new file mode 100644
index 0000000..84424c9
Binary files /dev/null and b/i2c_slave_opencores/doc/Philips_I2C_spec.pdf differ
diff --git a/i2c_slave_opencores/doc/i2cSlave_FSM.pdf b/i2c_slave_opencores/doc/i2cSlave_FSM.pdf
new file mode 100644
index 0000000..f9b88fc
Binary files /dev/null and b/i2c_slave_opencores/doc/i2cSlave_FSM.pdf differ
diff --git a/i2c_slave_opencores/doc/i2cSlave_IPCore_Specification.pdf b/i2c_slave_opencores/doc/i2cSlave_IPCore_Specification.pdf
new file mode 100644
index 0000000..28cbafc
Binary files /dev/null and b/i2c_slave_opencores/doc/i2cSlave_IPCore_Specification.pdf differ
diff --git a/i2c_slave_opencores/doc/i2c_master_specs.pdf b/i2c_slave_opencores/doc/i2c_master_specs.pdf
new file mode 100644
index 0000000..9476f10
Binary files /dev/null and b/i2c_slave_opencores/doc/i2c_master_specs.pdf differ
diff --git a/i2c_slave_opencores/doc/src/i2cSlave_IPCore_Specification.sxw b/i2c_slave_opencores/doc/src/i2cSlave_IPCore_Specification.sxw
new file mode 100644
index 0000000..f1d0c0a
Binary files /dev/null and b/i2c_slave_opencores/doc/src/i2cSlave_IPCore_Specification.sxw differ
diff --git a/i2c_slave_opencores/model/i2c_master_bit_ctrl.v b/i2c_slave_opencores/model/i2c_master_bit_ctrl.v
new file mode 100644
index 0000000..ccac6d1
--- /dev/null
+++ b/i2c_slave_opencores/model/i2c_master_bit_ctrl.v
@@ -0,0 +1,538 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE rev.B2 compliant I2C Master bit-controller ////
+//// ////
+//// ////
+//// Author: Richard Herveille ////
+//// richard@asics.ws ////
+//// www.asics.ws ////
+//// ////
+//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2001 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.v,v 1.1 2008-11-08 13:15:10 sfielding Exp $
+//
+// $Date: 2008-11-08 13:15:10 $
+// $Revision: 1.1 $
+// $Author: sfielding $
+// $Locker: $
+// $State: Exp $
+//
+// Change History:
+// $Log: not supported by cvs2svn $
+// Revision 1.12 2006/09/04 09:08:13 rherveille
+// fixed short scl high pulse after clock stretch
+// fixed slave model not returning correct '(n)ack' signal
+//
+// Revision 1.11 2004/05/07 11:02:26 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 2003/08/09 07:01:33 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.9 2003/03/10 14:26:37 rherveille
+// Fixed cmd_ack generation item (no bug).
+//
+// Revision 1.8 2003/02/05 00:06:10 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.7 2002/12/26 16:05:12 rherveille
+// Small code simplifications
+//
+// Revision 1.6 2002/12/26 15:02:32 rherveille
+// Core is now a Multimaster I2C controller
+//
+// Revision 1.5 2002/11/30 22:24:40 rherveille
+// Cleaned up code
+//
+// Revision 1.4 2002/10/30 18:10:07 rherveille
+// Fixed some reported minor start/stop generation timing issuess.
+//
+// Revision 1.3 2002/06/15 07:37:03 rherveille
+// Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment.
+//
+// Revision 1.2 2001/11/05 11:59:25 rherveille
+// Fixed wb_ack_o generation bug.
+// Fixed bug in the byte_controller statemachine.
+// 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 ~~~~~~~~\______
+// 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 ==X=========X=
+// x | A | B | C | D | i
+//
+//- read SCL ____/~~~~\____
+// SDA XXXX=====XXXX
+// 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
+//
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+`include "i2c_master_defines.v"
+
+module i2c_master_bit_ctrl(
+ clk, rst, nReset,
+ clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout,
+ scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen
+ );
+
+ //
+ // inputs & outputs
+ //
+ input clk;
+ input rst;
+ input nReset;
+ input ena; // core enable signal
+
+ input [15:0] clk_cnt; // clock prescale value
+
+ input [3:0] cmd;
+ output cmd_ack; // command complete acknowledge
+ reg cmd_ack;
+ output busy; // i2c bus busy
+ reg busy;
+ output al; // i2c bus arbitration lost
+ reg al;
+
+ input din;
+ output dout;
+ reg dout;
+
+ // I2C lines
+ input scl_i; // i2c clock line input
+ output scl_o; // i2c clock line output
+ output scl_oen; // i2c clock line output enable (active low)
+ reg scl_oen;
+ input sda_i; // i2c data line input
+ output sda_o; // i2c data line output
+ output sda_oen; // i2c data line output enable (active low)
+ reg sda_oen;
+
+
+ //
+ // variable declarations
+ //
+
+ reg sSCL, sSDA; // synchronized SCL and SDA inputs
+ reg dscl_oen; // delayed scl_oen
+ reg sda_chk; // check SDA output (Multi-master arbitration)
+ reg clk_en; // clock generation signals
+ wire slave_wait;
+// reg [15:0] cnt = clk_cnt; // clock divider counter (simulation)
+ reg [15:0] cnt; // clock divider counter (synthesis)
+
+ // state machine variable
+ reg [16:0] c_state; // synopsys enum_state
+
+ //
+ // module body
+ //
+
+ // whenever the slave is not ready it can delay the cycle by pulling SCL low
+ // delay scl_oen
+ always @(posedge clk)
+ dscl_oen <= #1 scl_oen;
+
+ assign slave_wait = dscl_oen && !sSCL;
+
+
+ // generate clk enable signal
+ always @(posedge clk or negedge nReset)
+ if(~nReset)
+ begin
+ cnt <= #1 16'h0;
+ clk_en <= #1 1'b1;
+ end
+ else if (rst)
+ begin
+ cnt <= #1 16'h0;
+ clk_en <= #1 1'b1;
+ end
+ else if ( ~|cnt || !ena)
+ begin
+ cnt <= #1 clk_cnt;
+ clk_en <= #1 1'b1;
+ end
+ else if (slave_wait)
+ begin
+ cnt <= #1 cnt;
+ clk_en <= #1 1'b0;
+ end
+ else
+ begin
+ cnt <= #1 cnt - 16'h1;
+ clk_en <= #1 1'b0;
+ end
+
+
+ // generate bus status controller
+ reg dSCL, dSDA;
+ reg sta_condition;
+ reg sto_condition;
+
+ // synchronize SCL and SDA inputs
+ // reduce metastability risc
+ always @(posedge clk or negedge nReset)
+ if (~nReset)
+ begin
+ sSCL <= #1 1'b1;
+ sSDA <= #1 1'b1;
+
+ dSCL <= #1 1'b1;
+ dSDA <= #1 1'b1;
+ end
+ else if (rst)
+ begin
+ sSCL <= #1 1'b1;
+ sSDA <= #1 1'b1;
+
+ dSCL <= #1 1'b1;
+ dSDA <= #1 1'b1;
+ end
+ else
+ begin
+ sSCL <= #1 scl_i;
+ sSDA <= #1 sda_i;
+
+ dSCL <= #1 sSCL;
+ dSDA <= #1 sSDA;
+ end
+
+ // detect start condition => detect falling edge on SDA while SCL is high
+ // detect stop condition => detect rising edge on SDA while SCL is high
+ always @(posedge clk or negedge nReset)
+ if (~nReset)
+ begin
+ sta_condition <= #1 1'b0;
+ sto_condition <= #1 1'b0;
+ end
+ else if (rst)
+ begin
+ sta_condition <= #1 1'b0;
+ sto_condition <= #1 1'b0;
+ end
+ else
+ begin
+ sta_condition <= #1 ~sSDA & dSDA & sSCL;
+ sto_condition <= #1 sSDA & ~dSDA & sSCL;
+ end
+
+ // generate i2c bus busy signal
+ always @(posedge clk or negedge nReset)
+ if(!nReset)
+ busy <= #1 1'b0;
+ else if (rst)
+ busy <= #1 1'b0;
+ else
+ busy <= #1 (sta_condition | busy) & ~sto_condition;
+
+ // generate arbitration lost signal
+ // aribitration lost when:
+ // 1) master drives SDA high, but the i2c bus is low
+ // 2) stop detected while not requested
+ reg cmd_stop;
+ always @(posedge clk or negedge nReset)
+ if (~nReset)
+ cmd_stop <= #1 1'b0;
+ else if (rst)
+ cmd_stop <= #1 1'b0;
+ else if (clk_en)
+ cmd_stop <= #1 cmd == `I2C_CMD_STOP;
+
+ always @(posedge clk or negedge nReset)
+ if (~nReset)
+ al <= #1 1'b0;
+ else if (rst)
+ al <= #1 1'b0;
+ else
+ al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop);
+
+
+ // generate dout signal (store SDA on rising edge of SCL)
+ always @(posedge clk)
+ if(sSCL & ~dSCL)
+ dout <= #1 sSDA;
+
+ // generate statemachine
+
+ // nxt_state decoder
+ parameter [16:0] idle = 17'b0_0000_0000_0000_0000;
+ parameter [16:0] start_a = 17'b0_0000_0000_0000_0001;
+ parameter [16:0] start_b = 17'b0_0000_0000_0000_0010;
+ parameter [16:0] start_c = 17'b0_0000_0000_0000_0100;
+ parameter [16:0] start_d = 17'b0_0000_0000_0000_1000;
+ parameter [16:0] start_e = 17'b0_0000_0000_0001_0000;
+ parameter [16:0] stop_a = 17'b0_0000_0000_0010_0000;
+ parameter [16:0] stop_b = 17'b0_0000_0000_0100_0000;
+ parameter [16:0] stop_c = 17'b0_0000_0000_1000_0000;
+ parameter [16:0] stop_d = 17'b0_0000_0001_0000_0000;
+ parameter [16:0] rd_a = 17'b0_0000_0010_0000_0000;
+ parameter [16:0] rd_b = 17'b0_0000_0100_0000_0000;
+ parameter [16:0] rd_c = 17'b0_0000_1000_0000_0000;
+ parameter [16:0] rd_d = 17'b0_0001_0000_0000_0000;
+ parameter [16:0] wr_a = 17'b0_0010_0000_0000_0000;
+ parameter [16:0] wr_b = 17'b0_0100_0000_0000_0000;
+ parameter [16:0] wr_c = 17'b0_1000_0000_0000_0000;
+ parameter [16:0] wr_d = 17'b1_0000_0000_0000_0000;
+
+ always @(posedge clk or negedge nReset)
+ if (!nReset)
+ begin
+ c_state <= #1 idle;
+ cmd_ack <= #1 1'b0;
+ scl_oen <= #1 1'b1;
+ sda_oen <= #1 1'b1;
+ sda_chk <= #1 1'b0;
+ end
+ else if (rst | al)
+ begin
+ c_state <= #1 idle;
+ cmd_ack <= #1 1'b0;
+ scl_oen <= #1 1'b1;
+ sda_oen <= #1 1'b1;
+ sda_chk <= #1 1'b0;
+ end
+ else
+ begin
+ cmd_ack <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle
+
+ if (clk_en)
+ case (c_state) // synopsys full_case parallel_case
+ // idle state
+ idle:
+ begin
+ case (cmd) // synopsys full_case parallel_case
+ `I2C_CMD_START:
+ c_state <= #1 start_a;
+
+ `I2C_CMD_STOP:
+ c_state <= #1 stop_a;
+
+ `I2C_CMD_WRITE:
+ c_state <= #1 wr_a;
+
+ `I2C_CMD_READ:
+ c_state <= #1 rd_a;
+
+ default:
+ c_state <= #1 idle;
+ endcase
+
+ scl_oen <= #1 scl_oen; // keep SCL in same state
+ sda_oen <= #1 sda_oen; // keep SDA in same state
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ // start
+ start_a:
+ begin
+ c_state <= #1 start_b;
+ scl_oen <= #1 scl_oen; // keep SCL in same state
+ sda_oen <= #1 1'b1; // set SDA high
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ start_b:
+ begin
+ c_state <= #1 start_c;
+ scl_oen <= #1 1'b1; // set SCL high
+ sda_oen <= #1 1'b1; // keep SDA high
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ start_c:
+ begin
+ c_state <= #1 start_d;
+ scl_oen <= #1 1'b1; // keep SCL high
+ sda_oen <= #1 1'b0; // set SDA low
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ start_d:
+ begin
+ c_state <= #1 start_e;
+ scl_oen <= #1 1'b1; // keep SCL high
+ sda_oen <= #1 1'b0; // keep SDA low
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ start_e:
+ begin
+ c_state <= #1 idle;
+ cmd_ack <= #1 1'b1;
+ scl_oen <= #1 1'b0; // set SCL low
+ sda_oen <= #1 1'b0; // keep SDA low
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ // stop
+ stop_a:
+ begin
+ c_state <= #1 stop_b;
+ scl_oen <= #1 1'b0; // keep SCL low
+ sda_oen <= #1 1'b0; // set SDA low
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ stop_b:
+ begin
+ c_state <= #1 stop_c;
+ scl_oen <= #1 1'b1; // set SCL high
+ sda_oen <= #1 1'b0; // keep SDA low
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ stop_c:
+ begin
+ c_state <= #1 stop_d;
+ scl_oen <= #1 1'b1; // keep SCL high
+ sda_oen <= #1 1'b0; // keep SDA low
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ stop_d:
+ begin
+ c_state <= #1 idle;
+ cmd_ack <= #1 1'b1;
+ scl_oen <= #1 1'b1; // keep SCL high
+ sda_oen <= #1 1'b1; // set SDA high
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ // read
+ rd_a:
+ begin
+ c_state <= #1 rd_b;
+ scl_oen <= #1 1'b0; // keep SCL low
+ sda_oen <= #1 1'b1; // tri-state SDA
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ rd_b:
+ begin
+ c_state <= #1 rd_c;
+ scl_oen <= #1 1'b1; // set SCL high
+ sda_oen <= #1 1'b1; // keep SDA tri-stated
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ rd_c:
+ begin
+ c_state <= #1 rd_d;
+ scl_oen <= #1 1'b1; // keep SCL high
+ sda_oen <= #1 1'b1; // keep SDA tri-stated
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ rd_d:
+ begin
+ c_state <= #1 idle;
+ cmd_ack <= #1 1'b1;
+ scl_oen <= #1 1'b0; // set SCL low
+ sda_oen <= #1 1'b1; // keep SDA tri-stated
+ sda_chk <= #1 1'b0; // don't check SDA output
+ end
+
+ // write
+ wr_a:
+ begin
+ c_state <= #1 wr_b;
+ scl_oen <= #1 1'b0; // keep SCL low
+ sda_oen <= #1 din; // set SDA
+ sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
+ end
+
+ wr_b:
+ begin
+ c_state <= #1 wr_c;
+ scl_oen <= #1 1'b1; // set SCL high
+ sda_oen <= #1 din; // keep SDA
+ sda_chk <= #1 1'b1; // check SDA output
+ end
+
+ wr_c:
+ begin
+ c_state <= #1 wr_d;
+ scl_oen <= #1 1'b1; // keep SCL high
+ sda_oen <= #1 din;
+ sda_chk <= #1 1'b1; // check SDA output
+ end
+
+ wr_d:
+ begin
+ c_state <= #1 idle;
+ cmd_ack <= #1 1'b1;
+ scl_oen <= #1 1'b0; // set SCL low
+ sda_oen <= #1 din;
+ sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
+ end
+
+ endcase
+ end
+
+
+ // assign scl and sda output (always gnd)
+ assign scl_o = 1'b0;
+ assign sda_o = 1'b0;
+
+endmodule
diff --git a/i2c_slave_opencores/model/i2c_master_byte_ctrl.v b/i2c_slave_opencores/model/i2c_master_byte_ctrl.v
new file mode 100644
index 0000000..0cb1a33
--- /dev/null
+++ b/i2c_slave_opencores/model/i2c_master_byte_ctrl.v
@@ -0,0 +1,344 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE rev.B2 compliant I2C Master byte-controller ////
+//// ////
+//// ////
+//// Author: Richard Herveille ////
+//// richard@asics.ws ////
+//// www.asics.ws ////
+//// ////
+//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2001 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.v,v 1.1 2008-11-08 13:15:10 sfielding Exp $
+//
+// $Date: 2008-11-08 13:15:10 $
+// $Revision: 1.1 $
+// $Author: sfielding $
+// $Locker: $
+// $State: Exp $
+//
+// Change History:
+// $Log: not supported by cvs2svn $
+// Revision 1.7 2004/02/18 11:40:46 rherveille
+// Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command.
+//
+// Revision 1.6 2003/08/09 07:01:33 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.5 2002/12/26 15:02:32 rherveille
+// Core is now a Multimaster I2C controller
+//
+// Revision 1.4 2002/11/30 22:24:40 rherveille
+// Cleaned up code
+//
+// Revision 1.3 2001/11/05 11:59:25 rherveille
+// Fixed wb_ack_o generation bug.
+// Fixed bug in the byte_controller statemachine.
+// Added headers.
+//
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+`include "i2c_master_defines.v"
+
+module i2c_master_byte_ctrl (
+ clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din,
+ cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen );
+
+ //
+ // inputs & outputs
+ //
+ input clk; // master clock
+ input rst; // synchronous active high reset
+ input nReset; // asynchronous active low reset
+ input ena; // core enable signal
+
+ input [15:0] clk_cnt; // 4x SCL
+
+ // control inputs
+ input start;
+ input stop;
+ input read;
+ input write;
+ input ack_in;
+ input [7:0] din;
+
+ // status outputs
+ output cmd_ack;
+ reg cmd_ack;
+ output ack_out;
+ reg ack_out;
+ output i2c_busy;
+ output i2c_al;
+ output [7:0] dout;
+
+ // I2C signals
+ input scl_i;
+ output scl_o;
+ output scl_oen;
+ input sda_i;
+ output sda_o;
+ output sda_oen;
+
+
+ //
+ // Variable declarations
+ //
+
+ // statemachine
+ parameter [4:0] ST_IDLE = 5'b0_0000;
+ parameter [4:0] ST_START = 5'b0_0001;
+ parameter [4:0] ST_READ = 5'b0_0010;
+ parameter [4:0] ST_WRITE = 5'b0_0100;
+ parameter [4:0] ST_ACK = 5'b0_1000;
+ parameter [4:0] ST_STOP = 5'b1_0000;
+
+ // signals for bit_controller
+ reg [3:0] core_cmd;
+ reg core_txd;
+ wire core_ack, core_rxd;
+
+ // signals for shift register
+ reg [7:0] sr; //8bit shift register
+ reg shift, ld;
+
+ // signals for state machine
+ wire go;
+ reg [2:0] dcnt;
+ wire cnt_done;
+
+ //
+ // Module body
+ //
+
+ // hookup bit_controller
+ i2c_master_bit_ctrl bit_controller (
+ .clk ( clk ),
+ .rst ( rst ),
+ .nReset ( nReset ),
+ .ena ( ena ),
+ .clk_cnt ( clk_cnt ),
+ .cmd ( core_cmd ),
+ .cmd_ack ( core_ack ),
+ .busy ( i2c_busy ),
+ .al ( i2c_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 )
+ );
+
+ // generate go-signal
+ assign go = (read | write | stop) & ~cmd_ack;
+
+ // assign dout output to shift-register
+ assign dout = sr;
+
+ // generate shift register
+ always @(posedge clk or negedge nReset)
+ if (!nReset)
+ sr <= #1 8'h0;
+ else if (rst)
+ sr <= #1 8'h0;
+ else if (ld)
+ sr <= #1 din;
+ else if (shift)
+ sr <= #1 {sr[6:0], core_rxd};
+
+ // generate counter
+ always @(posedge clk or negedge nReset)
+ if (!nReset)
+ dcnt <= #1 3'h0;
+ else if (rst)
+ dcnt <= #1 3'h0;
+ else if (ld)
+ dcnt <= #1 3'h7;
+ else if (shift)
+ dcnt <= #1 dcnt - 3'h1;
+
+ assign cnt_done = ~(|dcnt);
+
+ //
+ // state machine
+ //
+ reg [4:0] c_state; // synopsis enum_state
+
+ always @(posedge clk or negedge nReset)
+ if (!nReset)
+ begin
+ core_cmd <= #1 `I2C_CMD_NOP;
+ core_txd <= #1 1'b0;
+ shift <= #1 1'b0;
+ ld <= #1 1'b0;
+ cmd_ack <= #1 1'b0;
+ c_state <= #1 ST_IDLE;
+ ack_out <= #1 1'b0;
+ end
+ else if (rst | i2c_al)
+ begin
+ core_cmd <= #1 `I2C_CMD_NOP;
+ core_txd <= #1 1'b0;
+ shift <= #1 1'b0;
+ ld <= #1 1'b0;
+ cmd_ack <= #1 1'b0;
+ c_state <= #1 ST_IDLE;
+ ack_out <= #1 1'b0;
+ end
+ else
+ begin
+ // initially reset all signals
+ core_txd <= #1 sr[7];
+ shift <= #1 1'b0;
+ ld <= #1 1'b0;
+ cmd_ack <= #1 1'b0;
+
+ case (c_state) // synopsys full_case parallel_case
+ ST_IDLE:
+ if (go)
+ begin
+ if (start)
+ begin
+ c_state <= #1 ST_START;
+ core_cmd <= #1 `I2C_CMD_START;
+ end
+ else if (read)
+ begin
+ c_state <= #1 ST_READ;
+ core_cmd <= #1 `I2C_CMD_READ;
+ end
+ else if (write)
+ begin
+ c_state <= #1 ST_WRITE;
+ core_cmd <= #1 `I2C_CMD_WRITE;
+ end
+ else // stop
+ begin
+ c_state <= #1 ST_STOP;
+ core_cmd <= #1 `I2C_CMD_STOP;
+ end
+
+ ld <= #1 1'b1;
+ end
+
+ ST_START:
+ if (core_ack)
+ begin
+ if (read)
+ begin
+ c_state <= #1 ST_READ;
+ core_cmd <= #1 `I2C_CMD_READ;
+ end
+ else
+ begin
+ c_state <= #1 ST_WRITE;
+ core_cmd <= #1 `I2C_CMD_WRITE;
+ end
+
+ ld <= #1 1'b1;
+ end
+
+ ST_WRITE:
+ if (core_ack)
+ if (cnt_done)
+ begin
+ c_state <= #1 ST_ACK;
+ core_cmd <= #1 `I2C_CMD_READ;
+ end
+ else
+ begin
+ c_state <= #1 ST_WRITE; // stay in same state
+ core_cmd <= #1 `I2C_CMD_WRITE; // write next bit
+ shift <= #1 1'b1;
+ end
+
+ ST_READ:
+ if (core_ack)
+ begin
+ if (cnt_done)
+ begin
+ c_state <= #1 ST_ACK;
+ core_cmd <= #1 `I2C_CMD_WRITE;
+ end
+ else
+ begin
+ c_state <= #1 ST_READ; // stay in same state
+ core_cmd <= #1 `I2C_CMD_READ; // read next bit
+ end
+
+ shift <= #1 1'b1;
+ core_txd <= #1 ack_in;
+ end
+
+ ST_ACK:
+ if (core_ack)
+ begin
+ if (stop)
+ begin
+ c_state <= #1 ST_STOP;
+ core_cmd <= #1 `I2C_CMD_STOP;
+ end
+ else
+ begin
+ c_state <= #1 ST_IDLE;
+ core_cmd <= #1 `I2C_CMD_NOP;
+
+ // generate command acknowledge signal
+ cmd_ack <= #1 1'b1;
+ end
+
+ // assign ack_out output to bit_controller_rxd (contains last received bit)
+ ack_out <= #1 core_rxd;
+
+ core_txd <= #1 1'b1;
+ end
+ else
+ core_txd <= #1 ack_in;
+
+ ST_STOP:
+ if (core_ack)
+ begin
+ c_state <= #1 ST_IDLE;
+ core_cmd <= #1 `I2C_CMD_NOP;
+
+ // generate command acknowledge signal
+ cmd_ack <= #1 1'b1;
+ end
+
+ endcase
+ end
+endmodule
diff --git a/i2c_slave_opencores/model/i2c_master_defines.v b/i2c_slave_opencores/model/i2c_master_defines.v
new file mode 100644
index 0000000..ff0efa3
--- /dev/null
+++ b/i2c_slave_opencores/model/i2c_master_defines.v
@@ -0,0 +1,64 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE rev.B2 compliant I2C Master controller defines ////
+//// ////
+//// ////
+//// Author: Richard Herveille ////
+//// richard@asics.ws ////
+//// www.asics.ws ////
+//// ////
+//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2001 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_defines.v,v 1.1 2008-11-08 13:15:10 sfielding Exp $
+//
+// $Date: 2008-11-08 13:15:10 $
+// $Revision: 1.1 $
+// $Author: sfielding $
+// $Locker: $
+// $State: Exp $
+//
+// Change History:
+// $Log: not supported by cvs2svn $
+// Revision 1.3 2001/11/05 11:59:25 rherveille
+// Fixed wb_ack_o generation bug.
+// Fixed bug in the byte_controller statemachine.
+// Added headers.
+//
+
+
+// I2C registers wishbone addresses
+
+// bitcontroller states
+`define I2C_CMD_NOP 4'b0000
+`define I2C_CMD_START 4'b0001
+`define I2C_CMD_STOP 4'b0010
+`define I2C_CMD_WRITE 4'b0100
+`define I2C_CMD_READ 4'b1000
diff --git a/i2c_slave_opencores/model/i2c_master_top.v b/i2c_slave_opencores/model/i2c_master_top.v
new file mode 100644
index 0000000..aa823cb
--- /dev/null
+++ b/i2c_slave_opencores/model/i2c_master_top.v
@@ -0,0 +1,301 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE revB.2 compliant I2C Master controller Top-level ////
+//// ////
+//// ////
+//// Author: Richard Herveille ////
+//// richard@asics.ws ////
+//// www.asics.ws ////
+//// ////
+//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2001 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_top.v,v 1.1 2008-11-08 13:15:10 sfielding Exp $
+//
+// $Date: 2008-11-08 13:15:10 $
+// $Revision: 1.1 $
+// $Author: sfielding $
+// $Locker: $
+// $State: Exp $
+//
+// Change History:
+// $Log: not supported by cvs2svn $
+// Revision 1.11 2005/02/27 09:26:24 rherveille
+// Fixed register overwrite issue.
+// Removed full_case pragma, replaced it by a default statement.
+//
+// Revision 1.10 2003/09/01 10:34:38 rherveille
+// Fix a blocking vs. non-blocking error in the wb_dat output mux.
+//
+// Revision 1.9 2003/01/09 16:44:45 rherveille
+// Fixed a bug in the Command Register declaration.
+//
+// Revision 1.8 2002/12/26 16:05:12 rherveille
+// Small code simplifications
+//
+// Revision 1.7 2002/12/26 15:02:32 rherveille
+// Core is now a Multimaster I2C controller
+//
+// Revision 1.6 2002/11/30 22:24:40 rherveille
+// Cleaned up code
+//
+// Revision 1.5 2001/11/10 10:52:55 rherveille
+// Changed PRER reset value from 0x0000 to 0xffff, conform specs.
+//
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+`include "i2c_master_defines.v"
+
+module i2c_master_top(
+ wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o,
+ wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o,
+ scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o );
+
+ // parameters
+ parameter ARST_LVL = 1'b0; // asynchronous reset level
+
+ //
+ // inputs & outputs
+ //
+
+ // wishbone signals
+ input wb_clk_i; // master clock input
+ input wb_rst_i; // synchronous active high reset
+ input arst_i; // asynchronous reset
+ input [2:0] wb_adr_i; // lower address bits
+ input [7:0] wb_dat_i; // databus input
+ output [7:0] wb_dat_o; // databus output
+ input wb_we_i; // write enable input
+ input wb_stb_i; // stobe/core select signal
+ input wb_cyc_i; // valid bus cycle input
+ output wb_ack_o; // bus cycle acknowledge output
+ output wb_inta_o; // interrupt request signal output
+
+ reg [7:0] wb_dat_o;
+ reg wb_ack_o;
+ reg wb_inta_o;
+
+ // I2C signals
+ // i2c clock line
+ input scl_pad_i; // SCL-line input
+ output scl_pad_o; // SCL-line output (always 1'b0)
+ output scl_padoen_o; // SCL-line output enable (active low)
+
+ // i2c data line
+ input sda_pad_i; // SDA-line input
+ output sda_pad_o; // SDA-line output (always 1'b0)
+ output sda_padoen_o; // SDA-line output enable (active low)
+
+
+ //
+ // variable declarations
+ //
+
+ // registers
+ reg [15:0] prer; // clock prescale register
+ reg [ 7:0] ctr; // control register
+ reg [ 7:0] txr; // transmit register
+ wire [ 7:0] rxr; // receive register
+ reg [ 7:0] cr; // command register
+ wire [ 7:0] sr; // status register
+
+ // done signal: command completed, clear command register
+ wire done;
+
+ // core enable signal
+ wire core_en;
+ wire ien;
+
+ // status register signals
+ wire irxack;
+ reg rxack; // received aknowledge from slave
+ reg tip; // transfer in progress
+ reg irq_flag; // interrupt pending flag
+ wire i2c_busy; // bus busy (start signal detected)
+ wire i2c_al; // i2c bus arbitration lost
+ reg al; // status register arbitration lost bit
+
+ //
+ // module body
+ //
+
+ // generate internal reset
+ wire rst_i = arst_i ^ ARST_LVL;
+
+ // generate wishbone signals
+ wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i;
+
+ // generate acknowledge output signal
+ always @(posedge wb_clk_i)
+ wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored
+
+ // assign DAT_O
+ always @(posedge wb_clk_i)
+ begin
+ case (wb_adr_i) // synopsis parallel_case
+ 3'b000: wb_dat_o <= #1 prer[ 7:0];
+ 3'b001: wb_dat_o <= #1 prer[15:8];
+ 3'b010: wb_dat_o <= #1 ctr;
+ 3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr)
+ 3'b100: wb_dat_o <= #1 sr; // write is command register (cr)
+ 3'b101: wb_dat_o <= #1 txr;
+ 3'b110: wb_dat_o <= #1 cr;
+ 3'b111: wb_dat_o <= #1 0; // reserved
+ endcase
+ end
+
+ // generate registers
+ always @(posedge wb_clk_i or negedge rst_i)
+ if (!rst_i)
+ begin
+ prer <= #1 16'hffff;
+ ctr <= #1 8'h0;
+ txr <= #1 8'h0;
+ end
+ else if (wb_rst_i)
+ begin
+ prer <= #1 16'hffff;
+ ctr <= #1 8'h0;
+ txr <= #1 8'h0;
+ end
+ else
+ if (wb_wacc)
+ case (wb_adr_i) // synopsis parallel_case
+ 3'b000 : prer [ 7:0] <= #1 wb_dat_i;
+ 3'b001 : prer [15:8] <= #1 wb_dat_i;
+ 3'b010 : ctr <= #1 wb_dat_i;
+ 3'b011 : txr <= #1 wb_dat_i;
+ default: ;
+ endcase
+
+ // generate command register (special case)
+ always @(posedge wb_clk_i or negedge rst_i)
+ if (~rst_i)
+ cr <= #1 8'h0;
+ else if (wb_rst_i)
+ cr <= #1 8'h0;
+ else if (wb_wacc)
+ begin
+ if (core_en & (wb_adr_i == 3'b100) )
+ cr <= #1 wb_dat_i;
+ end
+ else
+ begin
+ if (done | i2c_al)
+ cr[7:4] <= #1 4'h0; // clear command bits when done
+ // or when aribitration lost
+ cr[2:1] <= #1 2'b0; // reserved bits
+ cr[0] <= #1 2'b0; // clear IRQ_ACK bit
+ end
+
+
+ // decode command register
+ wire sta = cr[7];
+ wire sto = cr[6];
+ wire rd = cr[5];
+ wire wr = cr[4];
+ wire ack = cr[3];
+ wire iack = cr[0];
+
+ // decode control register
+ assign core_en = ctr[7];
+ assign ien = ctr[6];
+
+ // hookup byte controller block
+ i2c_master_byte_ctrl byte_controller (
+ .clk ( wb_clk_i ),
+ .rst ( wb_rst_i ),
+ .nReset ( rst_i ),
+ .ena ( core_en ),
+ .clk_cnt ( prer ),
+ .start ( sta ),
+ .stop ( sto ),
+ .read ( rd ),
+ .write ( wr ),
+ .ack_in ( ack ),
+ .din ( txr ),
+ .cmd_ack ( done ),
+ .ack_out ( irxack ),
+ .dout ( rxr ),
+ .i2c_busy ( i2c_busy ),
+ .i2c_al ( i2c_al ),
+ .scl_i ( scl_pad_i ),
+ .scl_o ( scl_pad_o ),
+ .scl_oen ( scl_padoen_o ),
+ .sda_i ( sda_pad_i ),
+ .sda_o ( sda_pad_o ),
+ .sda_oen ( sda_padoen_o )
+ );
+
+ // status register block + interrupt request signal
+ always @(posedge wb_clk_i or negedge rst_i)
+ if (!rst_i)
+ begin
+ al <= #1 1'b0;
+ rxack <= #1 1'b0;
+ tip <= #1 1'b0;
+ irq_flag <= #1 1'b0;
+ end
+ else if (wb_rst_i)
+ begin
+ al <= #1 1'b0;
+ rxack <= #1 1'b0;
+ tip <= #1 1'b0;
+ irq_flag <= #1 1'b0;
+ end
+ else
+ begin
+ al <= #1 i2c_al | (al & ~sta);
+ rxack <= #1 irxack;
+ tip <= #1 (rd | wr);
+ irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated
+ end
+
+ // generate interrupt request signals
+ always @(posedge wb_clk_i or negedge rst_i)
+ if (!rst_i)
+ wb_inta_o <= #1 1'b0;
+ else if (wb_rst_i)
+ wb_inta_o <= #1 1'b0;
+ else
+ wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set)
+
+ // assign status register bits
+ assign sr[7] = rxack;
+ assign sr[6] = i2c_busy;
+ assign sr[5] = al;
+ assign sr[4:2] = 3'h0; // reserved
+ assign sr[1] = tip;
+ assign sr[0] = irq_flag;
+
+endmodule
diff --git a/i2c_slave_opencores/model/wb_master_model.v b/i2c_slave_opencores/model/wb_master_model.v
new file mode 100644
index 0000000..4f32542
--- /dev/null
+++ b/i2c_slave_opencores/model/wb_master_model.v
@@ -0,0 +1,176 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// wb_master_model.v ////
+//// ////
+//// This file is part of the SPI IP core project ////
+//// http://www.opencores.org/projects/spi/ ////
+//// ////
+//// Author(s): ////
+//// - Simon Srot (simons@opencores.org) ////
+//// ////
+//// Based on: ////
+//// - i2c/bench/verilog/wb_master_model.v ////
+//// Copyright (C) 2001 Richard Herveille ////
+//// ////
+//// All additional information is avaliable in the Readme.txt ////
+//// file. ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2002 Authors ////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+`include "timescale.v"
+
+module wb_master_model(clk, rst, adr, din, dout, cyc, stb, we, sel, ack, err, rty);
+
+ parameter dwidth = 32;
+ parameter awidth = 32;
+
+ input clk, rst;
+ output [awidth -1:0] adr;
+ input [dwidth -1:0] din;
+ output [dwidth -1:0] dout;
+ output cyc, stb;
+ output we;
+ output [dwidth/8 -1:0] sel;
+ input ack, err, rty;
+
+ // Internal signals
+ reg [awidth -1:0] adr;
+ reg [dwidth -1:0] dout;
+ reg cyc, stb;
+ reg we;
+ reg [dwidth/8 -1:0] sel;
+
+ reg [dwidth -1:0] q;
+
+ // Memory Logic
+ initial
+ begin
+ adr = {awidth{1'bx}};
+ dout = {dwidth{1'bx}};
+ cyc = 1'b0;
+ stb = 1'bx;
+ we = 1'hx;
+ sel = {dwidth/8{1'bx}};
+ #1;
+ end
+
+ // Wishbone write cycle
+ task wb_write;
+ input delay;
+ integer delay;
+
+ input [awidth -1:0] a;
+ input [dwidth -1:0] d;
+
+ begin
+
+ // wait initial delay
+ repeat(delay) @(posedge clk);
+
+ // assert wishbone signal
+ #1;
+ adr = a;
+ dout = d;
+ cyc = 1'b1;
+ stb = 1'b1;
+ we = 1'b1;
+ sel = {dwidth/8{1'b1}};
+ @(posedge clk);
+
+ // wait for acknowledge from slave
+ while(~ack) @(posedge clk);
+
+ // negate wishbone signals
+ #1;
+ cyc = 1'b0;
+ stb = 1'bx;
+ adr = {awidth{1'bx}};
+ dout = {dwidth{1'bx}};
+ we = 1'hx;
+ sel = {dwidth/8{1'bx}};
+
+ end
+ endtask
+
+ // Wishbone read cycle
+ task wb_read;
+ input delay;
+ integer delay;
+
+ input [awidth -1:0] a;
+ output [dwidth -1:0] d;
+
+ begin
+
+ // wait initial delay
+ repeat(delay) @(posedge clk);
+
+ // assert wishbone signals
+ #1;
+ adr = a;
+ dout = {dwidth{1'bx}};
+ cyc = 1'b1;
+ stb = 1'b1;
+ we = 1'b0;
+ sel = {dwidth/8{1'b1}};
+ @(posedge clk);
+
+ // wait for acknowledge from slave
+ while(~ack) @(posedge clk);
+
+ // negate wishbone signals
+ #1;
+ cyc = 1'b0;
+ stb = 1'bx;
+ adr = {awidth{1'bx}};
+ dout = {dwidth{1'bx}};
+ we = 1'hx;
+ sel = {dwidth/8{1'bx}};
+ d = din;
+
+ end
+ endtask
+
+ // Wishbone compare cycle (read data from location and compare with expected data)
+ task wb_cmp;
+ input delay;
+ integer delay;
+
+ input [awidth -1:0] a;
+ input [dwidth -1:0] d_exp;
+
+ begin
+ wb_read (delay, a, q);
+
+ if (d_exp !== q)
+ $display("Data compare error. Received %h, expected %h at time %t", q, d_exp, $time);
+ end
+ endtask
+
+endmodule
+
diff --git a/i2c_slave_opencores/rtl/i2cSlave.v b/i2c_slave_opencores/rtl/i2cSlave.v
new file mode 100644
index 0000000..a5fff46
--- /dev/null
+++ b/i2c_slave_opencores/rtl/i2cSlave.v
@@ -0,0 +1,199 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// i2cSlave.v ////
+//// ////
+//// This file is part of the i2cSlave opencores effort.
+//// ////
+//// ////
+//// Module Description: ////
+//// You will need to modify this file to implement your
+//// interface.
+//// ////
+//// To Do: ////
+////
+//// ////
+//// Author(s): ////
+//// - Steve Fielding, sfielding@base2designs.com ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Steve Fielding 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+`include "i2cSlave_define.v"
+
+
+module i2cSlave (
+ clk,
+ rst,
+ sda,
+ scl,
+ tb_readEn,
+ tb_writeEn,
+ tb_addr,
+ tb_dataIn,
+ tb_dataOut
+);
+
+input clk;
+input rst;
+inout sda;
+input scl;
+
+// tb interface
+input tb_readEn;
+input tb_writeEn;
+input [15:0] tb_addr;
+input [15:0] tb_dataIn;
+output [15:0] tb_dataOut;
+
+// local wires and regs
+reg sdaDeb;
+reg sclDeb;
+reg [`DEB_I2C_LEN-1:0] sdaPipe;
+reg [`DEB_I2C_LEN-1:0] sclPipe;
+
+reg [`SCL_DEL_LEN-1:0] sclDelayed;
+reg [`SDA_DEL_LEN-1:0] sdaDelayed;
+reg [1:0] startStopDetState;
+wire clearStartStopDet;
+wire sdaOut;
+wire sdaIn;
+wire [15:0] regAddr;
+wire [7:0] dataToRegIF;
+wire writeEn;
+wire [7:0] dataFromRegIF;
+reg [1:0] rstPipe;
+wire rstSyncToClk;
+reg startEdgeDet;
+
+assign sda = (sdaOut == 1'b0) ? 1'b0 : 1'bz;
+assign sdaIn = sda;
+
+// sync rst rsing edge to clk
+always @(posedge clk) begin
+ if (rst == 1'b1)
+ rstPipe <= 2'b11;
+ else
+ rstPipe <= {rstPipe[0], 1'b0};
+end
+
+assign rstSyncToClk = rstPipe[1];
+
+// debounce sda and scl
+always @(posedge clk) begin
+ if (rstSyncToClk == 1'b1) begin
+ sdaPipe <= {`DEB_I2C_LEN{1'b1}};
+ sdaDeb <= 1'b1;
+ sclPipe <= {`DEB_I2C_LEN{1'b1}};
+ sclDeb <= 1'b1;
+ end
+ else begin
+ sdaPipe <= {sdaPipe[`DEB_I2C_LEN-2:0], sdaIn};
+ sclPipe <= {sclPipe[`DEB_I2C_LEN-2:0], scl};
+ if (&sclPipe[`DEB_I2C_LEN-1:1] == 1'b1)
+ sclDeb <= 1'b1;
+ else if (|sclPipe[`DEB_I2C_LEN-1:1] == 1'b0)
+ sclDeb <= 1'b0;
+ if (&sdaPipe[`DEB_I2C_LEN-1:1] == 1'b1)
+ sdaDeb <= 1'b1;
+ else if (|sdaPipe[`DEB_I2C_LEN-1:1] == 1'b0)
+ sdaDeb <= 1'b0;
+ end
+end
+
+
+// delay scl and sda
+// sclDelayed is used as a delayed sampling clock
+// sdaDelayed is only used for start stop detection
+// Because sda hold time from scl falling is 0nS
+// sda must be delayed with respect to scl to avoid incorrect
+// detection of start/stop at scl falling edge.
+always @(posedge clk) begin
+ if (rstSyncToClk == 1'b1) begin
+ sclDelayed <= {`SCL_DEL_LEN{1'b1}};
+ sdaDelayed <= {`SDA_DEL_LEN{1'b1}};
+ end
+ else begin
+ sclDelayed <= {sclDelayed[`SCL_DEL_LEN-2:0], sclDeb};
+ sdaDelayed <= {sdaDelayed[`SDA_DEL_LEN-2:0], sdaDeb};
+ end
+end
+
+// start stop detection
+always @(posedge clk) begin
+ if (rstSyncToClk == 1'b1) begin
+ startStopDetState <= `NULL_DET;
+ startEdgeDet <= 1'b0;
+ end
+ else begin
+ if (sclDeb == 1'b1 && sdaDelayed[`SDA_DEL_LEN-2] == 1'b0 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b1)
+ startEdgeDet <= 1'b1;
+ else
+ startEdgeDet <= 1'b0;
+ if (clearStartStopDet == 1'b1)
+ startStopDetState <= `NULL_DET;
+ else if (sclDeb == 1'b1) begin
+ if (sdaDelayed[`SDA_DEL_LEN-2] == 1'b1 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b0)
+ startStopDetState <= `STOP_DET;
+ else if (sdaDelayed[`SDA_DEL_LEN-2] == 1'b0 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b1)
+ startStopDetState <= `START_DET;
+ end
+ end
+end
+
+
+registerInterface u_registerInterface(
+ .clk(clk),
+ .addr(regAddr),
+ .dataIn(dataToRegIF),
+ .writeEn(writeEn),
+ .dataOut(dataFromRegIF),
+ .tb_readEn(tb_readEn),
+ .tb_writeEn(tb_writeEn),
+ .tb_addr(tb_addr),
+ .tb_dataIn(tb_dataIn),
+ .tb_dataOut(tb_dataOut)
+);
+
+serialInterface u_serialInterface (
+ .clk(clk),
+ .rst(rstSyncToClk | startEdgeDet),
+ .dataIn(dataFromRegIF),
+ .dataOut(dataToRegIF),
+ .writeEn(writeEn),
+ .regAddr(regAddr),
+ .scl(sclDelayed[`SCL_DEL_LEN-1]),
+ .sdaIn(sdaDeb),
+ .sdaOut(sdaOut),
+ .startStopDetState(startStopDetState),
+ .clearStartStopDet(clearStartStopDet)
+);
+
+
+endmodule
+
+
+
diff --git a/i2c_slave_opencores/rtl/i2cSlave_define.v b/i2c_slave_opencores/rtl/i2cSlave_define.v
new file mode 100644
index 0000000..937ffcc
--- /dev/null
+++ b/i2c_slave_opencores/rtl/i2cSlave_define.v
@@ -0,0 +1,68 @@
+// ----------------------- i2cSlave_define.v --------------------
+
+// stream states
+`define STREAM_IDLE 2'b00
+`define STREAM_READ 2'b01
+`define STREAM_WRITE_ADDR 2'b10
+`define STREAM_WRITE_DATA 2'b11
+
+// start stop detection states
+`define NULL_DET 2'b00
+`define START_DET 2'b01
+`define STOP_DET 2'b10
+
+// i2c ack and nak
+`define I2C_NAK 1'b1
+`define I2C_ACK 1'b0
+
+// ----------------------------------------------------------------
+// ------------- modify constants below this line -----------------
+// ----------------------------------------------------------------
+
+// i2c device address
+`define I2C_ADDRESS 7'h3c
+
+// System clock frequency in MHz
+// If you are using a clock frequency below 24MHz, then the macro
+// for SDA_DEL_LEN will result in compile errors for i2cSlave.v
+// you will need to hand tweak the SDA_DEL_LEN constant definition
+`define CLK_FREQ 48
+
+// Debounce SCL and SDA over this many clock ticks
+// The rise time of SCL and SDA can be up to 1000nS (in standard mode)
+// so it is essential to debounce the inputs.
+// The spec requires 0.05V of hysteresis, but in practise
+// simply debouncing the inputs is sufficient
+// I2C spec requires suppresion of spikes of
+// maximum duration 50nS, so this debounce time should be greater than 50nS
+// Also increases data hold time and decreases data setup time
+// during an I2C read operation
+// 10 ticks = 208nS @ 48MHz
+`define DEB_I2C_LEN (10*`CLK_FREQ)/48
+
+// Delay SCL for use as internal sampling clock
+// Using delayed version of SCL to ensure that
+// SDA is stable when it is sampled.
+// Not entirely citical, as according to I2C spec
+// SDA should have a minimum of 100nS of set up time
+// with respect to SCL rising edge. But with the very slow edge
+// speeds used in I2C it is better to err on the side of caution.
+// This delay also has the effect of adding extra hold time to the data
+// with respect to SCL falling edge. I2C spec requires 0nS of data hold time.
+// 10 ticks = 208nS @ 48MHz
+`define SCL_DEL_LEN (10*`CLK_FREQ)/48
+
+// Delay SDA for use in start/stop detection
+// Use delayed SDA during start/stop detection to avoid
+// incorrect detection at SCL falling edge.
+// From I2C spec start/stop setup is 600nS with respect to SCL rising edge
+// and start/stop hold is 600nS wrt SCL falling edge.
+// So it is relatively easy to discriminate start/stop,
+// but data setup time is a minimum of 100nS with respect to SCL rising edge
+// and 0nS hold wrt to SCL falling edge.
+// So the tricky part is providing robust start/stop detection
+// in the presence of regular data transitions.
+// This delay time should be less than 100nS
+// 4 ticks = 83nS @ 48MHz
+`define SDA_DEL_LEN (4*`CLK_FREQ)/48
+
diff --git a/i2c_slave_opencores/rtl/registerInterface.v b/i2c_slave_opencores/rtl/registerInterface.v
new file mode 100644
index 0000000..5bfe19f
--- /dev/null
+++ b/i2c_slave_opencores/rtl/registerInterface.v
@@ -0,0 +1,109 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// registerInterface.v ////
+//// ////
+//// This file is part of the i2cSlave opencores effort.
+//// ////
+//// ////
+//// Module Description: ////
+//// You will need to modify this file to implement your
+//// interface.
+//// Add your control and status bytes/bits to module inputs and outputs,
+//// and also to the I2C read and write process blocks
+//// ////
+//// To Do: ////
+////
+//// ////
+//// Author(s): ////
+//// - Steve Fielding, sfielding@base2designs.com ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Steve Fielding 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+`include "i2cSlave_define.v"
+
+
+module registerInterface (
+ clk,
+ addr,
+ dataIn,
+ writeEn,
+ dataOut,
+ tb_readEn,
+ tb_writeEn,
+ tb_addr,
+ tb_dataIn,
+ tb_dataOut
+);
+
+// i2c interface
+input clk;
+input [15:0] addr;
+input [7:0] dataIn;
+input writeEn;
+output [7:0] dataOut;
+reg [7:0] dataOut;
+
+// speicher
+reg [7:0] memory [16'hffff:0];
+
+// tb interface
+input tb_readEn;
+input tb_writeEn;
+input [15:0] tb_addr;
+input [15:0] tb_dataIn;
+output [15:0] tb_dataOut;
+reg [15:0] tb_dataOut;
+
+// --- TB Read
+always @(posedge tb_readEn) begin
+ tb_dataOut[15:8] <= memory[tb_addr];
+ tb_dataOut[7:0] <= memory[tb_addr + 1'b1];
+end
+
+// --- TB Write
+always @(posedge tb_writeEn) begin
+ memory[tb_addr] <= tb_dataIn[15:8];
+ memory[tb_addr + 1'b1] <= tb_dataIn[7:0];
+end
+
+// --- I2C Read
+always @(posedge clk) begin
+ dataOut <= memory[addr];
+end
+
+// --- I2C Write
+always @(posedge clk) begin
+ if (writeEn == 1'b1) begin
+ memory[addr] <= dataIn;
+ end
+end
+
+endmodule
+
+
+
diff --git a/i2c_slave_opencores/rtl/serialInterface.v b/i2c_slave_opencores/rtl/serialInterface.v
new file mode 100644
index 0000000..4f79092
--- /dev/null
+++ b/i2c_slave_opencores/rtl/serialInterface.v
@@ -0,0 +1,372 @@
+
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// serialInterface.v ////
+//// ////
+//// This file is part of the i2cSlave opencores effort.
+//// ////
+//// ////
+//// Module Description: ////
+//// Perform all serial to parallel, and parallel
+//// to serial conversions. Perform device address matching
+//// Handle arbitrary length I2C reads terminated by NAK
+//// from host, and arbitrary length I2C writes terminated
+//// by STOP from host
+//// The second byte of a I2C write is always interpreted
+//// as a register address, and becomes the base register address
+//// for all read and write transactions.
+//// I2C WRITE: devAddr, regAddr, data[regAddr], data[regAddr+1], ..... data[regAddr+N]
+//// I2C READ: data[regAddr], data[regAddr+1], ..... data[regAddr+N]
+//// Note that when regAddR reaches 255 it will automatically wrap round to 0
+//// ////
+//// To Do: ////
+////
+//// ////
+//// Author(s): ////
+//// - Steve Fielding, sfielding@base2designs.com ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Steve Fielding 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+`include "timescale.v"
+`include "i2cSlave_define.v"
+
+module serialInterface (clearStartStopDet, clk, dataIn, dataOut, regAddr, rst, scl, sdaIn, sdaOut, startStopDetState, writeEn);
+input clk;
+input [7:0]dataIn;
+input rst;
+input scl;
+input sdaIn;
+input [1:0]startStopDetState;
+output clearStartStopDet;
+output [7:0]dataOut;
+output [15:0]regAddr;
+output sdaOut;
+output writeEn;
+
+reg clearStartStopDet, next_clearStartStopDet;
+wire clk;
+wire [7:0]dataIn;
+reg [7:0]dataOut, next_dataOut;
+reg [15:0]regAddr, next_regAddr;
+reg regAddr_hiByte = 1'b0; //high and low byte of regAddr
+wire rst;
+wire scl;
+wire sdaIn;
+reg sdaOut, next_sdaOut;
+wire [1:0]startStopDetState;
+reg writeEn, next_writeEn;
+
+// diagram signals declarations
+reg [2:0]bitCnt, next_bitCnt;
+reg [7:0]rxData, next_rxData;
+reg [1:0]streamSt, next_streamSt;
+reg [7:0]txData, next_txData;
+
+// BINARY ENCODED state machine: SISt
+// State codes definitions:
+`define START 4'b0000
+`define CHK_RD_WR 4'b0001
+`define READ_RD_LOOP 4'b0010
+`define READ_WT_HI 4'b0011
+`define READ_CHK_LOOP_FIN 4'b0100
+`define READ_WT_LO 4'b0101
+`define READ_WT_ACK 4'b0110
+`define WRITE_WT_LO 4'b0111
+`define WRITE_WT_HI 4'b1000
+`define WRITE_CHK_LOOP_FIN 4'b1001
+`define WRITE_LOOP_WT_LO 4'b1010
+`define WRITE_ST_LOOP 4'b1011
+`define WRITE_WT_LO2 4'b1100
+`define WRITE_WT_HI2 4'b1101
+`define WRITE_CLR_WR 4'b1110
+`define WRITE_CLR_ST_STOP 4'b1111
+
+reg [3:0]CurrState_SISt, NextState_SISt;
+
+// Diagram actions (continuous assignments allowed only: assign ...)
+// diagram ACTION
+
+
+// Machine: SISt
+
+// NextState logic (combinatorial)
+always @ (startStopDetState or streamSt or scl or txData or bitCnt or rxData or sdaIn or regAddr or dataIn or sdaOut or writeEn or dataOut or clearStartStopDet or CurrState_SISt)
+begin
+ NextState_SISt <= CurrState_SISt;
+ // Set default values for outputs and signals
+ next_streamSt <= streamSt;
+ next_txData <= txData;
+ next_rxData <= rxData;
+ next_sdaOut <= sdaOut;
+ next_writeEn <= writeEn;
+ next_dataOut <= dataOut;
+ next_bitCnt <= bitCnt;
+ next_clearStartStopDet <= clearStartStopDet;
+ next_regAddr <= regAddr;
+ case (CurrState_SISt) // synopsys parallel_case full_case
+ `START:
+ begin
+ next_streamSt <= `STREAM_IDLE;
+ next_txData <= 8'h00;
+ next_rxData <= 8'h00;
+ next_sdaOut <= 1'b1;
+ next_writeEn <= 1'b0;
+ next_dataOut <= 8'h00;
+ next_bitCnt <= 3'b000;
+ next_clearStartStopDet <= 1'b0;
+ NextState_SISt <= `CHK_RD_WR;
+ end
+ `CHK_RD_WR:
+ begin
+ if (streamSt == `STREAM_READ)
+ begin
+ NextState_SISt <= `READ_RD_LOOP;
+ next_txData <= dataIn;
+ next_regAddr <= regAddr + 1'b1;
+ next_bitCnt <= 3'b001;
+ end
+ else
+ begin
+ NextState_SISt <= `WRITE_WT_HI;
+ next_rxData <= 8'h00;
+ end
+ end
+ `READ_RD_LOOP:
+ begin
+ if (scl == 1'b0)
+ begin
+ NextState_SISt <= `READ_WT_HI;
+ next_sdaOut <= txData [7];
+ next_txData <= {txData [6:0], 1'b0};
+ end
+ end
+ `READ_WT_HI:
+ begin
+ if (scl == 1'b1)
+ begin
+ NextState_SISt <= `READ_CHK_LOOP_FIN;
+ end
+ end
+ `READ_CHK_LOOP_FIN:
+ begin
+ if (bitCnt == 3'b000)
+ begin
+ NextState_SISt <= `READ_WT_LO;
+ end
+ else
+ begin
+ NextState_SISt <= `READ_RD_LOOP;
+ next_bitCnt <= bitCnt + 1'b1;
+ end
+ end
+ `READ_WT_LO:
+ begin
+ if (scl == 1'b0)
+ begin
+ NextState_SISt <= `READ_WT_ACK;
+ next_sdaOut <= 1'b1;
+ end
+ end
+ `READ_WT_ACK:
+ begin
+ if (scl == 1'b1)
+ begin
+ NextState_SISt <= `CHK_RD_WR;
+ if (sdaIn == `I2C_NAK)
+ next_streamSt <= `STREAM_IDLE;
+ end
+ end
+ `WRITE_WT_LO:
+ begin
+ if ((scl == 1'b0) && (startStopDetState == `STOP_DET ||
+ (streamSt == `STREAM_IDLE && startStopDetState == `NULL_DET)))
+ begin
+ NextState_SISt <= `WRITE_CLR_ST_STOP;
+ case (startStopDetState)
+ `NULL_DET:
+ next_bitCnt <= bitCnt + 1'b1;
+ `START_DET: begin
+ next_streamSt <= `STREAM_IDLE;
+ next_rxData <= 8'h00;
+ end
+ default: ;
+ endcase
+ next_streamSt <= `STREAM_IDLE;
+ next_clearStartStopDet <= 1'b1;
+ end
+ else if (scl == 1'b0)
+ begin
+ NextState_SISt <= `WRITE_ST_LOOP;
+ case (startStopDetState)
+ `NULL_DET:
+ next_bitCnt <= bitCnt + 1'b1;
+ `START_DET: begin
+ next_streamSt <= `STREAM_IDLE;
+ next_rxData <= 8'h00;
+ end
+ default: ;
+ endcase
+ end
+ end
+ `WRITE_WT_HI:
+ begin
+ if (scl == 1'b1)
+ begin
+ NextState_SISt <= `WRITE_WT_LO;
+ next_rxData <= {rxData [6:0], sdaIn};
+ next_bitCnt <= 3'b000;
+ end
+ end
+ `WRITE_CHK_LOOP_FIN:
+ begin
+ if (bitCnt == 3'b111)
+ begin
+ NextState_SISt <= `WRITE_CLR_WR;
+ next_sdaOut <= `I2C_ACK;
+ case (streamSt)
+ `STREAM_IDLE: begin
+ if (rxData[7:1] == `I2C_ADDRESS && startStopDetState == `START_DET) begin
+ if (rxData[0] == 1'b1)
+ next_streamSt <= `STREAM_READ;
+ else
+ next_streamSt <= `STREAM_WRITE_ADDR;
+ end
+ else
+ next_sdaOut <= `I2C_NAK;
+ end
+ `STREAM_WRITE_ADDR: begin
+ if(regAddr_hiByte == 0) begin
+ next_regAddr[15:8] <= rxData;
+ regAddr_hiByte <= 1;
+ end
+ else begin
+ next_streamSt <= `STREAM_WRITE_DATA;
+ next_regAddr[7:0] <= rxData;
+ regAddr_hiByte <= 0;
+ end
+ end
+ `STREAM_WRITE_DATA: begin
+ next_dataOut <= rxData;
+ next_writeEn <= 1'b1;
+ end
+ default:
+ next_streamSt <= streamSt;
+ endcase
+ end
+ else
+ begin
+ NextState_SISt <= `WRITE_ST_LOOP;
+ next_bitCnt <= bitCnt + 1'b1;
+ end
+ end
+ `WRITE_LOOP_WT_LO:
+ begin
+ if (scl == 1'b0)
+ begin
+ NextState_SISt <= `WRITE_CHK_LOOP_FIN;
+ end
+ end
+ `WRITE_ST_LOOP:
+ begin
+ if (scl == 1'b1)
+ begin
+ NextState_SISt <= `WRITE_LOOP_WT_LO;
+ next_rxData <= {rxData [6:0], sdaIn};
+ end
+ end
+ `WRITE_WT_LO2:
+ begin
+ if (scl == 1'b0)
+ begin
+ NextState_SISt <= `CHK_RD_WR;
+ next_sdaOut <= 1'b1;
+ end
+ end
+ `WRITE_WT_HI2:
+ begin
+ next_clearStartStopDet <= 1'b0;
+ if (scl == 1'b1)
+ begin
+ NextState_SISt <= `WRITE_WT_LO2;
+ end
+ end
+ `WRITE_CLR_WR:
+ begin
+ if (writeEn == 1'b1)
+ next_regAddr <= regAddr + 1'b1;
+ next_writeEn <= 1'b0;
+ next_clearStartStopDet <= 1'b1;
+ NextState_SISt <= `WRITE_WT_HI2;
+ end
+ `WRITE_CLR_ST_STOP:
+ begin
+ next_clearStartStopDet <= 1'b0;
+ NextState_SISt <= `CHK_RD_WR;
+ end
+ endcase
+end
+
+// Current State Logic (sequential)
+always @ (posedge clk)
+begin
+ if (rst == 1'b1)
+ CurrState_SISt <= `START;
+ else
+ CurrState_SISt <= NextState_SISt;
+end
+
+// Registered outputs logic
+always @ (posedge clk)
+begin
+ if (rst == 1'b1)
+ begin
+ sdaOut <= 1'b1;
+ writeEn <= 1'b0;
+ dataOut <= 8'h00;
+ clearStartStopDet <= 1'b0;
+ // regAddr <= // Initialization in the reset state or default value required!!
+ streamSt <= `STREAM_IDLE;
+ txData <= 8'h00;
+ rxData <= 8'h00;
+ bitCnt <= 3'b000;
+ end
+ else
+ begin
+ sdaOut <= next_sdaOut;
+ writeEn <= next_writeEn;
+ dataOut <= next_dataOut;
+ clearStartStopDet <= next_clearStartStopDet;
+ regAddr <= next_regAddr;
+ streamSt <= next_streamSt;
+ txData <= next_txData;
+ rxData <= next_rxData;
+ bitCnt <= next_bitCnt;
+ end
+end
+
+endmodule
\ No newline at end of file
diff --git a/i2c_slave_opencores/rtl/timescale.v b/i2c_slave_opencores/rtl/timescale.v
new file mode 100644
index 0000000..edd8d7a
--- /dev/null
+++ b/i2c_slave_opencores/rtl/timescale.v
@@ -0,0 +1,5 @@
+//////////////////////////////////////////////////////////////////////
+// timescale.v
+//////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+
diff --git a/i2c_slave_opencores/sim/build_icarus.bat b/i2c_slave_opencores/sim/build_icarus.bat
new file mode 100644
index 0000000..dd87e77
--- /dev/null
+++ b/i2c_slave_opencores/sim/build_icarus.bat
@@ -0,0 +1,2 @@
+#!/bin/sh
+iverilog -o testHarness -c filelist.icarus
diff --git a/i2c_slave_opencores/sim/filelist.icarus b/i2c_slave_opencores/sim/filelist.icarus
new file mode 100644
index 0000000..7d33b1b
--- /dev/null
+++ b/i2c_slave_opencores/sim/filelist.icarus
@@ -0,0 +1,16 @@
+../rtl/serialInterface.v
+../rtl/registerInterface.v
+../rtl/i2cSlave.v
+../model/i2c_master_bit_ctrl.v
+../model/i2c_master_byte_ctrl.v
+../model/i2c_master_top.v
+../model/wb_master_model.v
+../bench/multiByteReadWrite.v
+../bench/testHarness.v
+../bench/testCase0.v
+
++incdir+../rtl
++incdir+../bench
++incdir+../model
++define+SIM_COMPILE
+
diff --git a/i2c_slave_opencores/sim/gtkwave.ini b/i2c_slave_opencores/sim/gtkwave.ini
new file mode 100644
index 0000000..bb5f6d7
--- /dev/null
+++ b/i2c_slave_opencores/sim/gtkwave.ini
@@ -0,0 +1,50 @@
+#
+# sample rc file
+#
+hier_max_level 1
+force_toolbars 0
+
+dynamic_resizing 1
+hpane_pack 1
+use_vcd 0
+#initial_window_x 700
+#initial_window_y 400
+use_maxtime_display 0
+
+enable_vcd_autosave 0
+use_roundcaps 1
+
+use_nonprop_fonts yes
+enable_horiz_grid yes
+use_big_fonts no
+constant_marker_update yes
+show_grid yes
+show_base_symbols no
+use_roundcaps yes
+
+atomic_vectors yes
+vcd_explicit_zero_subscripts no
+
+#
+# color additions
+#
+color_back 000000
+color_grid 202070
+color_high 00ff00
+color_low 008000
+color_trans 00c000
+color_mid c0c000
+
+color_value ffffff
+color_vbox 00ff00
+color_vtrans 00c000
+
+color_x 00ff00
+color_xfill 004000
+
+color_umark ff8080
+color_mark ffff80
+
+color_time ffffff
+color_timeb 000000
+
diff --git a/i2c_slave_opencores/sim/myWave.sav b/i2c_slave_opencores/sim/myWave.sav
new file mode 100644
index 0000000..f155467
--- /dev/null
+++ b/i2c_slave_opencores/sim/myWave.sav
@@ -0,0 +1,10 @@
+*-27.236394 43400000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+@28
+testHarness.u_i2cSlave.scl
+testHarness.u_i2cSlave.sda
+@22
+testHarness.u_i2cSlave.tb_readEn
+testHarness.u_i2cSlave.tb_writeEn
+testHarness.u_i2cSlave.tb_addr[15:0]
+testHarness.u_i2cSlave.tb_dataIn[15:0]
+testHarness.u_i2cSlave.tb_dataOut[15:0]
diff --git a/i2c_slave_opencores/sim/run_icarus.bat b/i2c_slave_opencores/sim/run_icarus.bat
new file mode 100644
index 0000000..9d6aae0
--- /dev/null
+++ b/i2c_slave_opencores/sim/run_icarus.bat
@@ -0,0 +1,2 @@
+vvp testHarness
+
diff --git a/i2c_slave_opencores/sim/simulate.sh b/i2c_slave_opencores/sim/simulate.sh
new file mode 100644
index 0000000..9b0aab4
--- /dev/null
+++ b/i2c_slave_opencores/sim/simulate.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+iverilog -o testHarness -cfilelist.icarus && vvp testHarness
diff --git a/i2c_slave_opencores/sim/viewWave.bat b/i2c_slave_opencores/sim/viewWave.bat
new file mode 100644
index 0000000..45f2687
--- /dev/null
+++ b/i2c_slave_opencores/sim/viewWave.bat
@@ -0,0 +1 @@
+gtkwave wave.vcd myWave.sav