Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

verilog I2C protocol doubts.. problem with adding setup time, how to add setup time

Status
Not open for further replies.

fradaric

Newbie level 5
Joined
Oct 7, 2011
Messages
8
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,403
Hei ,
I am making a verilog code for I2C in order to communicate with TMP100 , In my design I made the SCL globally, and I've given the slave addressing, pointer addressing etc with a 'always @(posedge scl)' block, so the clock transitions and sda transitions occurs at the same time but TMP 100 (temperature sensor) needs a setup time of 100ns. I couldn't able to provide it since I am using 'always @(posedge scl)'
How can I solve this issue? anyone have any idea?? please help me .... i've added testbench wave form here and also My I2C code is given below.
Capture.PNG

`timescale 1ns / 1ps
// Fradaric Joseph

// Ph: 09401015142

module I2C(
inout sda,
output scl,
output [15:0] temperature_out,
input clk,
output [2:0] ack_out,
output [1:0] ack_count1,
input reset
);

parameter clock_div=500; // I2C clock 50MHz/(500)=100KHz
//---------------------------I2C State Machine Variables----------------------
parameter Rxidle =0;
parameter Rxstart =1;
parameter RxPointeraddr =2;
parameter Rxstart1=3;
parameter Rxdata =4;
parameter Rxstop =5;
//-----------------------------------------------------------------------------
reg chk=0;
reg [2:0] ack;
reg [1:0] ack_count=0;
//reg poiter2=0;
//reg ack2=0;
//reg ack3=0;
//------------------------------------------------------------------------------
reg I2Cclk =1; // I2C clock
reg [8:0] clkclk=clock_div; // in order to divide 50MHz clock
reg sda_int =1; // making SDA high in initial state
reg [15:0] outreg =0;
reg [3:0] I2C_counter=0; // for giving the pointer address (000000-00(P1P0))
reg [3:0] bitaddrs7=4'b0001; // initializing via giving slave address(1001000-0(R/W))
reg [3:0] Rxcount=0;
reg [3:0] slaveaddrs=0; //receiving data from TMP 100
/// ----------------------------------------------------------------------------
reg [2:0] state =Rxidle ; // For State machine starting
assign scl =I2Cclk;// Generated Clock for I2C
assign temperature_out = outreg; // output from TMP 100
assign sda =sda_int; // Using SDA pin
assign ack_out=ack;
assign ack_count1=ack_count;
////------------------------------
always @ (posedge clk) /// --------------------- scl generation-----------------
begin
if(!chk)
begin
clkclk=clkclk - 1;
if(clkclk==0)
begin
I2Cclk=~I2Cclk;
clkclk =clock_div;
end
end
else I2Cclk=1'b1; end
////.............................................................................
always @(posedge I2Cclk )
if(reset)
begin
chk <=0;
outreg <=0;
I2C_counter <=0;
bitaddrs7 <=4'b0001;
Rxcount <=0;
slaveaddrs <=0;
ack <=0;
ack_count <=0;
I2Cclk <=1;
sda_int <=1;
clkclk <=clock_div;
end

always @(posedge I2Cclk )
begin
////....................................state machine............................
case (state)
//-------------------------------------------------------------------------------
Rxidle:
begin sda_int=1'b0; //---------------------start sda = 0
state =Rxstart;end
//-------------------------------------------------------------------------------
Rxstart:
begin
case(bitaddrs7)
// initial frame 1001000 Initializing slave address
1: begin
sda_int =1'b1;//---------------------sda 1
bitaddrs7=bitaddrs7+1; end

2: begin sda_int =1'b0;//---------------------sda 0
bitaddrs7=bitaddrs7+1; end

3: begin sda_int =1'b0;//---------------------sda 0
bitaddrs7=bitaddrs7+1; end

4: begin sda_int =1'b1;//---------------------sda 1
bitaddrs7=bitaddrs7+1; end

5: begin sda_int =1'b0;//---------------------sda 0
bitaddrs7=bitaddrs7+1; end

6: begin sda_int =1'b0;//---------------------sda 0
bitaddrs7=bitaddrs7+1; end

7: begin sda_int =1'b0;//---------------------sda=0
bitaddrs7=bitaddrs7+1; end

8: begin sda_int =1'b0;
ack_count=2'b00;
bitaddrs7=bitaddrs7+1; // R/W bit
end
9: begin if(sda==1'b0)
ack[0]=1;
state=RxPointeraddr; // Checking ack
end
endcase
end
//---------------------------------------------------------------------------------
RxPointeraddr:
// Pointer Address 000000-00(P1P0) for temperature register
begin
case(I2C_counter)
//---------------------sda = 0
0: begin sda_int =1'b0;
I2C_counter=I2C_counter+1;end
//---------------------sda = 0
1: begin sda_int =1'b0;
I2C_counter=I2C_counter+1;end
//---------------------sda = 0
2: begin sda_int =1'b0;
I2C_counter=I2C_counter+1; end
//---------------------sda = 0
3: begin sda_int =1'b0;
I2C_counter=I2C_counter+1; end
//---------------------sda = 0
4: begin sda_int =1'b0;
I2C_counter=I2C_counter+1;end
//---------------------sda = 0
5: begin sda_int =1'b0;
I2C_counter=I2C_counter+1;end
//---------------------sda = 0
6: begin sda_int =1'b0;
I2C_counter=I2C_counter+1;end
//---------------------sda = 0
7: begin sda_int =1'b0;
ack_count=2'b01;
I2C_counter=I2C_counter+1;end
8: begin if(sda==1'b0)
ack[1]=1'b0; state=Rxstart1;end // after pointer register sda line acknoledged by a low pulse
endcase
end
//-----------------------------------start+ slave address byte---------------------
Rxstart1:
begin

case(slaveaddrs)
// initial frame 1001000 Initializing slave address including start (case 0:)
0: begin sda_int=1'b0;
slaveaddrs=slaveaddrs+1; end
1: begin sda_int =1'b1;//---------------------sda 1
slaveaddrs=slaveaddrs+1; end

2: begin sda_int =1'b0;//---------------------sda 0
slaveaddrs=slaveaddrs+1; end

3: begin sda_int =1'b0;//---------------------sda 0
slaveaddrs=slaveaddrs+1; end

4: begin sda_int =1'b1;//---------------------sda 1
slaveaddrs=slaveaddrs+1; end

5: begin sda_int =1'b0;//---------------------sda 0
slaveaddrs=slaveaddrs+1; end

6: begin sda_int =1'b0;//---------------------sda 0
slaveaddrs=slaveaddrs+1; end

7: begin sda_int =1'b0;//---------------------sda=0
slaveaddrs=slaveaddrs+1; end

8: begin sda_int =1'b1;
slaveaddrs=slaveaddrs+1; // R/W bit high
ack_count=2'b10; end
9: begin if(sda==1'b0)
ack[2]=1;
state=Rxdata; // Checking ack
end
endcase
end


//----------------------------------Receiving Temperature Data --------------------------
Rxdata:
begin
case(Rxcount)
0: begin outreg[15]=sda;
Rxcount=Rxcount+1;end
1: begin outreg[14]=sda;
Rxcount=Rxcount+1;end
2: begin outreg[13]=sda;
Rxcount=Rxcount+1;end
3: begin outreg[12]=sda;
Rxcount=Rxcount+1;end
4: begin outreg[11]=sda;
Rxcount=Rxcount+1;end
5: begin outreg[10]=sda;
Rxcount=Rxcount+1;end
6: begin outreg[9]=sda;
Rxcount=Rxcount+1;end
7: begin outreg[8]=sda;
Rxcount=Rxcount+1;
ack_count=2'b11; end
// low pulse acknoledgment from TMP100
8: begin outreg[7]=sda;
if(!sda) ack[2]=1;
Rxcount=Rxcount+1;end

9: begin outreg[6]=sda ;
Rxcount=Rxcount+1;end
10: begin outreg[5]=sda ;
Rxcount=Rxcount+1;end
11: begin outreg[4]=sda;
Rxcount=Rxcount+1;end
12: begin outreg[3]=sda;
Rxcount=Rxcount+1;end
13: begin outreg[2]=sda;
Rxcount=Rxcount+1;end
14: begin outreg[1]=sda;
Rxcount=Rxcount+1;end

15: begin sda_int=1'b0;
// checking low pulse acknoledge frm TMP 100
state=Rxstop; end
endcase
end
//-----------------------------------------------------------------------------------------
Rxstop:
begin chk=1; sda_int=1'b1; end


endcase
end
endmodule




 

It's not a TMP100 specific problem. You have to keep the I2C timing defined in the specification (downloadable from NXP, if you possibly don't know it).

It's not a good idea to clock the design from SCL. You have to split a bus cycle in multiple phases, each with respective actions. A fourfold SCL clock is often used in synchronous I2C interface designs.

I don't see that SDA is tristated anywhere in your design, thus I doubt that you'll be able to receive any response from the slave.
 

It's not a TMP100 specific problem. You have to keep the I2C timing defined in the specification (downloadable from NXP, if you possibly don't know it).

It's not a good idea to clock the design from SCL. You have to split a bus cycle in multiple phases, each with respective actions. A fourfold SCL clock is often used in synchronous I2C interface designs.

I don't see that SDA is tristated anywhere in your design, thus I doubt that you'll be able to receive any response from the slave.


I am sorry!! I don't understand this statement "You have to split a bus cycle in multiple phases, each with respective actions. A fourfold SCL clock is often used in synchronous I2C interface designs", because I am new in Verilog. And also in test-bench I didn't provide any acknowledge that should done by TMP100, I just give the clock as shown below....
Do I need to make the scl for each and every step specifically ??


`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 10:55:28 08/22/2012
// Design Name: I2C
// Module Name: D:/programs/working directory/Temperature/I2Ct4.v
// Project Name: Temperature
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: I2C
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////

module I2Ct4;

// Inputs
reg clk;
reg reset;
// Outputs
wire scl;
wire [15:0] temperature_out;
wire [2:0] ack_out;
wire [1:0] ack_count1;

// Bidirs
wire sda;

// Instantiate the Unit Under Test (UUT)
I2C uut (
.sda(sda),
.scl(scl),
.temperature_out(temperature_out),
.clk(clk),
.ack_out(ack_out),
.ack_count1(ack_count1),
.reset(reset)
);

pullup(sda);
pullup(scl);


always
begin
#10;
clk=0;
#10;
clk=1;
end
initial
begin
reset=0;
end

endmodule
 

Refer to the SDA and SCL timing required by the I2C specification. To generate it in hardware, your bit level state machine will go through several states.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top