Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Altera_Forum
Honored Contributor I
2,123 Views

I2C read of De0 nano accelerometer

Hello everyone, 

I am using de0 nano and would like to try I2C read of accelerometer(ADXL345) that embedded in de0 nano. 

So I take it that I2C read has the following sequence: 

1) generate start signal 

2) write slave address(0011101) + write bit(0) 

3) receive acknowledge from slave 

4) write memory location(register with add 00110000 has reset value of 00000010) 

5) receive acknowledge from slave 

6) generate repeated start signal 

7) write slave address + read bit(1) 

8) receive acknowledge from slave 

9) read byte from slave 

10) write no acknowledge (NACK) to slave, indicating end of transfer 

11) generate stop signal 

 

Everything's going fine until step 9.The value ,that was read at step 9, is 11111111. 

I expect the data value to be 00000010 because it is the reset value of register 00110000. 

I generate clock of 100 hz for the whole operation because the default/reset value of register BW_Rate is 00001010 (this register control the "output data rate") which translate that output data rate is 100hz.  

Could someone give me an advice to be able to read the correct data? 

Your help is fully appreciated.
0 Kudos
21 Replies
Altera_Forum
Honored Contributor I
123 Views

I wonder if ADXL support clock stretching? If yes, in what condition should we apply it.  

I personally think that clock stretching is not needed in my case because there is no sign that the adxl has ever hold the I2C clock low. It can be seen because I am using signaltap2 with clock 200hz(2 times of the clock that I generated for the reading of ADXL)
Altera_Forum
Honored Contributor I
123 Views

This is my coding. Please somebody out there help me. 

 

// ADXL clock= 500,000samples of 50Mhz/100Hz 

// ADXL address= 0x1D/11101 

module ADXL_Read( 

clk_50, //clock 50Mhz// 

key, 

I2C_sclk, 

I2C_sdat, 

); 

 

input clk_50; 

input [1:0] key; 

inout I2C_sclk; 

inout I2C_sdat; 

 

reg I2C_sdat; 

reg [18:0] counter; 

reg [18:0] counter2; 

reg [1:0] q;  

reg [1:0] q2; 

 

wire reset_n; 

reg GO; 

reg sclk; 

reg [6:0] sd_counter;  

reg [6:0] slave_add = 7'b0011101; // DEFINE SLAVE ADDRESS 

reg [7:0] register_add = 8'b110000; // DEFINE REGISTER ADDRESS 

reg [7:0] data; //Data that is read 

 

initial 

begin 

counter = 3'b0; 

data = 8'b0; 

end 

 

assign reset_n= key[0]; 

 

// 50MHz clock is too fast for the our devive 

// therefore slower clk need to be generated 

 

always @(posedge clk_50) 

begin 

