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.

[SOLVED] [moved] Can't get data from I2C slave register with FPGA

Status
Not open for further replies.
Hi,

previously you drove SDA = HIGH, This caused short circuit current, therefore there is the change that some device is damaged now.
Now that you say I2C bus voltage is 1.8V (is this within specification?) any SCL or SDA line protection diodes or the complete device may got damaged too.

Klaus
 

I checked device with evulation kit, fortunately It's not damaged and works properly.
Now I drive SDA and ACK bits with HIGH-Z
Test bench is below.
test_i2c.png
 

Hi,

i wonder about the blue lines.
It makes sense if this is the driver simulation only.

But in real circuit, there should be a valid voltage level. (Either HIGH by pullup, or LOW by master or slave LOW).

While the driver switches to HIGH-Z the bus is never HIGH-Z.


Klaus
 

You're right, there is valid voltage level in real circuit. I tested change in ack and data bit as shown scope out. Blue lines in the test bench are drived HIGH in real circuit.
Is driving SDA HIGH-Z when we expect to get data incorrect ?

DSC_0155.jpg DSC_0157.jpg
 

I wonder who is driving SDA low during the 9th clock cycle? That's not right. The 9th cycle is to read acknowledge, the slave would never change SDA while SCL is high, so I guess the master is doing something wrong.

DSC_0155.jpg

The simulated sequence also isn't correct, I don't see a repeated start before the read action.

Preferably, we would connect a slave simulation model in the test bench, now no one is answering. The test bench should also drive SDA with weak high level (h state) to simulate a pull-up resistor.

I see that you are apparently performing your test in a repeated loop. Take care that the slave is returning to idle state before the next start.
 

It appears to me the OP is still driving SDA high and not just driving it low only. Otherwise the simulation waveform in post #22 would have had hi-z everytime the SDA is high (given there is no weak H on the line).

I think they should post there current code so it can be reviewed for errors.
 

I revised verilog code according to you said. I sent 1 byte and wait 1 bit ACK. But still can't get any data from slave.
Circuit have pull up resistors.
True I2C address = 0x39
I drove SDA high or high-z when wait ACK or data.

Evalkit sent by producer scope output:
DSC_0158.jpg

Verilog implementation output
DSC_0159.jpg

Verilog code:
Code:
module i2cio3(
		input wire clk,
		inout wire sda,
		input wire reset,
		output wire scl,
		output reg [7:0] data,
		output reg [7:0] state,
		output wire i2c_clk
		
    );
	localparam STATE_IDLE				=0;	//00000	
	localparam STATE_START_WRITE		=1;	//00001	
	localparam STATE_I2C_ADD_CALL1	=2;	//00010	
	localparam STATE_RW1					=3;	//00011	
	localparam STATE_ACK1				=4;	//00100
	localparam STATE_REG_ADD1			=5;	//00101
	localparam STATE_ACK2				=6;	//00110
	localparam STATE_START_READ		=7;	//00111
	localparam STATE_I2C_ADD_CALL2	=8;	//01000
	localparam STATE_RW2 				=9;	//01001	
	localparam STATE_ACK3				=10;	//01010	
	localparam STATE_DATA				=11;	//01011	
	localparam STATE_ACK4				=12;	//01100	
	localparam STATE_STOP				=13;	//01101
	localparam STATE_REG_ADD			=14;	//01110
	localparam STATE_WAIT1				=15;	//01111
	localparam STATE_WAIT2				=16;	//10000
	localparam STATE_WAIT3				=17;	//10001
	localparam STATE_WAIT4				=18;	//10010
	localparam STATE_WAIT5				=19;	//10011
	localparam STATE_WAIT6				=20;	//10100
	localparam STATE_IDLE2				=21;	//10101
	
	 
	
	reg [7:0] addr;
	reg [6:0] adcall;
	reg [7:0] count;
	reg ack1;
	reg ack2;
	reg ack3;
	reg sda_reg;
	reg scl_reg;
	reg [1:0] scl_enable;
	
	
	reg rw1;
	reg rw2;
	reg sclkcnt;
	initial begin
		scl_enable<=0;
		sclkcnt <=1;
		sda_reg<=1;
		scl_reg<=1;
	end
	
	
	

	assign sda=sda_reg;
	assign scl=scl_reg;
	

	i2c_clk_divider instance_name (
    .clk(clk), 
    .reset(reset), 
    .i2c_clk2(i2c_clk2),
	 .i2c_clk(i2c_clk)
    );
	

	
		
		
