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

Subversion Repositories i2cslave

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/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
 
/trunk/bench/testCase0.v
0,0 → 1,41
// ---------------------------------- 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;
#1000;
 
// 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}, 8'h00, 32'h89abcdef, `SEND_STOP);
multiByteReadWrite.read({`I2C_ADDRESS, 1'b0}, 8'h00, 32'h89abcdef, dataWord, `NULL);
multiByteReadWrite.read({`I2C_ADDRESS, 1'b0}, 8'h04, 32'h12345678, dataWord, `NULL);
 
$write("Finished all tests\n");
$stop;
 
end
 
endmodule
 
/trunk/bench/testHarness.v
0,0 → 1,119
// -------------------------- 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;
 
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, testHarness);
end
 
 
i2cSlave u_i2cSlave(
.clk(clk),
.rst(rst),
.sda(sda),
.scl(scl),
.myReg0(),
.myReg1(),
.myReg2(),
.myReg3(),
.myReg4(8'h12),
.myReg5(8'h34),
.myReg6(8'h56),
.myReg7(8'h78)
);
 
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
/trunk/bench/multiByteReadWrite.v
0,0 → 1,152
// ------------------ 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 [7: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
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr);
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 [7: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
testHarness.u_wb_master_model.wb_write(1, `TXR_REG, regAddr);
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("I2C Read: At [0x%0x] = 0x%0x\n", regAddr, data);
end
endtask
 
endmodule
 
/trunk/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
/trunk/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
/trunk/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
/trunk/model/i2c_master_specs.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
trunk/model/i2c_master_specs.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/model/i2c_master_bit_ctrl.v =================================================================== --- trunk/model/i2c_master_bit_ctrl.v (nonexistent) +++ trunk/model/i2c_master_bit_ctrl.v (revision 2) @@ -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 Index: trunk/model/i2c_master_top.v =================================================================== --- trunk/model/i2c_master_top.v (nonexistent) +++ trunk/model/i2c_master_top.v (revision 2) @@ -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 Index: trunk/rtl/i2cSlaveTop.v =================================================================== --- trunk/rtl/i2cSlaveTop.v (nonexistent) +++ trunk/rtl/i2cSlaveTop.v (revision 2) @@ -0,0 +1,82 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// i2cSlaveTop.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 i2cSlaveTop ( + clk, + rst, + sda, + scl, + myReg0 +); +input clk; +input rst; +inout sda; +input scl; +output [7:0] myReg0; + + +i2cSlave u_i2cSlave( + .clk(clk), + .rst(rst), + .sda(sda), + .scl(scl), + .myReg0(myReg0), + .myReg1(), + .myReg2(), + .myReg3(), + .myReg4(8'h12), + .myReg5(8'h34), + .myReg6(8'h56), + .myReg7(8'h78) + +); + + +endmodule + + + Index: trunk/rtl/serialInterface.v =================================================================== --- trunk/rtl/serialInterface.v (nonexistent) +++ trunk/rtl/serialInterface.v (revision 2) @@ -0,0 +1,365 @@ + +////////////////////////////////////////////////////////////////////// +//// //// +//// 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 [7:0]regAddr; +output sdaOut; +output writeEn; + +reg clearStartStopDet, next_clearStartStopDet; +wire clk; +wire [7:0]dataIn; +reg [7:0]dataOut, next_dataOut; +reg [7:0]regAddr, next_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 + next_streamSt <= `STREAM_WRITE_DATA; + next_regAddr <= rxData; + 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 Index: trunk/rtl/i2cSlave_define.v =================================================================== --- trunk/rtl/i2cSlave_define.v (nonexistent) +++ trunk/rtl/i2cSlave_define.v (revision 2) @@ -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 + Index: trunk/rtl/registerInterface.v =================================================================== --- trunk/rtl/registerInterface.v (nonexistent) +++ trunk/rtl/registerInterface.v (revision 2) @@ -0,0 +1,116 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// 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, + myReg0, + myReg1, + myReg2, + myReg3, + myReg4, + myReg5, + myReg6, + myReg7 + +); +input clk; +input [7:0] addr; +input [7:0] dataIn; +input writeEn; +output [7:0] dataOut; +output [7:0] myReg0; +output [7:0] myReg1; +output [7:0] myReg2; +output [7:0] myReg3; +input [7:0] myReg4; +input [7:0] myReg5; +input [7:0] myReg6; +input [7:0] myReg7; + +reg [7:0] dataOut; +reg [7:0] myReg0; +reg [7:0] myReg1; +reg [7:0] myReg2; +reg [7:0] myReg3; + +// --- I2C Read +always @(posedge clk) begin + case (addr) + 8'h00: dataOut <= myReg0; + 8'h01: dataOut <= myReg1; + 8'h02: dataOut <= myReg2; + 8'h03: dataOut <= myReg3; + 8'h04: dataOut <= myReg4; + 8'h05: dataOut <= myReg5; + 8'h06: dataOut <= myReg6; + 8'h07: dataOut <= myReg7; + default: dataOut <= 8'h00; + endcase +end + +// --- I2C Write +always @(posedge clk) begin + if (writeEn == 1'b1) begin + case (addr) + 8'h00: myReg0 <= dataIn; + 8'h01: myReg1 <= dataIn; + 8'h02: myReg2 <= dataIn; + 8'h03: myReg3 <= dataIn; + endcase + end +end + +endmodule + + + Index: trunk/rtl/timescale.v =================================================================== --- trunk/rtl/timescale.v (nonexistent) +++ trunk/rtl/timescale.v (revision 2) @@ -0,0 +1,5 @@ +////////////////////////////////////////////////////////////////////// +// timescale.v +////////////////////////////////////////////////////////////////////// +`timescale 1ns / 1ps + Index: trunk/rtl/i2cSlave.v =================================================================== --- trunk/rtl/i2cSlave.v (nonexistent) +++ trunk/rtl/i2cSlave.v (revision 2) @@ -0,0 +1,207 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// 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, + myReg0, + myReg1, + myReg2, + myReg3, + myReg4, + myReg5, + myReg6, + myReg7 +); + +input clk; +input rst; +inout sda; +input scl; +output [7:0] myReg0; +output [7:0] myReg1; +output [7:0] myReg2; +output [7:0] myReg3; +input [7:0] myReg4; +input [7:0] myReg5; +input [7:0] myReg6; +input [7:0] myReg7; + + +// 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 [7: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), + .myReg0(myReg0), + .myReg1(myReg1), + .myReg2(myReg2), + .myReg3(myReg3), + .myReg4(myReg4), + .myReg5(myReg5), + .myReg6(myReg6), + .myReg7(myReg7) +); + +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 + + + Index: trunk/doc/i2cSlave_IPCore_Specification.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/i2cSlave_IPCore_Specification.pdf =================================================================== --- trunk/doc/i2cSlave_IPCore_Specification.pdf (nonexistent) +++ trunk/doc/i2cSlave_IPCore_Specification.pdf (revision 2)
trunk/doc/i2cSlave_IPCore_Specification.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/doc/i2cSlave_FSM.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/i2cSlave_FSM.pdf =================================================================== --- trunk/doc/i2cSlave_FSM.pdf (nonexistent) +++ trunk/doc/i2cSlave_FSM.pdf (revision 2)
trunk/doc/i2cSlave_FSM.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/doc/Philips_I2C_spec.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/Philips_I2C_spec.pdf =================================================================== --- trunk/doc/Philips_I2C_spec.pdf (nonexistent) +++ trunk/doc/Philips_I2C_spec.pdf (revision 2)
trunk/doc/Philips_I2C_spec.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/doc/src/i2cSlave_IPCore_Specification.sxw =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/src/i2cSlave_IPCore_Specification.sxw =================================================================== --- trunk/doc/src/i2cSlave_IPCore_Specification.sxw (nonexistent) +++ trunk/doc/src/i2cSlave_IPCore_Specification.sxw (revision 2)
trunk/doc/src/i2cSlave_IPCore_Specification.sxw Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/Aldec/design0/fsm.set =================================================================== --- trunk/Aldec/design0/fsm.set (nonexistent) +++ trunk/Aldec/design0/fsm.set (revision 2) @@ -0,0 +1,5 @@ +FSMSET_CUTHEADER=1 +FSMSET_GENCOMMENTS=1 +FSMSET_USEDEFINE=1 +FSMSET_OMITGENNULL=0 +FSMSET_ENABLEPARSING=1 Index: trunk/Aldec/design0/design0.adf =================================================================== --- trunk/Aldec/design0/design0.adf (nonexistent) +++ trunk/Aldec/design0/design0.adf (revision 2) @@ -0,0 +1,28 @@ +[Project] +Current Flow=Generic +VCS=0 +version=1 +Current Config=compile + +[Configurations] +compile=design0 + +[Library] +design0=.\design0.LIB + +[$LibMap$] +design0=. + +[Settings] +FLOW_TYPE=HDL +LANGUAGE=VHDL + +[Files] +/serialInterface.asf=-1 + +[Files.Data] +.\src\serialInterface.asf=State Diagram + +[file_out:/serialInterface.asf] +/\compile\serialInterface.v=-1 + Index: trunk/Aldec/design0/src/serialInterface.asf =================================================================== --- trunk/Aldec/design0/src/serialInterface.asf (nonexistent) +++ trunk/Aldec/design0/src/serialInterface.asf (revision 2) @@ -0,0 +1,207 @@ +VERSION=1.15 +HEADER +FILE="serialInterface.asf" +FID=4788d213 +LANGUAGE=VERILOG +ENTITY="serialInterface" +FRAMES=ON +FREEOID=1240 +"LIBRARIES=//////////////////////////////////////////////////////////////////////\n//// ////\n//// serialInterface.v ////\n//// ////\n//// This file is part of the i2cSlave opencores effort.\n//// ////\n//// ////\n//// Module Description: ////\n//// Perform all serial to parallel, and parallel\n//// to serial conversions. Perform device address matching\n//// Handle arbitrary length I2C reads terminated by NAK\n//// from host, and arbitrary length I2C writes terminated\n//// by STOP from host\n//// The second byte of a I2C write is always interpreted\n//// as a register address, and becomes the base register address\n//// for all read and write transactions.\n//// I2C WRITE: devAddr, regAddr, data[regAddr], data[regAddr+1], ..... data[regAddr+N]\n//// I2C READ: data[regAddr], data[regAddr+1], ..... data[regAddr+N]\n//// Note that when regAddR reaches 255 it will automatically wrap round to 0\n//// ////\n//// To Do: ////\n//// \n//// ////\n//// Author(s): ////\n//// - Steve Fielding, sfielding@base2designs.com ////\n//// ////\n//////////////////////////////////////////////////////////////////////\n//// ////\n//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG ////\n//// ////\n//// This source file may be used and distributed without ////\n//// restriction provided that this copyright statement is not ////\n//// removed from the file and that any derivative work contains ////\n//// the original copyright notice and the associated disclaimer. ////\n//// ////\n//// This source file is free software; you can redistribute it ////\n//// and/or modify it under the terms of the GNU Lesser General ////\n//// Public License as published by the Free Software Foundation; ////\n//// either version 2.1 of the License, or (at your option) any ////\n//// later version. ////\n//// ////\n//// This source is distributed in the hope that it will be ////\n//// useful, but WITHOUT ANY WARRANTY; without even the implied ////\n//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////\n//// PURPOSE. See the GNU Lesser General Public License for more ////\n//// details. ////\n//// ////\n//// You should have received a copy of the GNU Lesser General ////\n//// Public License along with this source; if not, download it ////\n//// from ////\n//// ////\n//////////////////////////////////////////////////////////////////////\n//\n`include \"timescale.v\"\n`include \"i2cSlave_define.v\"\n" +END +BUNDLES +B T "Declarations" 0,0,255 0 0 1 255,255,255 0 2844 0 0000 1 "Arial" 0 +B T "Conditions" 0,0,0 0 0 0 255,255,255 0 2844 0 0110 1 "Arial" 0 +B F "States" 0,0,0 0 0 1 0,255,0 1 3527 1480 0000 1 "Arial" 0 +B T "Actions" 0,0,0 0 0 1 255,255,255 0 2844 0 0000 1 "Arial" 0 +B T "Labels" 0,0,0 0 0 0 255,255,255 0 2844 0 0000 1 "Arial" 0 +B L "Transitions" 0,0,0 0 0 1 0,0,0 1 3527 1480 0000 1 "Arial" 0 +B F "Ports" 0,0,0 0 0 1 0,255,255 1 3527 1480 0000 1 "Arial" 0 +B L "Errors" 255,0,0 0 3 1 255,255,255 1 3527 1480 0000 1 "Arial" 0 +B T "State Labels" 0,0,0 0 0 0 255,255,255 0 2844 0 0000 1 "Arial" 4 +B F "Current State" 255,255,0 0 0 1 255,255,0 1 3527 1480 0000 1 "Arial" 0 +B T "Comments" 157,157,157 0 0 1 255,255,255 0 3527 1480 0000 1 "Arial" 0 +B L "Info" 0,255,0 0 3 1 255,255,255 1 3527 1480 0000 1 "Arial" 0 +END +INSTHEADER 1 +PAGE 25400,25400 215900,279400 +UPPERLEFT 0,0 +GRID=OFF +GRIDSIZE 5000,5000 10000,10000 +END +INSTHEADER 1093 +PAGE 25400,25400 215900,279400 +UPPERLEFT 0,0 +GRID=OFF +GRIDSIZE 0,0 10000,10000 +END +INSTHEADER 1102 +PAGE 25400,25400 215900,279400 +UPPERLEFT 0,0 +GRID=OFF +GRIDSIZE 0,0 10000,10000 +END +INSTHEADER 1163 +PAGE 25400,25400 215900,279400 +UPPERLEFT 0,0 +GRID=OFF +GRIDSIZE 0,0 10000,10000 +END +OBJECTS +L 7 6 0 TEXT "Labels" | 31673,209974 1 0 0 "SISt" +F 6 0 512 72 0 RECT 0,0,0 0 0 1 255,255,255 0 | 28400,28400 212900,212603 +A 5 0 1 TEXT "Actions" | 30400,266783 1 0 0 "-- diagram ACTION" +G 1 0 0 TEXT 0,0,0 0 0 0 255,255,255 0 3527 1480 0000 1 "Arial" 0 | 110650,276400 1 0 0 "Module: serialInterface" +I 1088 0 130 Builtin Signal | 170556,231962 "" "" +A 1089 100 4 TEXT "Actions" | 164916,210687 1 0 0 "streamSt <= `STREAM_IDLE;\ntxData <= 8'h00;\nrxData <= 8'h00;\nsdaOut <= 1'b1;\nwriteEn <= 1'b0;\ndataOut <= 8'h00;\nbitCnt <= 3'b000;\nclearStartStopDet <= 1'b0;" +L 1090 1091 0 TEXT "State Labels" | 113022,167010 1 0 0 "CHK_RD_WR\n/1/" +S 1091 6 4096 ELLIPSE "States" | 113022,167010 6500 6500 +L 1092 1093 0 TEXT "State Labels" | 145788,131922 1 0 0 "READ" +S 1093 6 8196 ELLIPSE 0,0,0 0 0 1 0,255,255 1 | 145788,131922 6500 6500 +H 1094 1093 0 RECT 0,0,0 0 0 1 255,255,255 0 | 28400,28400 212900,276400 +I 1097 1094 0 Builtin Entry | 45436,264408 +I 1098 1094 0 Builtin Exit | 66804,75108 +L 1101 1102 0 TEXT "State Labels" | 82836,130374 1 0 0 "WRITE" +S 1102 6 12292 ELLIPSE 0,0,0 0 0 1 0,255,255 1 | 82836,130374 6500 6500 +H 1103 1102 0 RECT 0,0,0 0 0 1 255,255,255 0 | 28400,28400 212900,276400 +I 1106 1103 0 Builtin Entry | 45436,269052 +W 1111 6 1 1091 1093 BEZIER "Transitions" | 117575,162372 124283,155471 134905,143802 141613,136901 +W 1112 6 2 1091 1102 BEZIER "Transitions" | 108455,162386 102521,154775 92600,143235 86666,135624 +C 1113 1111 0 TEXT "Conditions" | 124761,159657 1 0 0 "streamSt == `STREAM_READ" +L 1114 1115 0 TEXT "State Labels" | 60132,233832 1 0 0 "RD_LOOP\n/2/" +S 1115 1094 16384 ELLIPSE "States" | 60132,233832 6500 6500 +W 1116 1094 0 1097 1115 BEZIER "Transitions" | 49435,264408 51757,258345 54648,245572 56970,239509 +L 1117 1118 0 TEXT "State Labels" | 62196,202356 1 0 0 "WT_HI\n/3/" +S 1118 1094 20480 ELLIPSE "States" | 62196,202356 6500 6500 +W 1119 1094 0 1115 1118 BEZIER "Transitions" | 60334,227358 60656,222198 61220,213982 61542,208822 +C 1120 1119 0 TEXT "Conditions" | 61814,227496 1 0 0 "scl == 1'b0" +L 1121 1122 0 TEXT "State Labels" | 63833,168493 1 0 0 "CHK_LOOP_FIN\n/4/" +S 1122 1094 24576 ELLIPSE "States" | 63833,168493 6500 6500 +W 1123 1094 0 1118 1122 BEZIER "Transitions" | 62616,195885 62873,192095 63548,178990 63552,174971 +C 1124 1123 0 TEXT "Conditions" | 65004,194763 1 0 0 "scl == 1'b1" +A 1125 1116 16 TEXT "Actions" | 46574,259544 1 0 0 "txData <= dataIn;\nregAddr <= regAddr + 1'b1;\nbitCnt <= 3'b001;" +L 1127 1128 0 TEXT "State Labels" | 64515,139815 1 0 0 "WT_LO\n/5/" +S 1128 1094 28672 ELLIPSE "States" | 64515,139815 6500 6500 +W 1133 1094 1 1122 1128 BEZIER "Transitions" | 63734,162016 63671,157426 63956,150868 63893,146278 +C 1135 1133 0 TEXT "Conditions" | 67448,161363 1 0 0 "bitCnt == 3'b000" +W 1136 1094 2 1122 1115 BEZIER "Transitions" | 70264,169432 80793,170973 95664,170699 106435,174896\ + 117206,179094 120169,183293 119563,193014 118958,202736\ + 113857,211534 106441,217176 99026,222818 76882,233683\ + 66172,236233 +L 1137 1138 0 TEXT "State Labels" | 65790,108960 1 0 0 "WT_ACK\n/6/" +S 1138 1094 32768 ELLIPSE "States" | 65790,108960 6500 6500 +W 1139 1094 0 1128 1138 BEZIER "Transitions" | 64641,133339 64223,128449 65212,119705 65696,115446 +A 1141 1136 16 TEXT "Actions" | 99952,191787 1 0 0 "bitCnt <= bitCnt + 1'b1;" +A 1143 1119 16 TEXT "Actions" | 42458,221543 1 0 0 "sdaOut <= txData [7];\ntxData <= {txData [6:0], 1'b0};" +C 1144 1139 0 TEXT "Conditions" | 66481,131783 1 0 0 "scl == 1'b0" +W 1147 1094 0 1138 1098 BEZIER "Transitions" | 65848,102499 65911,97591 66741,82032 66804,77124 +C 1148 1147 0 TEXT "Conditions" | 67234,101707 1 0 0 "scl == 1'b1" +A 1149 1147 16 TEXT "Actions" | 61593,95455 1 0 0 "if (sdaIn == `I2C_NAK)\n streamSt <= `STREAM_IDLE;" +A 1150 1139 16 TEXT "Actions" | 63113,125918 1 0 0 "sdaOut <= 1'b1;" +L 71 72 0 TEXT "Labels" | 201700,272800 1 0 0 "clk" +I 72 0 3 Builtin InPort | 195700,272800 "" "" +L 73 74 0 TEXT "Labels" | 201700,267632 1 0 0 "rst" +I 74 0 2 Builtin InPort | 195700,267632 "" "" +L 1152 1153 0 TEXT "State Labels" | 50328,243636 1 0 0 "WT_HI\n/8/" +S 1153 1103 45056 ELLIPSE "States" | 50328,243636 6500 6500 +W 1154 1103 0 1106 1153 BEZIER "Transitions" | 45436,266988 46403,261957 48180,255054 49147,250023 +L 1156 1157 0 TEXT "State Labels" | 53682,211902 1 0 0 "WT_LO\n/7/" +S 1157 1103 40960 ELLIPSE "States" | 53682,211902 6500 6500 +W 1158 1103 0 1153 1157 BEZIER "Transitions" | 50941,237173 51263,234013 52778,221621 52602,218309 +C 1160 1158 0 TEXT "Conditions" | 52521,236757 1 0 0 "scl == 1'b1" +L 1162 1163 0 TEXT "State Labels" | 54198,183780 1 0 0 "J1" +S 1163 1103 36868 ELLIPSE 0,0,0 0 0 1 255,0,0 1 | 54136,183976 3858 3858 +W 1164 1103 0 1157 1163 BEZIER "Transitions" | 53938,205422 54389,199424 52869,194235 53483,187777 +C 1165 1164 0 TEXT "Conditions" | 36280,204549 1 0 0 "scl == 1'b0" +H 1166 1163 0 RECT 0,0,0 0 0 1 255,255,255 0 | 28400,28400 212900,276400 +I 1169 1166 0 Builtin Entry | 96520,182880 +I 1170 1166 0 Builtin Exit | 144780,121920 +W 1171 1166 0 1169 1170 BEZIER "Transitions" | 100503,182880 105961,175176 136367,129625 141825,121920 +C 1174 1173 0 TEXT "Conditions" | 38599,178519 1 0 0 "startStopDetState == `STOP_DET || \n(streamSt == `STREAM_IDLE && startStopDetState == `NULL_DET)" +A 1175 1158 16 TEXT "Actions" | 50457,231381 1 0 0 "rxData <= {rxData [6:0], sdaIn};\nbitCnt <= 3'b000;" +L 1176 1177 0 TEXT "State Labels" | 153270,180426 1 0 0 "ST_LOOP\n/11/" +S 1177 1103 57344 ELLIPSE "States" | 153270,180426 6500 6500 +W 1178 1103 2 1163 1177 BEZIER "Transitions" | 57992,183868 81212,183352 123565,181370 146785,180854 +L 1179 1180 0 TEXT "State Labels" | 155592,146628 1 0 0 "LOOP_WT_LO\n/10/" +S 1180 1103 53248 ELLIPSE "States" | 155592,146628 6500 6500 +L 1181 1182 0 TEXT "State Labels" | 157656,119022 1 0 0 "CHK_LOOP_FIN\n/9/" +S 1182 1103 49152 ELLIPSE "States" | 157656,119022 6500 6500 +W 1183 1103 0 1177 1180 BEZIER "Transitions" | 153480,173948 154060,169433 154616,157853 155339,153110 +W 1173 1103 1 1163 1227 BEZIER "Transitions" | 53628,180156 50790,158613 43756,133955 42667,107411 +L 99 100 0 TEXT "State Labels" | 112176,193512 1 0 0 "START\n/0/" +S 100 6 0 ELLIPSE "States" | 112176,193512 6500 6500 +C 1184 1183 0 TEXT "Conditions" | 155746,173950 1 0 0 "scl == 1'b1" +A 1185 1183 16 TEXT "Actions" | 132915,164958 1 0 0 "rxData <= {rxData [6:0], sdaIn};" +W 1186 1103 0 1180 1182 BEZIER "Transitions" | 155830,140145 156152,136275 156699,129381 156919,125472 +C 1187 1186 0 TEXT "Conditions" | 157807,138966 1 0 0 "scl == 1'b0" +L 1188 1189 0 TEXT "State Labels" | 140079,63027 1 0 0 "WT_HI2\n/13/" +S 1189 1103 65536 ELLIPSE "States" | 140079,63027 6500 6500 +W 1190 1103 1 1182 1222 BEZIER "Transitions" | 158063,112542 158373,105705 114008,67631 99616,51225 +C 1191 1190 0 TEXT "Conditions" | 154327,105370 1 0 0 "bitCnt == 3'b111" +W 1192 1103 2 1182 1177 BEZIER "Transitions" | 164050,120187 172177,122186 187713,125537 192034,132825\ + 196356,140113 197388,165269 194840,174814 192293,184360\ + 181069,197390 175554,198486 170040,199583 161883,190407\ + 156465,186086 +A 1194 1192 16 TEXT "Actions" | 177909,132825 1 0 0 "bitCnt <= bitCnt + 1'b1;" +A 1195 1190 16 TEXT "Actions" | 75201,159471 1 0 0 "sdaOut <= `I2C_ACK;\ncase (streamSt)\n `STREAM_IDLE: begin\n if (rxData[7:1] == `I2C_ADDRESS && \n startStopDetState == `START_DET) begin\n if (rxData[0] == 1'b1)\n streamSt <= `STREAM_READ;\n else\n streamSt <= `STREAM_WRITE_ADDR;\n end\n else\n sdaOut <= `I2C_NAK;\n end\n `STREAM_WRITE_ADDR: begin\n streamSt <= `STREAM_WRITE_DATA;\n regAddr <= rxData;\n end\n `STREAM_WRITE_DATA: begin\n dataOut <= rxData;\n writeEn <= 1'b1;\n end\n default:\n streamSt <= streamSt; \nendcase" +L 1196 1197 0 TEXT "State Labels" | 191305,78543 1 0 0 "WT_LO2\n/12/" +S 1197 1103 61440 ELLIPSE "States" | 191305,78543 6500 6500 +W 1198 1103 0 1189 1197 BEZIER "Transitions" | 146335,64787 154139,63625 179557,72674 185403,75822 +C 1199 1198 0 TEXT "Conditions" | 155872,71869 1 0 0 "scl == 1'b1" +W 1211 6 0 1102 1091 BEZIER "Transitions" | 76391,131214 68980,132010 55006,133664 50535,137890\ + 46064,142116 43001,157429 45206,164043 47411,170658\ + 59294,181807 66276,184103 73258,186400 89307,184440\ + 95064,182296 100821,180153 105473,175392 108964,172085 +W 1210 6 0 1093 1091 BEZIER "Transitions" | 152177,133113 160752,135501 176220,139177 178823,144934\ + 181427,150691 174688,168944 167277,174211 159867,179478\ + 136958,182297 130006,181531 123055,180765 119021,175394\ + 116571,172454 +I 1209 0 130 Builtin Signal | 170935,221379 "" "" +L 1208 1209 0 TEXT "Labels" | 173935,221379 1 0 0 "rxData[7:0]" +I 1207 0 130 Builtin Signal | 170682,226692 "" "" +L 1206 1207 0 TEXT "Labels" | 173682,226692 1 0 0 "txData[7:0]" +I 387 6 0 Builtin Reset | 49555,202550 +W 388 6 0 387 100 BEZIER "Transitions" | 49555,202550 64193,201024 91216,196545 105854,195019 +C 389 388 0 TEXT "Conditions" | 63836,205024 1 0 0 "rst == 1'b1" +W 1201 1103 0 1197 1228 BEZIER "Transitions" | 192418,72141 193381,63146 199794,43721 197819,33702 +C 1202 1201 0 TEXT "Conditions" | 186842,58803 1 0 0 "scl == 1'b0" +A 1203 1173 16 TEXT "Actions" | 31827,161251 1 0 0 "streamSt <= `STREAM_IDLE;\nclearStartStopDet <= 1'b1;" +A 1205 1154 16 TEXT "Actions" | 46743,263198 1 0 0 "rxData <= 8'h00;" +L 1212 1213 0 TEXT "Labels" | 173176,236812 1 0 0 "bitCnt[2:0]" +I 1213 0 130 Builtin Signal | 170176,236812 "" "" +L 1215 1216 0 TEXT "Labels" | 82738,249858 1 0 0 "clearStartStopDet" +I 1216 0 2 Builtin OutPort | 76738,249858 "" "" +A 1218 1164 16 TEXT "Actions" | 61717,219098 1 0 0 "case (startStopDetState)\n `NULL_DET:\n bitCnt <= bitCnt + 1'b1;\n `START_DET: begin\n streamSt <= `STREAM_IDLE;\n rxData <= 8'h00;\n end\n default: ;\nendcase" +A 1219 1201 16 TEXT "Actions" | 186936,64587 1 0 0 "sdaOut <= 1'b1;" +L 1221 1222 0 TEXT "State Labels" | 97155,45210 1 0 0 "CLR_WR\n/14/" +S 1222 1103 69632 ELLIPSE "States" | 97155,45210 6500 6500 +A 1223 1222 4 TEXT "Actions" | 51543,60237 1 0 0 "if (writeEn == 1'b1)\n regAddr <= regAddr + 1'b1;\nwriteEn <= 1'b0;\nclearStartStopDet <= 1'b1;" +W 1224 1103 0 1222 1189 BEZIER "Transitions" | 103397,43398 108943,43589 118129,42724 122750,44891\ + 127372,47058 132685,53538 136382,57681 +A 1225 1189 4 TEXT "Actions" | 138593,50693 1 0 0 "clearStartStopDet <= 1'b0;" +L 1226 1227 0 TEXT "State Labels" | 44784,101266 1 0 0 "CLR_ST_STOP\n/15/" +S 1227 1103 73728 ELLIPSE "States" | 44784,101266 6500 6500 +I 1228 1103 0 Builtin Exit | 194898,33702 +W 1229 1103 0 1227 1228 BEZIER "Transitions" | 43558,94885 41209,84027 36973,63356 36338,55800\ + 35703,48244 37863,39734 41355,37226 44847,34718\ + 56659,33194 75867,32940 95076,32686 159465,33448\ + 191977,33702 +A 1230 1227 4 TEXT "Actions" | 30606,92250 1 0 0 "clearStartStopDet <= 1'b0;" +W 1239 6 0 100 1091 BEZIER "Transitions" | 112488,187021 112665,183009 112810,177405 112987,173393 +I 479 0 130 Builtin InPort | 123454,253473 "" "" +L 478 477 0 TEXT "Labels" | 127232,248761 1 0 0 "dataOut[7:0]" +I 477 0 130 Builtin OutPort | 121232,248761 "" "" +L 476 475 0 TEXT "Labels" | 127470,243915 1 0 0 "writeEn" +I 475 0 2 Builtin OutPort | 121470,243915 "" "" +L 472 471 0 TEXT "Labels" | 126974,258272 1 0 0 "regAddr[7:0]" +I 471 0 130 Builtin OutPort | 120974,258272 "" "" +L 480 479 0 TEXT "Labels" | 129454,253473 1 0 0 "dataIn[7:0]" +I 499 0 2 Builtin InPort | 79523,242127 "" "" +L 498 499 0 TEXT "Labels" | 85523,242127 1 0 0 "scl" +I 497 0 130 Builtin InPort | 78578,254745 "" "" +L 496 497 0 TEXT "Labels" | 84578,254745 1 0 0 "startStopDetState[1:0]" +I 1065 0 2 Builtin InPort | 79622,237762 "" "" +L 1064 1065 0 TEXT "Labels" | 85622,237762 1 0 0 "sdaIn" +L 1083 1084 0 TEXT "Labels" | 83208,232994 1 0 0 "sdaOut" +I 1084 0 2 Builtin OutPort | 77208,232994 "" "" +L 1087 1088 0 TEXT "Labels" | 173556,231962 1 0 0 "streamSt[1:0]" +END Index: trunk/sim/run_icarus.bat =================================================================== --- trunk/sim/run_icarus.bat (nonexistent) +++ trunk/sim/run_icarus.bat (revision 2) @@ -0,0 +1,2 @@ +vvp testHarness + Index: trunk/sim/filelist.icarus =================================================================== --- trunk/sim/filelist.icarus (nonexistent) +++ trunk/sim/filelist.icarus (revision 2) @@ -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 + Index: trunk/sim/build_icarus.bat =================================================================== --- trunk/sim/build_icarus.bat (nonexistent) +++ trunk/sim/build_icarus.bat (revision 2) @@ -0,0 +1,4 @@ +iverilog -o testHarness -cfilelist.icarus + +pause +

powered by: WebSVN 2.1.0

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