if (counter == 18'b0) // if counter is 0 

begin 

q = 2'b01; 

end 

else if (counter == 19'b111101000010010000) // if counter is the desired value(has the same priority as earlier if) 

begin 

q = 2'b00; 

end 

else  

begin 

q<= q; 

end 

end 

 

always @(posedge clk_50) 

begin 

if (q == 2'b00) 

begin 

counter <= counter -1; 

end 

if (q == 2'b01) 

begin 

counter <= counter +1; 

end 

end 

 

//Clk for the Signaltap2 

// Notify the moment counter is at the desired value or at 0  

always @(posedge clk_50) 

begin 

if (counter2 == 18'b0) // if counter is 0 

begin 

q2 = 2'b01; 

end 

else if (counter2 == 19'b11110100001001000) // if counter is the desired value(has the same priority as earlier if) 

begin 

q2 = 2'b00; 

end 

else  

begin 

q2<= q2; 

end 

end 

 

always @(posedge clk_50) 

begin 

if (q2 == 2'b00) 

begin 

counter2 <= counter2 -1; 

end 

if (q2 == 2'b01) 

begin 

counter2 <= counter2 +1; 

end 

end  

// key[0] is to reset the whole operation 

// key[1] is to give a start signal 

always@(posedge q[0] or negedge reset_n) 

begin  

if (!reset_n) 

GO <= 0; 

else  

if (!key[1]) 

GO <= 1; 

end 

 

always@ (posedge q[0] or negedge reset_n) 

begin  

if(!reset_n) 

sd_counter <= 6'b0; 

else  

begin  

if (!GO) 

sd_counter <= 0; 

else 

if (sd_counter < 44) //sd_counter maximum 

sd_counter <= sd_counter + 1; 

end 

end 

 

always@ (posedge q[0] or negedge reset_n) 

begin 

if (!reset_n) 

begin 

sclk <= 1; 

I2C_sdat <= 1; 

end 

else 

case (sd_counter) 

 

6'd0 : begin I2C_sdat<=1; sclk<=1;end 

 

//START 

6'd1 : I2C_sdat <= 0; 

6'd2 : sclk <= 0; 

 

//SLAVE ADDR+Write(Control Byte)7'b0011101 

6'd3 : I2C_sdat <= slave_add[6]; 

6'd4 : I2C_sdat <= slave_add[5]; 

6'd5 : I2C_sdat <= slave_add[4]; 

6'd6 : I2C_sdat <= slave_add[3]; 

6'd7 : I2C_sdat <= slave_add[2]; 

6'd8 : I2C_sdat <= slave_add[1]; 

6'd9 : I2C_sdat <= slave_add[0]; 

6'd10 : I2C_sdat <= 0; //Write(0) 

6'd11 : I2C_sdat <= 1'bz;//Slave ACK 

 

//SUB ADDR(WORD ADDRESS)8'b110000 

6'd12 : I2C_sdat <= register_add[7]; 

6'd13 : I2C_sdat <= register_add[6]; 

6'd14 : I2C_sdat <= register_add[5]; 

6'd15 : I2C_sdat <= register_add[4]; 

6'd16 : I2C_sdat <= register_add[3]; 

6'd17 : I2C_sdat <= register_add[2]; 

6'd18 : I2C_sdat <= register_add[1]; 

6'd19 : I2C_sdat <= register_add[0]; 

6'd20 : I2C_sdat <= 1'bz;//Slave ACK 

 

//START 

6'd21 : begin I2C_sdat <= 1; sclk<=1; end 

6'd22 : I2C_sdat <= 0; 

 

//SLAVE ADDR+Read(CONTROL BYTE) 

6'd23 : I2C_sdat <= slave_add[6];  

6'd24 : I2C_sdat <= slave_add[5]; 

6'd25 : I2C_sdat <= slave_add[4]; 

6'd26 : I2C_sdat <= slave_add[3]; 

6'd27 : I2C_sdat <= slave_add[2]; 

6'd28 : I2C_sdat <= slave_add[1]; 

6'd29 : I2C_sdat <= slave_add[0]; 

6'd30 : I2C_sdat <= 1; //Read(1) 

6'd31 : I2C_sdat <= 1'bz;//Slave ACK 

 

//Data read(DATA) 

//Data byte 1 

6'd32 : I2C_sdat <= 1'bz; 

6'd33 : I2C_sdat <= 1'bz; 

6'd34 : I2C_sdat <= 1'bz; 

6'd35 : I2C_sdat <= 1'bz; 

6'd36 : I2C_sdat <= 1'bz; 

6'd37 : I2C_sdat <= 1'bz; 

6'd38 : I2C_sdat <= 1'bz; 

6'd39 : I2C_sdat <= 1'bz; 

6'd40 : I2C_sdat <= 1'b1;//Master ACK 

 

//stop 

6'd41 : begin I2C_sdat <= 1'b0; sclk <= 1'b1; end  

6'd42 : I2C_sdat <= 1'b1;  

endcase 

end 

 

assign I2C_sclk = (((sd_counter >= 4)&(sd_counter <= 20))|((sd_counter >=24)&(sd_counter <=42)))? ~q[0] : sclk; 

 

endmodule
Altera_Forum
Honored Contributor I
123 Views

Too bad:( nobody's willing to help me in my thesis project. 

Come on anyone help me:D
Altera_Forum
Honored Contributor I
123 Views

First using generated logic signals inside FPGAs isn't a good idea. If you have glitches on the signal the FPGA logic could interpret it as a new clock cycle and you would loose some cycles. 

It is best to do everything in a single always block and use a counter to generate both the clock and data signals from the same place, changing them only when the counter reaches specific values. 

Do you actually try to read the acknowledge pulse from the I2C slave? You should read it to be sure it has actually recognized its address on the I2C bus first.
Altera_Forum
Honored Contributor I
123 Views

Thank you very much for your reply, Daixiwen. 

I don't really get it.  

Do you mean the "generated clock" when you say "generated logic signal"("First using generated logic signals inside FPGAs isn't a good idea.")? 

I need to generate slower clock because the accelerometer output data rate is 100hz(by default) and my fpga has 50Mhz clock. 

I will try to remake my program by trying to use always block as less as possible(although I am not sure that I can do it with only a single always block). 

 

"Do you actually try to read the acknowledge pulse from the I2C slave? You should read it to be sure it has actually recognized its address on the I2C bus first." 

 

Yeah I am actually trying to read ack pulse from ADXL to make sure that the ADXL has already listened the data from master(at 6'd11, 6'd20, 6'd31) and at 6'd40 the master send the ack pulse to the slave.(I believe this is the standard timing diagram for I2C read protocol) 

 

Could you give more hint to solve this problem? 

Thank you so much for your help.
Altera_Forum
Honored Contributor I
123 Views

Yes sorry, I forgot to finish my sentence. I meant "using generated logic signals as a clock inside FPGAs isn't a good idea". You should generate both I2C_sclk and I2C_sdat in the same always block, clocked with clk_50. You can use a counter to gerenate the I2C_sclk signal and only execute your state machine code when the counter reaches a specific value. 

I've asked about acknowledge read because I don't see anything in your code that does that. Sure you put the I2C_sdat in high impedance mode, but you don't seem to do anything to read back the signal value and check that the slave indeed acknowledged its address. Did you check it with signaltap?
Altera_Forum
Honored Contributor I
123 Views

Thanks again Daixiwen. 

Yeah I use signaltap2 to check my coding. It shows that the slave grounded the pulse at 6'd11, 6'd20, 6'd31(low pulse instead of high pulse). If the slave do not acknowledge the master, it will give the high pulse at 6'd11, 6'd20, 6'd31.  

If you think I am wrong at the acknowledge read pulse, how do you suggest me to get the right acknowledge read?  

Thank you so much for your quick response, Daixiwen.
Altera_Forum
Honored Contributor I
123 Views

Yes you are right, this means the slave is acknowledging properly. But if in your application you need to know if the slave answered properly without having to use SignalTap, it could be a good idea to read this value in your code and change an output pin such as "SlaveOK" or "SlaveError" depending on the results. 

The next thing to check is that you are reading the correct register, and indep check if the slave is doing any clock stretching. For that you can change your code so that the clock output is set to 'z' instead of '1' (you do have external pull-ups on both the I2C clock and data, don't you?) and see with signaltap if the slave is keeping scl low for any reason.
Altera_Forum
Honored Contributor I
123 Views

Thanks Daixiwen. 

Now I am remaking my program and trying to follow your suggestion. 

Tomorrow I will have finished it and will post it here. 

Thank you.
Altera_Forum
Honored Contributor I
123 Views

Here is my new code: 

 

// ADXL clock= 500,000samples of 50Mhz/100Hz 

// ADXL address= 0x1D/11101 (alt address pin grounded) 

module ADXL_Read(clk_50, I2C_sclk, I2C_sdat, key0, key1, clk_st); 

 

input clk_50; 

output I2C_sclk; 

inout I2C_sdat; 

input key0; //Trigger0 to reset 

input key1; //Trigger1 to begin 

output clk_st; 

 

reg [18:0] a; 

reg [18:0] b; 

reg clk; //Clk for slave 

reg clk_signaltap; //Clk for signaltap2 

reg q; //Register for Trigger 

reg [10:0] step; 

reg [6:0] sl_ad = 7'b0011101; // Slave Address 

reg [7:0] reg_ad = 8'b110000; // Register Address 

reg [7:0] data1; // Databyte#1 

reg sclk; 

reg sdat; 

 

initial begin 

step = 0; 

q = 0; 

end 

 

always @(posedge clk_50) 

begin 

if(a == 250000) //Clock for Slave with sample 2a 

begin 

clk = ~clk; 

a = 1; 

end 

else 

a = a + 1; 

 

//Signaltap begin 

if(b == 125000) //Clock for Signaltap2 

begin 

clk_signaltap = ~clk_signaltap; 

b = 1; 

end 

else 

b = b + 1; 

end 

 

//Signaltap end 

always @(posedge clk_50) //Trigger Condition 

case({key0, key1}) 

2'b00 : q <= q; 

2'b10 : q <= 1; //Set 

2'b01 : q <= 0; //Reset 

endcase 

 

always @(posedge clk) 

begin 

if (q == 1) 

begin 

case(step) 

//Initial 

0: begin sclk = 1; sdat = 1; step = 1; end 

//1.Start 

1: begin sclk = 1; sdat = 0; step = 2; end 

2: begin sclk = 0; sdat = 0; step = 3; end 

//2.Slave add 

3: begin sclk = 1; sdat = sl_ad[6]; step = 4; end 

4: begin sclk = 0; sdat = sl_ad[6]; step = 5; end 

5: begin sclk = 1; sdat = sl_ad[5]; step = 6; end 

6: begin sclk = 0; sdat = sl_ad[5]; step = 7; end 

7: begin sclk = 1; sdat = sl_ad[4]; step = 8; end 

8: begin sclk = 0; sdat = sl_ad[4]; step = 9; end 

9: begin sclk = 1; sdat = sl_ad[3]; step = 10; end 

10: begin sclk = 0; sdat = sl_ad[3]; step = 11; end 

11: begin sclk = 1; sdat = sl_ad[2]; step = 12; end 

12: begin sclk = 0; sdat = sl_ad[2]; step = 13; end 

13: begin sclk = 1; sdat = sl_ad[1]; step = 14; end 

14: begin sclk = 0; sdat = sl_ad[1]; step = 15; end 

15: begin sclk = 1; sdat = sl_ad[0]; step = 16; end 

16: begin sclk = 0; sdat = sl_ad[0]; step = 17; end 

//3.sdat = 0 

17: begin sclk = 1; sdat = 0; step = 18; end 

18: begin sclk = 0; sdat = 0; step = 19; end 

//4.Acknowledge 

19: begin sclk = 1; sdat = 1'bz; step = 20; end 

20: begin sclk = 0; sdat = 1'bz; if (sdat == 1) step = 19; else step = 21; end 

//5.Reg add 

21: begin sclk = 1; sdat = reg_ad[7]; step = 22; end //7 

22: begin sclk = 0; sdat = reg_ad[7]; step = 23; end 

23: begin sclk = 1; sdat = reg_ad[6]; step = 24; end //6 

24: begin sclk = 0; sdat = reg_ad[6]; step = 25; end 

25: begin sclk = 1; sdat = reg_ad[5]; step = 26; end //5 

26: begin sclk = 0; sdat = reg_ad[5]; step = 27; end 

27: begin sclk = 1; sdat = reg_ad[4]; step = 28; end //4 

28: begin sclk = 0; sdat = reg_ad[4]; step = 29; end 

29: begin sclk = 1; sdat = reg_ad[3]; step = 30; end //3 

30: begin sclk = 0; sdat = reg_ad[3]; step = 31; end 

31: begin sclk = 1; sdat = reg_ad[2]; step = 32; end //2 

32: begin sclk = 0; sdat = reg_ad[2]; step = 33; end 

33: begin sclk = 1; sdat = reg_ad[1]; step = 34; end //1 

34: begin sclk = 0; sdat = reg_ad[1]; step = 35; end 

35: begin sclk = 1; sdat = reg_ad[0]; step = 36; end //0 

36: begin sclk = 0; sdat = reg_ad[0]; step = 37; end 

//6.Acknowledge 

37: begin sclk = 1; sdat = 1'bz; step = 38; end 

38: begin sclk = 0; sdat = 1'bz; if (sdat == 1) step = 37; else step = 39; end 

//7.Start 

39: begin sclk = 1; sdat = 1; step = 40; end //sclk= 1, sdat= 1 

40: begin sclk = 1; sdat = 1; step = 41; end 

41: begin sclk = 1; sdat = 0; step = 42; end //sclk= 1, sdat= 0 

42: begin sclk = 1; sdat = 0; step = 43; end 

43: begin sclk = 0; sdat = 0; step = 44; end //sclk= 0, sdat= 0 

44: begin sclk = 0; sdat = 0; step = 45; end 

//8.Slave Add 

45: begin sclk = 1; sdat = sl_ad[6]; step = 46; end //6 

46: begin sclk = 0; sdat = sl_ad[6]; step = 47; end 

47: begin sclk = 1; sdat = sl_ad[5]; step = 48; end //5 

48: begin sclk = 0; sdat = sl_ad[5]; step = 49; end 

49: begin sclk = 1; sdat = sl_ad[4]; step = 50; end //4 

50: begin sclk = 0; sdat = sl_ad[4]; step = 51; end 

51: begin sclk = 1; sdat = sl_ad[3]; step = 52; end //3 

52: begin sclk = 0; sdat = sl_ad[3]; step = 53; end 

53: begin sclk = 1; sdat = sl_ad[2]; step = 54; end //2 

54: begin sclk = 0; sdat = sl_ad[2]; step = 55; end 

55: begin sclk = 1; sdat = sl_ad[1]; step = 56; end //1 

56: begin sclk = 0; sdat = sl_ad[1]; step = 57; end 

57: begin sclk = 1; sdat = sl_ad[0]; step = 58; end //0 

58: begin sclk = 0; sdat = sl_ad[0]; step = 59; end 

//9.sdat = 1 

59: begin sclk = 1; sdat = 1; step = 60; end 

60: begin sclk = 0; sdat = 1; step = 61; end 

//10.Acknowledge 

61: begin sclk = 1; sdat = 1'bz; step = 62; end 

62: begin sclk = 0; sdat = 1'bz; if (sdat == 1) step = 61; else step = 63; end 

//11.Databyte#1 

63: begin sclk = 1; data1[7] = sdat; step = 64; end //Databyte#1 bit 7 

64: begin sclk = 0; data1[7] = sdat; step = 65; end 

65: begin sclk = 1; data1[6] = sdat; step = 66; end //6 

66: begin sclk = 0; data1[6] = sdat; step = 67; end 

67: begin sclk = 1; data1[5] = sdat; step = 68; end //5 

68: begin sclk = 0; data1[5] = sdat; step = 69; end 

69: begin sclk = 1; data1[4] = sdat; step = 70; end //4 

70: begin sclk = 0; data1[4] = sdat; step = 71; end 

71: begin sclk = 1; data1[3] = sdat; step = 72; end //3 

72: begin sclk = 0; data1[3] = sdat; step = 73; end 

73: begin sclk = 1; data1[2] = sdat; step = 74; end //2 

74: begin sclk = 0; data1[2] = sdat; step = 75; end 

75: begin sclk = 1; data1[1] = sdat; step = 76; end //1 

76: begin sclk = 0; data1[1] = sdat; step = 77; end 

77: begin sclk = 1; data1[0] = sdat; step = 78; end //0 

78: begin sclk = 0; data1[0] = sdat; step = 79; end 

//12.Acknowledge 

79: begin sclk = 1; sdat = 1'bz; step = 80; end 

80: begin sclk = 0; sdat = 1'bz; if (sdat == 1) step = 79; else step = 81; end 

//13.Stop 

81: begin sclk = 1; sdat = 0; step = 82; end //sclk= 1, sdat= 0 

82: begin sclk = 1; sdat = 0; step = 83; end 

83: begin sclk = 1; sdat = 1; step = 84; end //sclk= 1, sdat= 1 

84: begin sclk = 1; sdat = 1; end 

endcase 

end 

end 

assign I2C_sclk = sclk; 

assign I2C_sdat = sdat; 

assign clk_st = clk_signaltap; 

endmodule
Altera_Forum
Honored Contributor I
123 Views

I have tried to generate I2C_sclk and I2C_sdat in the same always block. And also I use state machine code. The data I get is 0 instead of 0000 0010. Can anyone help me?

Altera_Forum
Honored Contributor I
123 Views

I still use signal tap2 and use clock "clk_signaltap" as the clock for signaltap. My trigger is rising edge of "q" to check node "sclk", "sdat" and "q". I have no idea what's wrong. The slave DO acknowledge everything but it just transmit wrong data.

Altera_Forum
Honored Contributor I
123 Views

I wonder why with the first program(at page 1), I could read(display at signaltap2) the register of eeprom in my de0 nano without any problem. But the same code can't work with adxl

Altera_Forum
Honored Contributor I
123 Views

I think you should read I2C_sdat instead of sdat in your code, on steps 20, 38, 62 and 63-78. sdat is an internal signal and it is only used to control the output. To read the data pin, place sdat at 1'bz and read the value from I2C_sdat. 

When you read the data you should only read it on the rising edge of the clock, the slave will change the data line on the falling edge and you may miss a bit if you read it on both edges. 

To simplify the code a bit (once it's working ;) ), it seems that most of the time you pull the clock low when step has an odd value and high when it is even. Also in most of the cases you increase step by one. I think you should be able to have those two rules as general ones before the case and just override those on the specific steps that need overriding. Now I'm not a Verilog expert, I'm more a VHDL guy myself, but I think it could be done. 

 

As for the register value, did you try to read different registers and see what value you got back?
Altera_Forum
Honored Contributor I
123 Views

Thanks Daixiwen. 

I will try it right away. 

Yeah I have tried to read different reg and I always got 0000 0000. 

Thank you.
Altera_Forum
Honored Contributor I
123 Views

"When you read the data you should only read it on the rising edge of the clock, the slave will change the data line on the falling edge and you may miss a bit if you read it on both edges." 

 

How about if I read the I2C_sdat when the I2C_sclk high (instead of the moment of rising edge I2C_sclk)? I am asking because I am not sure how to do it on the rising edge.
Altera_Forum
Honored Contributor I
123 Views

// ADXL clock= 500,000samples of 50Mhz/100Hz 

// ADXL address= 0x1D/11101 (alt address pin grounded) 

module ADXL_Read(clk_50, I2C_sclk, I2C_sdat, key0, key1, clk_st, data1); 

 

input clk_50; 

output I2C_sclk; 

output data1; 

inout I2C_sdat; 

input key0; //Trigger0 to reset 

input key1; //Trigger1 to begin 

output clk_st; 

 

reg [30:0] a; 

reg [30:0] b; 

reg clk; //Clk for slave 

reg clk_signaltap; //Clk for signaltap2 

reg q; //Register for Trigger 

reg [10:0] step; 

reg [6:0] sl_ad = 7'b0011101; // Slave Address 

reg [7:0] reg_ad = 8'h2D; // Register Address 

reg [7:0] data1; // Databyte#1 

reg sclk; 

reg sdat; 

 

initial begin 

step = 0; 

q = 0; 

end 

 

always @(posedge clk_50) 

begin 

if(a == 1000000) //Clock for Slave with sample 2a 

begin 

clk = ~clk; 

a = 1; 

end 

else 

a = a + 1; 

 

//Signaltap begin 

if(b == 500000) //Clock for Signaltap2 

begin 

clk_signaltap = ~clk_signaltap; 

b = 1; 

end 

else 

b = b + 1; 

end 

 

//Signaltap end 

always @(posedge clk_50) //Trigger Condition 

case({!key1, !key0}) //Active low 

2'b00 : q <= q; 

2'b10 : q <= 1; //Set 

2'b01 : q <= 0; //Reset 

endcase 

 

always @(posedge clk) 

begin 

if (q == 1) 

begin 

case(step) 

//Initial 

0: begin sclk = 1; sdat = 1; step = 1; end 

//1.Start 

1: begin sclk = 1; sdat = 0; step = 2; end 

2: begin sclk = 0; sdat = 0; step = 3; end 

//2.Slave add 

3: begin sclk = 0; sdat = sl_ad[6]; step = 4; end 

4: begin sclk = 1; sdat = sl_ad[6]; step = 5; end 

5: begin sclk = 0; sdat = sl_ad[5]; step = 6; end 

6: begin sclk = 1; sdat = sl_ad[5]; step = 7; end 

7: begin sclk = 0; sdat = sl_ad[4]; step = 8; end 

8: begin sclk = 1; sdat = sl_ad[4]; step = 9; end 

9: begin sclk = 0; sdat = sl_ad[3]; step = 10; end 

10: begin sclk =1; sdat = sl_ad[3]; step = 11; end 

11: begin sclk = 0; sdat = sl_ad[2]; step = 12; end 

12: begin sclk = 1; sdat = sl_ad[2]; step = 13; end 

13: begin sclk = 0; sdat = sl_ad[1]; step = 14; end 

14: begin sclk = 1; sdat = sl_ad[1]; step = 15; end 

15: begin sclk = 0; sdat = sl_ad[0]; step = 16; end 

16: begin sclk = 1; sdat = sl_ad[0]; step = 17; end 

//3.sdat = 0 

17: begin sclk = 0; sdat = 0; step = 18; end 

18: begin sclk = 1; sdat = 0; step = 19; end 

//4.Acknowledge 

19: begin sclk = 0; sdat = 1'bz; step = 20; end 

20: begin sclk = 1; sdat = 1'bz; if (I2C_sdat == 1) step = 20; else step = 21; end 

//5.Reg add 

21: begin sclk = 0; sdat = reg_ad[7]; step = 22; end //7 

22: begin sclk = 1; sdat = reg_ad[7]; step = 23; end 

23: begin sclk = 0; sdat = reg_ad[6]; step = 24; end //6 

24: begin sclk = 1; sdat = reg_ad[6]; step = 25; end 

25: begin sclk = 0; sdat = reg_ad[5]; step = 26; end //5 

26: begin sclk = 1; sdat = reg_ad[5]; step = 27; end 

27: begin sclk = 0; sdat = reg_ad[4]; step = 28; end //4 

28: begin sclk = 1; sdat = reg_ad[4]; step = 29; end 

29: begin sclk = 0; sdat = reg_ad[3]; step = 30; end //3 

30: begin sclk = 1; sdat = reg_ad[3]; step = 31; end 

31: begin sclk = 0; sdat = reg_ad[2]; step = 32; end //2 

32: begin sclk = 1; sdat = reg_ad[2]; step = 33; end 

33: begin sclk = 0; sdat = reg_ad[1]; step = 34; end //1 

34: begin sclk = 1; sdat = reg_ad[1]; step = 35; end 

35: begin sclk = 0; sdat = reg_ad[0]; step = 36; end //0 

36: begin sclk = 1; sdat = reg_ad[0]; step = 37; end 

//6.Acknowledge 

37: begin sclk = 0; sdat = 1'bz; step = 38; end 

38: begin sclk = 1; sdat = 1'bz; if (I2C_sdat == 1) step = 38; else step = 39; end 

//7.Start 

39: begin sclk = 0; sdat = 0; step = 40; end //sclk= 0, sdat= 0 

40: begin sclk = 1; sdat = 1; step = 41; end //sclk= 1, sdat= 1 

41: begin sclk = 1; sdat = 0; step = 42; end //sclk= 1, sdat= 0 

42: begin sclk = 0; sdat = 0; step = 45; end //sclk= 0, sdat= 0 --------------- 

//8.Slave Add 

45: begin sclk = 0; sdat = sl_ad[6]; step = 46; end //6 

46: begin sclk = 1; sdat = sl_ad[6]; step = 47; end 

47: begin sclk = 0; sdat = sl_ad[5]; step = 48; end //5 

48: begin sclk = 1; sdat = sl_ad[5]; step = 49; end 

49: begin sclk = 0; sdat = sl_ad[4]; step = 50; end //4 

50: begin sclk = 1; sdat = sl_ad[4]; step = 51; end 

51: begin sclk = 0; sdat = sl_ad[3]; step = 52; end //3 

52: begin sclk = 1; sdat = sl_ad[3]; step = 53; end 

53: begin sclk = 0; sdat = sl_ad[2]; step = 54; end //2 

54: begin sclk = 1; sdat = sl_ad[2]; step = 55; end 

55: begin sclk = 0; sdat = sl_ad[1]; step = 56; end //1 

56: begin sclk = 1; sdat = sl_ad[1]; step = 57; end 

57: begin sclk = 0; sdat = sl_ad[0]; step = 58; end //0 

58: begin sclk = 1; sdat = sl_ad[0]; step = 59; end 

//9.sdat = 1 

59: begin sclk = 0; sdat = 1; step = 60; end 

60: begin sclk = 1; sdat = 1; step = 61; end 

//10.Acknowledge 

61: begin sclk = 0; sdat = 1'bz; step = 62; end 

62: begin sclk = 1; sdat = 1'bz; if (I2C_sdat == 1) step = 62; else step = 63; end 

//11.Databyte#1 

63: begin sclk = 0; sdat = 1'bz; step = 64; end //Databyte#1 bit 7 

64: begin sclk = 1; sdat = 1'bz; data1[7] = I2C_sdat; step = 65; end 

65: begin sclk = 0; sdat = 1'bz; step = 66; end //6 

66: begin sclk = 1; sdat = 1'bz; data1[6] = I2C_sdat; step = 67; end 

67: begin sclk = 0; sdat = 1'bz; step = 68; end //5 

68: begin sclk = 1; sdat = 1'bz; data1[5] = I2C_sdat; step = 69; end 

69: begin sclk = 0; sdat = 1'bz; step = 70; end //4 

70: begin sclk = 1; sdat = 1'bz; data1[4] = I2C_sdat; step = 71; end 

71: begin sclk = 0; sdat = 1'bz; step = 72; end //3 

72: begin sclk = 1; sdat = 1'bz; data1[3] = I2C_sdat; step = 73; end 

73: begin sclk = 0; sdat = 1'bz; step = 74; end //2 

74: begin sclk = 1; sdat = 1'bz; data1[2] = I2C_sdat; step = 75; end 

75: begin sclk = 0; sdat = 1'bz; step = 76; end //1 

76: begin sclk = 1; sdat = 1'bz; data1[1] = I2C_sdat; step = 77; end 

77: begin sclk = 0; sdat = 1'bz; step = 78; end //0 

78: begin sclk = 1; sdat = 1'bz; data1[0] = I2C_sdat; step = 79; end 

//12.Acknowledge 

79: begin sclk = 0; sdat = 1'bz; step = 80; end 

80: begin sclk = 1; sdat = 1'bz; if (I2C_sdat == 1) step = 80; else step = 81; end 

//13.Stop 

81: begin sclk = 1; sdat = 0; step = 82; end //sclk= 1, sdat= 0 

82: begin sclk = 1; sdat = 1; step = 83; end //sclk= 1, sdat= 1 

83: begin sclk = 1; sdat = 1; end 

endcase 

end 

end 

assign I2C_sclk = sclk; 

assign I2C_sdat = sdat; 

assign clk_st = clk_signaltap; 

endmodule 

 

Now problem's solved. 

I also do some modification so that I feed each new data at sdat when the sclk is low(instead of when it was high) and I read the needed data when the sclk is high. That way I could be sure although if there is any delay when the data is being transmited by the slave, I could still get the right data. 

 

Thank you so much Daixiwen. Without your help, I may still stuck in this problem now.
Altera_Forum
Honored Contributor I
123 Views

// ADXL clock= 500,000samples of 50Mhz/100Hz 

// ADXL address= 0x1D/11101 (alt address pin grounded) 

module ADXL_Read(clk_50, I2C_sclk, I2C_sdat, key0, key1, clk_st, data1); 

 

input clk_50; 

output I2C_sclk; 

output data1; 

inout I2C_sdat; 

input key0; //Trigger0 to reset 

input key1; //Trigger1 to begin 

output clk_st; 

 

reg [30:0] a; 

reg [30:0] b; 

reg clk; //Clk for slave 

reg clk_signaltap; //Clk for signaltap2 

reg q; //Register for Trigger 

reg [10:0] step; 

reg [6:0] sl_ad = 7'b0011101; // Slave Address 

reg [7:0] reg_ad = 8'h2D; // Register Address 

reg [7:0] data1; // Databyte#1 

reg sclk; 

reg sdat; 

 

initial begin 

step = 0; 

q = 0; 

end 

 

always @(posedge clk_50) 

begin 

if(a == 1000000) //Clock for Slave with sample 2a 

begin 

clk = ~clk; 

a = 1; 

end 

else 

a = a + 1; 

 

//Signaltap begin 

if(b == 500000) //Clock for Signaltap2 

begin 

clk_signaltap = ~clk_signaltap; 

b = 1; 

end 

else 

b = b + 1; 

end 

 

//Signaltap end 

always @(posedge clk_50) //Trigger Condition 

case({!key1, !key0}) //Active low 

2'b00 : q <= q; 

2'b10 : q <= 1; //Set 

2'b01 : q <= 0; //Reset 

endcase 

 

always @(posedge clk) 

begin 

if (q == 1) 

begin 

case(step) 

//Initial 

0: begin sclk = 1; sdat = 1; step = 1; end 

//1.Start 

1: begin sclk = 1; sdat = 0; step = 2; end 

2: begin sclk = 0; sdat = 0; step = 3; end 

//2.Slave add 

3: begin sclk = 0; sdat = sl_ad[6]; step = 4; end 

4: begin sclk = 1; sdat = sl_ad[6]; step = 5; end 

5: begin sclk = 0; sdat = sl_ad[5]; step = 6; end 

6: begin sclk = 1; sdat = sl_ad[5]; step = 7; end 

7: begin sclk = 0; sdat = sl_ad[4]; step = 8; end 

8: begin sclk = 1; sdat = sl_ad[4]; step = 9; end 

9: begin sclk = 0; sdat = sl_ad[3]; step = 10; end 

10: begin sclk =1; sdat = sl_ad[3]; step = 11; end 

11: begin sclk = 0; sdat = sl_ad[2]; step = 12; end 

12: begin sclk = 1; sdat = sl_ad[2]; step = 13; end 

13: begin sclk = 0; sdat = sl_ad[1]; step = 14; end 

14: begin sclk = 1; sdat = sl_ad[1]; step = 15; end 

15: begin sclk = 0; sdat = sl_ad[0]; step = 16; end 

16: begin sclk = 1; sdat = sl_ad[0]; step = 17; end 

//3.sdat = 0 

17: begin sclk = 0; sdat = 0; step = 18; end 

18: begin sclk = 1; sdat = 0; step = 19; end 

//4.Acknowledge 

19: begin sclk = 0; sdat = 1'bz; step = 20; end 

20: begin sclk = 1; sdat = 1'bz; if (I2C_sdat == 1) step = 20; else step = 21; end 

//5.Reg add 

21: begin sclk = 0; sdat = reg_ad[7]; step = 22; end //7 

22: begin sclk = 1; sdat = reg_ad[7]; step = 23; end 

23: begin sclk = 0; sdat = reg_ad[6]; step = 24; end //6 

24: begin sclk = 1; sdat = reg_ad[6]; step = 25; end 

25: begin sclk = 0; sdat = reg_ad[5]; step = 26; end //5 

26: begin sclk = 1; sdat = reg_ad[5]; step = 27; end 

27: begin sclk = 0; sdat = reg_ad[4]; step = 28; end //4 

28: begin sclk = 1; sdat = reg_ad[4]; step = 29; end 

29: begin sclk = 0; sdat = reg_ad[3]; step = 30; end //3 

30: begin sclk = 1; sdat = reg_ad[3]; step = 31; end 

31: begin sclk = 0; sdat = reg_ad[2]; step = 32; end //2 

32: begin sclk = 1; sdat = reg_ad[2]; step = 33; end 

33: begin sclk = 0; sdat = reg_ad[1]; step = 34; end //1 

34: begin sclk = 1; sdat = reg_ad[1]; step = 35; end 

35: begin sclk = 0; sdat = reg_ad[0]; step = 36; end //0 

36: begin sclk = 1; sdat = reg_ad[0]; step = 37; end 

//6.Acknowledge 

37: begin sclk = 0; sdat = 1'bz; step = 38; end 

38: begin sclk = 1; sdat = 1'bz; if (I2C_sdat == 1) step = 38; else step = 39; end 

//7.Start 

39: begin sclk = 0; sdat = 0; step = 40; end //sclk= 0, sdat= 0 

40: begin sclk = 1; sdat = 1; step = 41; end //sclk= 1, sdat= 1 

41: begin sclk = 1; sdat = 0; step = 42; end //sclk= 1, sdat= 0 

42: begin sclk = 0; sdat = 0; step = 45; end //sclk= 0, sdat= 0 --------------- 

//8.Slave Add 

45: begin sclk = 0; sdat = sl_ad[6]; step = 46; end //6 

46: begin sclk = 1; sdat = sl_ad[6]; step = 47; end 

47: begin sclk = 0; sdat = sl_ad[5]; step = 48; end //5 

48: begin sclk = 1; sdat = sl_ad[5]; step = 49; end 

49: begin sclk = 0; sdat = sl_ad[4]; step = 50; end //4 

50: begin sclk = 1; sdat = sl_ad[4]; step = 51; end 

51: begin sclk = 0; sdat = sl_ad[3]; step = 52; end //3 

52: begin sclk = 1; sdat = sl_ad[3]; step = 53; end 

53: begin sclk = 0; sdat = sl_ad[2]; step = 54; end //2 

54: begin sclk = 1; sdat = sl_ad[2]; step = 55; end 

55: begin sclk = 0; sdat = sl_ad[1]; step = 56; end //1 

56: begin sclk = 1; sdat = sl_ad[1]; step = 57; end 

57: begin sclk = 0; sdat = sl_ad[0]; step = 58; end //0 

58: begin sclk = 1; sdat = sl_ad[0]; step = 59; end 

//9.sdat = 1 

59: begin sclk = 0; sdat = 1; step = 60; end 

60: begin sclk = 1; sdat = 1; step = 61; end 

//10.Acknowledge 

61: begin sclk = 0; sdat = 1'bz; step = 62; end 

62: begin sclk = 1; sdat = 1'bz; if (I2C_sdat == 1) step = 62; else step = 63; end 

//11.Databyte#1 

63: begin sclk = 0; sdat = 1'bz; step = 64; end //Databyte#1 bit 7 

64: begin sclk = 1; sdat = 1'bz; data1[7] = I2C_sdat; step = 65; end 

65: begin sclk = 0; sdat = 1'bz; step = 66; end //6 

66: begin sclk = 1; sdat = 1'bz; data1[6] = I2C_sdat; step = 67; end 

67: begin sclk = 0; sdat = 1'bz; step = 68; end //5 

68: begin sclk = 1; sdat = 1'bz; data1[5] = I2C_sdat; step = 69; end 

69: begin sclk = 0; sdat = 1'bz; step = 70; end //4 

70: begin sclk = 1; sdat = 1'bz; data1[4] = I2C_sdat; step = 71; end 

71: begin sclk = 0; sdat = 1'bz; step = 72; end //3 

72: begin sclk = 1; sdat = 1'bz; data1[3] = I2C_sdat; step = 73; end 

73: begin sclk = 0; sdat = 1'bz; step = 74; end //2 

74: begin sclk = 1; sdat = 1'bz; data1[2] = I2C_sdat; step = 75; end 

75: begin sclk = 0; sdat = 1'bz; step = 76; end //1 

76: begin sclk = 1; sdat = 1'bz; data1[1] = I2C_sdat; step = 77; end 

77: begin sclk = 0; sdat = 1'bz; step = 78; end //0 

78: begin sclk = 1; sdat = 1'bz; data1[0] = I2C_sdat; step = 79; end 

//12.Acknowledge 

79: begin sclk = 0; sdat = 1'bz; step = 80; end 

80: begin sclk = 1; sdat = 1'bz; if (I2C_sdat == 1) step = 80; else step = 81; end 

//13.Stop 

81: begin sclk = 1; sdat = 0; step = 82; end //sclk= 1, sdat= 0 

82: begin sclk = 1; sdat = 1; step = 83; end //sclk= 1, sdat= 1 

83: begin sclk = 1; sdat = 1; end 

endcase 

end 

end 

assign I2C_sclk = sclk; 

assign I2C_sdat = sdat; 

assign clk_st = clk_signaltap; 

endmodule 

 

Now problem's solved. 

I also do some modification so that I feed each new data at sdat when the sclk is low(instead of when it was high) and I read the needed data when the sclk is high. That way I could be sure although if there is any delay when the data is being transmited by the slave, I could still get the right data. 

 

Thank you so much Daixiwen. Without your help, I may still stuck in this problem now.
Altera_Forum
Honored Contributor I
123 Views

I'm glad you managed to solve your problem! I was about to suggest to use a scope just to be sure the signals outside the FPGA where the ones you expected. 

Solving those kind of problems sure can be painful, but you also learn a lot in the process. 

The I2C protocol indeed only says that the data line should be stable when the clock signal is high, and one way to do it is to write to sda on the falling edge of the clock (or when you put yourself the clock to 0) and read from sda on the rising edge of the clock (or when you put yourself the clock to 1). It's not 100% compliant when you control yourself the clock because of the delay on the line but in practise it works well.
Altera_Forum
Honored Contributor I
18 Views

What was your final code on this project?

Reply