- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Too bad:( nobody's willing to help me in my thesis project.
Come on anyone help me:D- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Daixiwen.
I will try it right away. Yeah I have tried to read different reg and I always got 0000 0000. Thank you.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
// 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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
// 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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What was your final code on this project?

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page