//		always @(i2c_clk)begin
//		if(scl_enable==1) scl_reg<=~i2c_clk;
//		else if(scl_enable==0) scl_reg<=1;
//		else scl_reg<=0;
//		end
		
	
                                      
	
	


	
	
	
	
	always @(posedge i2c_clk2)begin
		
		if(reset==1)begin
		scl_enable<=0;
		sda_reg<=1;
		state<=STATE_IDLE;
		adcall<=7'b0111001;
		addr<=8'b10011000;//'h0x98;
		rw1<=0;
		rw2<=1;
		data<=8'b10101010;
		end
		else begin
			case(state)
			
				STATE_IDLE:	
					begin 	//IDDLE
							scl_enable<=0;
						if(sclkcnt<=0)begin
							state<=STATE_START_WRITE;
							sclkcnt<=1;
							scl_reg<=1;
							sda_reg<=1;
							end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
							sda_reg<=1;
						end
					end 		
					
				STATE_START_WRITE:
					begin		//START
							scl_enable <= 0;
							count<=6;
						if(sclkcnt<=0)begin
							state<=STATE_WAIT1;
							sclkcnt<=1;
							sda_reg<=0;
							scl_reg<=0;
							end
						else begin
							sclkcnt<=sclkcnt-1;
							sda_reg<=0;
							scl_reg<=1;
						end
					end
					
				STATE_WAIT1:
					begin
							sda_reg<=0;
							scl_enable<=2;
						if(sclkcnt<=0)begin
							state<=STATE_I2C_ADD_CALL1;
							sclkcnt<=1;
							scl_reg<=0;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end
						
					end
				
				STATE_I2C_ADD_CALL1:
					begin
						
						scl_enable<=1;
						sda_reg<=adcall[count];
						if(count==0)begin
								if(sclkcnt<=0)begin
									state<=STATE_RW1;
									sclkcnt<=1;
									scl_reg<=~i2c_clk;
								end
								else begin
									sclkcnt<=sclkcnt-1;
									scl_reg<=~i2c_clk;
								end
						end else begin 
								if(sclkcnt<=0)begin
										count<=count-1;
										sclkcnt<=1;
										scl_reg<=~i2c_clk;
								end
								else begin
									sclkcnt<=sclkcnt-1;
									scl_reg<=~i2c_clk;
								end
						end
					end
				STATE_RW1:
					begin
						
							scl_enable<=1;
							count<=7;
							sda_reg<=rw1;
						if(sclkcnt<=0)begin
							state<=STATE_ACK1;
							sclkcnt<=1;
							scl_reg<=~i2c_clk;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=~i2c_clk;
						end
						
					end
					
				STATE_ACK1:
					begin
						
							scl_enable<=1;
							sda_reg<=1;
						if(sclkcnt<=0)begin
							state<=STATE_WAIT2;
							sclkcnt<=1;
							scl_reg<=~i2c_clk;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=~i2c_clk;
						end
					end
					
				STATE_WAIT2:
					begin
						scl_enable<=2;
						sda_reg<=1;
						if(sclkcnt<=0)begin
							state<=STATE_REG_ADD1;
							sclkcnt<=1;
							scl_reg<=0;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end
					end
				
					
				STATE_REG_ADD1:
					begin
						sda_reg<=addr[count];
						scl_enable<=1;
						if(count==0)begin
								if(sclkcnt<=0)begin
									state<=STATE_ACK2;
									sclkcnt<=1;
									scl_reg<=~i2c_clk;
								end
								else begin
									sclkcnt<=sclkcnt-1;
									scl_reg<=~i2c_clk;
								end
						end else begin 
								if(sclkcnt<=0)begin
									count<=count-1;
									sclkcnt<=1;
									scl_reg<=~i2c_clk;
								end
								else begin
									sclkcnt<=sclkcnt-1;
									scl_reg<=~i2c_clk;
								end
						end
					end
							
				STATE_ACK2:
					begin
						sda_reg<=1;
						scl_enable<=1;	
						if(sclkcnt<=0)begin
						state<=STATE_WAIT3;
						sclkcnt<=1;
						scl_reg<=~i2c_clk;
						end
						else begin
						sclkcnt<=sclkcnt-1;
						scl_reg<=~i2c_clk;
						end
					end
				
				STATE_WAIT3:
					begin
						scl_enable<=0;
						sda_reg<=1;
						if(sclkcnt<=0)begin
						state<=STATE_START_READ;
						sclkcnt<=1;
						scl_reg<=1;
						end
						else begin
						sclkcnt<=sclkcnt-1;
						scl_reg<=1;
						end
					end
					
				STATE_START_READ:
					begin
						sda_reg<=0;
						scl_enable<=1;
						count<=6;
						if(sclkcnt<=0)begin
							state<=STATE_WAIT4;
							sclkcnt<=1;
							scl_reg<=0;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end
					end
				
					
				STATE_WAIT4:
					begin
						scl_enable<=2;
						sda_reg<=1;
						
						if(sclkcnt<=0)begin
							state<=STATE_I2C_ADD_CALL2;
							sclkcnt<=1;
							scl_reg<=0;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end
					end
					
				STATE_I2C_ADD_CALL2:	
				begin
					scl_enable<=1;
						sda_reg<=adcall[count];
						if(count==0)begin
								if(sclkcnt<=0)begin
									state<=STATE_RW2;
									sclkcnt<=1;
									scl_reg<=~i2c_clk;
								end
								else begin
									sclkcnt<=sclkcnt-1;
									scl_reg<=~i2c_clk;
								end
						end else begin 
								if(sclkcnt<=0)begin
										count<=count-1;
										sclkcnt<=1;
										scl_reg<=~i2c_clk;
								end
								else begin
									sclkcnt<=sclkcnt-1;
									scl_reg<=~i2c_clk;
								end
						end
					end
					
				STATE_RW2:
					begin		//BIT 5
						sda_reg<=rw2;
						scl_enable<=1;
						if(sclkcnt<=0)begin
							state<=STATE_ACK3;
							sclkcnt<=1;
							scl_reg<=~i2c_clk;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=~i2c_clk;
						end
					end
				
				STATE_ACK3:
					begin
						sda_reg<=1;
						
						scl_enable<=1;
						count<=7;
						if(sclkcnt<=0)begin
							state<=STATE_WAIT5;
							sclkcnt<=1;
							scl_reg<=~i2c_clk;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=~i2c_clk;
						end
					end
				
				STATE_WAIT5:
					begin
						scl_enable<=2;
						sda_reg<=1;
						
						if(sclkcnt<=0)begin
							state<=STATE_DATA;
							sclkcnt<=1;
							scl_reg<=0;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end
					end
				
				STATE_DATA:
					begin
						sda_reg<=1;
						scl_enable<=1;
						data[count]<=sda_reg;
						if(count==0)begin
								if(sclkcnt<=0)begin
									state<=STATE_ACK4;
									sclkcnt<=1;
									scl_reg<=~i2c_clk;
								end
								else begin
									sclkcnt<=sclkcnt-1;
									scl_reg<=~i2c_clk;
								end
						end else begin 
								if(sclkcnt<=0)begin
									count<=count-1;
									sclkcnt<=1;
									scl_reg<=~i2c_clk;
								end
								else begin
									sclkcnt<=sclkcnt-1;
									scl_reg<=~i2c_clk;
								end
						end
						
					end
				
				STATE_ACK4:
					begin
						sda_reg<=0;
						scl_enable<=1;
						if(sclkcnt<=0)begin
							state<=STATE_WAIT6;
							sclkcnt<=1;
							scl_reg<=~i2c_clk;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=~i2c_clk;
						end
					end
					
				STATE_WAIT6:
					begin
						scl_enable<=2;
						sda_reg<=1;
						
						if(sclkcnt<=0)begin
							state<=state<=STATE_STOP;
							sclkcnt<=1;
							scl_reg<=0;
						end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end
					end
					
				STATE_STOP:
					begin
						sda_reg<=1;
						scl_enable<=0;
						state<=STATE_IDLE;
					end
			endcase
		end//end else
	
	end	// end always
	




endmodule
 

Hi,

EVALKIT waveform seems to be correct.

VERILOG implementation waveform is NOT CORRECT.
--> It seems you still driving SDA and SCL actively HIGH.
--> You risk to damage something.
--> It is impossible to READ with this implementation. Neiter ACK nor data.


Klaus
 

How must I drive SDA and SCL lines ? Must I use z and x instead of 1 and 0 ?
 

Hi,

as said multiple times before :

* NEVER drive it HIGH, NEVER drive it 1
* Drive it LOW (0) only when you want it to be low
* in any other case: don´t drive it at all. Leave it High-Z, leave it floating. --> Then the external pullup generates a HIGH as long as no other device drives it LOW.

For both SCL and SDA.

These are basics of the I2C bus.
Also said multiple times before: Read the I2C specifications!

Klaus
 

This is the way you must drive SDA and SCL signal

sda <= 'Z' when (sda_signal='1') else '0';
scl <= 'Z' when (scl_signal='1') else '0';

When SDA is as an output, set it to 'Z' to let the pullup to bring it to '1', otherwise set it to '0' for a real '0'. As an input, set it to 'Z' and the slave will drive it to '0' or let the pullup to bring it to '1'.
 
Hi,

As an input, set it to 'Z' and the slave will drive it to '0' or let the pullup to bring it to '1'.

There is no need to switch as "input" or "output".
You may continously have an input (buffer) at the SCL and SDA pins. I mean: No need to disable the input at any time.

It is a good technique to read back both pin states continously.
For SCL: when the slave uses "clock stretching"
For SDA: for bus arbitration in multi master configuration. To read slave ACK state. To read slave data.

Klaus
 

Thank you very much for your suggestions and helps.
I revised again verilog code, and I can get ack when I sent both Device Address and Register Address.
Repeated start condition have been adapted into code, Outputs and verilog code below.

DSC_0440.jpgDSC_0441.jpg

There's some mistakes when I sent second I2C address and read data. Maybe ACK bit got early.

Code:
module i2cio3(
		input wire clk,
		inout wire sda,
		input wire reset,
		output wire scl,
		output reg [7:0] data,
		output reg [7:0] state,
		output wire i2c_clk
		
    );
	localparam STATE_IDLE				=0;	//00000	
	localparam STATE_START_WRITE		=1;	//00001	
	localparam STATE_I2C_ADD_CALL1	=2;	//00010	
	localparam STATE_RW1					=3;	//00011	
	localparam STATE_ACK1				=4;	//00100
	localparam STATE_REG_ADD1			=5;	//00101
	localparam STATE_ACK2				=6;	//00110
	localparam STATE_START_READ		=7;	//00111
	localparam STATE_I2C_ADD_CALL2	=8;	//01000
	localparam STATE_RW2 				=9;	//01001	
	localparam STATE_ACK3				=10;	//01010	
	localparam STATE_DATA				=11;	//01011	
	localparam STATE_ACK4				=12;	//01100	
	localparam STATE_STOP				=13;	//01101
	localparam STATE_REG_ADD			=14;	//01110
	localparam STATE_WAIT1				=15;	//01111
	localparam STATE_WAIT2				=16;	//10000
	localparam STATE_WAIT3				=17;	//10001
	localparam STATE_WAIT4				=18;	//10010
	localparam STATE_WAIT5				=19;	//10011
	localparam STATE_WAIT6				=20;	//10100
	localparam STATE_IDLE2				=21;	//10101
	localparam STATE_REPEATED_START	=22;  //10110
	localparam STATE_WAIT7				=23;
	
	 
	
	reg [7:0] addr;
	reg [6:0] adcall;
	reg [7:0] count;
	reg ack1;
	reg ack2;
	reg ack3;
	reg sda_reg;
	reg scl_reg;
	reg [1:0] scl_enable;
	
	
	reg rw1;
	reg rw2;
	reg [3:0] sclkcnt;
	initial begin
		scl_enable<=0;
		sclkcnt <=3;
		sda_reg<=1;
		scl_reg<=1;
	end
	
	
	

	assign sda=(sda_reg==1)?  1'bz:1'b0;
	assign scl=(scl_reg==1)?  1'bz:1'b0;
	

	i2c_clk_divider instance_name (
    .clk(clk), 
    .reset(reset), 
    .i2c_clk2(i2c_clk2),
	 .i2c_clk(i2c_clk)
    );
	

	
		
		
//		always @(i2c_clk)begin
//		if(scl_enable==1) scl_reg<=~i2c_clk;
//		else if(scl_enable==0) scl_reg<=1;
//		else scl_reg<=0;
//		end
		
	
                                      
	
	


	
	
	
	
	always @(posedge i2c_clk2)begin
		
		if(reset==1)begin
		scl_enable<=0;
		sda_reg<=1;
		state<=STATE_IDLE;
		adcall<=7'b0111001;
		addr<=8'b10011001;//'h0x98;
		rw1<=0;
		rw2<=1;
		data<=8'b11111111;
		end
		else begin
			case(state)
			
				STATE_IDLE:	
					begin 	
						if(sclkcnt<=0)begin
							state<=STATE_START_WRITE;
							sclkcnt<=3;
							scl_reg<=1;
							sda_reg<=1;
							end
						else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
							sda_reg<=1;
						end
					end 		
					
				
				STATE_START_WRITE:
					begin		//START
						scl_enable <= 0;
						count<=6;
						if(sclkcnt==3)begin
							sda_reg<=1;
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==2)begin
							sda_reg<=0;
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
								end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
							sda_reg<=0;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							sda_reg<=0;
							state<=STATE_WAIT1;
						end
					end
					
				
				STATE_WAIT1:
					begin
						sda_reg<=0;
						scl_enable<=2;
						if(sclkcnt<=0)begin
							state<=STATE_I2C_ADD_CALL1;
							sclkcnt<=3;
							scl_reg<=0;
						end else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end
					end
				
				STATE_I2C_ADD_CALL1:
					begin
						scl_enable<=1;
						if(count==0)begin
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=adcall[count];
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else begin
								state<=STATE_RW1;
								sclkcnt<=3;
								scl_reg<=0;
							end
						end else begin 
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=adcall[count];
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else begin
								sclkcnt<=3;
								scl_reg<=0;
								count<=count-1;
							end
						end
					end
	

				STATE_RW1:
					begin
						scl_enable<=1;
						count<=7;
						if(sclkcnt==3)begin
							sda_reg<=rw1;
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							state<=STATE_ACK1;
						end
						
					end
					
				STATE_ACK1:
					begin
						scl_enable<=1;
						sda_reg<=1;
						if(sclkcnt==3)begin
							sclkcnt<=sclkcnt-1;	
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							state<=STATE_WAIT2;
						end
					end

					
				STATE_WAIT2:
					begin
						scl_enable<=2;
						if(sclkcnt==3)begin
							sclkcnt<=sclkcnt-1;
							sda_reg<=0;
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							state<=STATE_REG_ADD1;
						end
					end
				
					
				STATE_REG_ADD1:
					begin
						scl_enable<=1;
						if(count==0)begin
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=addr[count];
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else begin
								state<=STATE_ACK2;
								sclkcnt<=3;
								scl_reg<=0;
							end
						end else begin 
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=addr[count];
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else begin
								sclkcnt<=3;
								scl_reg<=0;
								count<=count-1;
							end
						end
					end
							
				
				STATE_ACK2:
					begin
						scl_enable<=1;	
						sda_reg<=1;
						if(sclkcnt==3)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							state<=STATE_WAIT3;
						end
					end
				
				STATE_WAIT3:
					begin
						scl_enable<=0;
						if(sclkcnt==3)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
							sda_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
							sda_reg<=0;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
							sda_reg<=1;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							sda_reg<=1;
							state<=STATE_REPEATED_START;
						end
					end
					
	

				STATE_REPEATED_START:
					begin
						scl_enable<=0;
						if(sclkcnt==3)begin
							sclkcnt<=sclkcnt-1;
							sda_reg<=1;
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							sda_reg<=1;
							scl_reg<=1;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
							sda_reg<=1;
						end else begin
							sclkcnt<=3;
							scl_reg<=1;
							sda_reg<=1;
							state<=STATE_START_READ;
						end
					end
				
				
				STATE_START_READ:
					begin
						count<=6;
						if(sclkcnt==3)begin
							sda_reg<=1;
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==2)begin
							sda_reg<=0;
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
							sda_reg<=0;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							sda_reg<=0;
							state<=STATE_WAIT4;
						end
					end
				
					
				STATE_WAIT4:
					begin
						sda_reg<=0;
						if(sclkcnt<=0)begin
							state<=STATE_I2C_ADD_CALL2;
							sclkcnt<=3;
							scl_reg<=0;
						end else begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end
					end
					
				
				STATE_I2C_ADD_CALL2:	
					begin
						if(count==0)begin
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=adcall[count];
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else begin
								state<=STATE_RW2;
								sclkcnt<=3;
								scl_reg<=0;
							end
						end else begin 
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=adcall[count];
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
							end else begin
								sclkcnt<=3;
								scl_reg<=0;
								count<=count-1;
							end
						end
					end
					
				
				STATE_RW2:
					begin	
						
						if(sclkcnt==3)begin
							sda_reg<=rw2;
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							state<=STATE_ACK3;
						end
					end
				
				STATE_ACK3:
					begin
						count<=7;
						sda_reg<=1;
						if(sclkcnt==3)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							state<=STATE_WAIT5;
						end
					end
				
				
				STATE_WAIT5:
					begin
						count<=7;
						if(sclkcnt==3)begin
							sclkcnt<=sclkcnt-1;
							sda_reg<=0;
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							state<=STATE_DATA;
						end
					end
				
				
				STATE_DATA:
					begin		
						if(count==0)begin
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=1;
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
								sda_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
								sda_reg<=1;
							end else begin
								state<=STATE_ACK4;
								sclkcnt<=3;
								scl_reg<=0;
								sda_reg<=1;
							end
						end else begin 
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=1;
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
								sda_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
								sda_reg<=1;
							end else begin
								sclkcnt<=3;
								sda_reg<=1;
								scl_reg<=0;
								count<=count-1;
							end
						end
					end
				
				
				STATE_ACK4:
					begin
						if(sclkcnt==3)begin
							sda_reg<=1;
							sclkcnt<=sclkcnt-1;
							scl_reg<=0;
						end else if(sclkcnt==2)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else if(sclkcnt==1)begin
							sclkcnt<=sclkcnt-1;
							scl_reg<=1;
						end else begin
							sclkcnt<=3;
							scl_reg<=0;
							state<=STATE_WAIT6;
						end
					end
					
		
				STATE_WAIT6:
						begin
							scl_enable<=0;
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								sda_reg<=0;
								scl_reg<=0;
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								sda_reg<=0;
								scl_reg<=0;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=0;
								sda_reg<=0;
							end else begin
								sclkcnt<=3;
								scl_reg<=0;
								sda_reg<=0;
								state<=STATE_STOP;
							end
						end
						
				STATE_STOP:
						begin
							if(sclkcnt==3)begin
								sclkcnt<=sclkcnt-1;
								sda_reg<=0;
								scl_reg<=1;
							end else if(sclkcnt==2)begin
								sclkcnt<=sclkcnt-1;
								sda_reg<=0;
								scl_reg<=1;
							end else if(sclkcnt==1)begin
								sclkcnt<=sclkcnt-1;
								scl_reg<=1;
								sda_reg<=1;
							end else begin
								sclkcnt<=3;
								scl_reg<=1;
								sda_reg<=1;
								state<=STATE_IDLE;
							end
						end
			endcase
		end//end else
		
		
		
	
	end	// end always
	




endmodule
 

Hi,

just of your scope picture i doubt there is high-z.
It still seems to be actively driven high.

I´m not falmiliar with VERILOG.
but i can´t find where you read the status of (9th bit) SDA as ACK.
and i can´t find where you switch SCL and sda high-z.
Can you help me to find that in your code?

Klaus
 

I drove SDA high z and 0, otherwise I can't communicate with device. I can get ACK in first pic which I sent device address and register address.
But I can't get proper data in second pic. Maybe there is something wrong in start condition.

Read status in states STATE_ADD_CALL2, RW2 and ACK3.
I sent this bits in this three states.

SDA : 0000 0111 1111 1111 1000 0000 0111 1111 1111
SCL : 0011 0011 0011 0011 0011 0011 0011 0011 0011
Bitn : ad[6] ad[5] ad[4] ad[3] ad[2] ad[1] ad[0] rw=1 ACK





Device's address is 0x39.
 

I defined scl high-z or 0.

assign sda=(sda_reg==1)? 1'bz:1'b0;
assign scl=(scl_reg==1)? 1'bz:1'b0;
 

I defined scl high-z or 0.

assign sda=(sda_reg==1)? 1'bz:1'b0;
assign scl=(scl_reg==1)? 1'bz:1'b0;

It should be high when no data transfer.

- - - Updated - - -

I defined scl high-z or 0.

assign sda=(sda_reg==1)? 1'bz:1'b0;
assign scl=(scl_reg==1)? 1'bz:1'b0;

First of all your hardware configuration should be like this.
 

Attachments

  • Hardwareconfiguration.pdf
    33.3 KB · Views: 76

It should be high when no data transfer.

You should also read the (3.1.1 defines the signals SCL and SDA). It's never driven high it's always set to Hi-Z and a pullup is used to generate a high, the I2C is only driven low.

Only SCL can be a push-pull driver if there is only master and there is no clock stretching allowed.
 

You should also read the I2C spec. It's never driven high it's always set to Hi-Z and a pullup is used to generate a high, the I2C is only driven low.

Yes right but in FPGA there is no I2C, you have to develop it using hardware programming, that why all this we have to consider in software.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top