Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 module i2cio2( input wire clk, input wire reset, output reg sda, output wire scl, output reg [7:0] data, output reg [7:0] state ); localparam STATE_IDLE =0; localparam STATE_START =1; localparam STATE_ADDR =2; localparam STATE_RW =3; localparam STATE_WACK =4; localparam STATE_DATA =5; localparam STATE_WACK2 =6; localparam STATE_STOP =7; reg [6:0] addr; reg [7:0] count; reg ack1; reg ack2; reg scl_enable; reg rw; initial scl_enable<=0; i2c_clk_divider instance_name ( .clk(clk), .reset(reset), .i2c_clk(i2c_clk) ); assign scl=(scl_enable==0) ? 1:~i2c_clk; always @ (posedge i2c_clk)begin if(reset==1)begin scl_enable<=0; sda<=1; state<=STATE_IDLE; addr<=7'h0x96; rw<=1; count<=8'd0; data<=8'b01010101; ack1<=0; ack2<=0; end else begin case(state) STATE_IDLE: begin //IDDLE sda<=1; state<=STATE_START; scl_enable<=0; end STATE_START: begin //START sda<=0; state<=STATE_ADDR; scl_enable<=0; count<=6; end STATE_ADDR: begin //MSB ADDRESS BIT sda<=addr[count]; scl_enable<=1; if(count==0) state<=STATE_RW; else count<=count-1; end STATE_RW: begin //BIT 5 sda<=1; count<=7; state<=STATE_WACK; scl_enable<=1; end STATE_WACK: begin //BIT 4 sda<=0; state<=STATE_DATA; scl_enable<=1; end STATE_DATA: begin scl_enable<=1; sda<=data[count]; if(count==0) state<=STATE_WACK2; else count<=count-1; end STATE_WACK2: begin sda<=0; scl_enable<=1; state<=STATE_STOP; end STATE_STOP: begin sda<=1; scl_enable<=0; state<=STATE_IDLE; end endcase end//end else end // end always endmodule
There's a light sensor connected to FPGA.
FPGA is the master and Sensor is slave.
Probably, SDA line is not working bidirectionally. I can't communicate with slave.
output reg sda,
Hi,
check with a scope. Dual channel, SDA and SCL.
Klaus
Code:output reg sda,
Probably? most definitely it's not bi-directional, you can only write to a slave given the code you've written.
Unlikely, looks like 2x SDA probed differently. No signal looks like a valid I2C clock. Levels seem incorrect. What's I2C voltage level, 3.3 or 5 volt?Here's the output of scope.
top=SDA
bottom=SCL
No, needs real pull-up resistors.Declaring pull up resistor like sda<='H' ?
That's a very general I2C question, not specific to this sensor. I suggest to read a basic I2C specification or tutorial, e.g. the I2C specification from NXP.First, How can I read ACK from slave ? I wanna made SDA bidirectionally. But I can't estimate how can I get it. Because SDA is bidirectionally, I must send data and read data. How can I read data and send data at the same time ?
Unfortunately. Taos/AMS didn't manage to give an example of the complete I2C communication sequence. We can just guess that the addressing is similar to accessing I2C EEPROMSSecond, For communicatiıon with IC Sensor may require sending control byte before the addres byte.
module i2cio2(
input wire clk,
input wire reset,
inout wire sda,
output wire scl,
output reg [7:0] data,
output reg [7:0] state,
output wire i2c_clk
);
localparam STATE_IDLE =0;
localparam STATE_START =1;
localparam STATE_ADDR =2;
localparam STATE_RW =3;
localparam STATE_WACK =4;
localparam STATE_DATA =5;
localparam STATE_WACK2 =6;
localparam STATE_STOP =7;
reg [6:0] addr;
reg [7:0] count;
reg ack1;
reg ack2;
reg sda_reg;
reg scl_enable;
reg rw;
initial scl_enable<=0;
i2c_clk_divider instance_name (
.clk(clk),
.reset(reset),
.i2c_clk(i2c_clk)
);
assign scl=(scl_enable==0) ? 1:~i2c_clk;
assign sda=sda_reg;
always @ (posedge i2c_clk)begin
if(reset==1)begin
scl_enable<=0;
sda_reg<=1;
state<=STATE_IDLE;
addr<=7'h0x96;
rw<=1;
count<=8'd0;
data<="00000000";
ack1<=0;
ack2<=0;
end
else begin
case(state)
STATE_IDLE:
begin //IDDLE
sda_reg<=1;
state<=STATE_START;
scl_enable<=0;
end
STATE_START:
begin //START
sda_reg<=0;
state<=STATE_ADDR;
scl_enable<=0;
count<=6;
end
STATE_ADDR:
begin //MSB ADDRESS BIT
sda_reg<=addr[count];
scl_enable<=1;
if(count==0) state<=STATE_RW;
else count<=count-1;
end
STATE_RW:
begin //BIT 5
sda_reg<=rw;
count<=7;
state<=STATE_WACK;
scl_enable<=1;
end
STATE_WACK:
begin
if(sda_reg==0)begin
state<=STATE_DATA;
end else begin
state<=STATE_START;
end
scl_enable<=1;
end
STATE_DATA:
begin
scl_enable<=1;
sda_reg<=data[count];
if(count==0) state<=STATE_WACK2;
else count<=count-1;
end
STATE_WACK2:
begin
sda_reg<=0;
scl_enable<=1;
state<=STATE_STOP;
end
STATE_STOP:
begin
sda_reg<=1;
scl_enable<=0;
state<=STATE_IDLE;
end
endcase
end//end else
end // end always
endmodule
Yes I see, this gives you nice waveforms but no chance to receive a response from the slave. There's even a risk of damaging the I2C slave or the FPGA output if the FPGA is driving 1 and the slave 0.I don't operate the I2C line with pull-up resistor and open drain. I get I2C signals directly from FPGA to sensor.
The actual code is thisI want to send 0x98 address bits but it seems 0010110
addr<=7'h0x96;
I feel a bit helpless facing your denial of accepting the I2C basics. That's the bus topology according to the NXP specification:Why I need use pull up resistor ? Input voltage of sensor is enough to communicate.
module i2cio3(
input wire clk,
input wire reset,
inout wire sda,
output wire scl,
output reg [7:0] data,
output reg [7:0] state,
output wire i2c_clk
);
localparam STATE_IDLE =0; // 0000
localparam STATE_START =1; // 0001
localparam STATE_ADCALL =2; // 0010
localparam STATE_RW1 =3; // 0011
localparam STATE_ACK1 =4; // 0100
localparam STATE_ADDR =5; // 0101
localparam STATE_RW2 =6; // 0110
localparam STATE_ACK2 =7; // 0111
localparam STATE_DATA =8; // 1000
localparam STATE_ACK3 =9; // 1001
localparam STATE_STOP =10; // 1010
reg [6:0] addr;
reg [6:0] adcall;
reg [7:0] count1;
reg [7:0] count2;
reg [7:0] count3;
reg ack1;
reg ack2;
reg ack3;
reg sda_reg;
reg scl_enable;
reg rw1;
reg rw2;
initial scl_enable<=0;
i2c_clk_divider instance_name (
.clk(clk),
.reset(reset),
.i2c_clk(i2c_clk)
);
assign scl=(scl_enable==0) ? 1:~i2c_clk;
assign sda=sda_reg;
always @ (posedge i2c_clk)begin
if(reset==1)begin
scl_enable<=0;
sda_reg<=1;
state<=STATE_IDLE;
adcall<=7'h0x29;
addr<=7'h0x96;
rw1<=0;
rw2<=1;
data<=8'b10101010;
end
else begin
case(state)
STATE_IDLE:
begin //IDDLE
sda_reg<=1;
state<=STATE_START;
scl_enable<=0;
end
STATE_START:
begin //START
sda_reg<=0;
state<=STATE_ADCALL;
scl_enable<=0;
count1<=6;
count2<=6;
count3<=7;
end
STATE_ADCALL:
begin
sda_reg<=adcall[count1];
scl_enable<=1;
if(count1==0) state<=STATE_RW1;
else count1<=count1-1;
end
STATE_RW1:
begin
sda_reg<=rw1;
state<=STATE_ACK1;
scl_enable<=1;
end
STATE_ACK1:
begin
sda_reg<=1'bx;
state<=STATE_ADDR;
scl_enable<=1;
end
STATE_ADDR:
begin //MSB ADDRESS BIT
sda_reg<=addr[count2];
scl_enable<=1;
if(count2==0) state<=STATE_RW2;
else count2<=count2-1;
end
STATE_RW2:
begin //BIT 5
sda_reg<=rw2;
state<=STATE_ACK2;
scl_enable<=1;
end
STATE_ACK2:
begin
//BIT 4
//if(sda_reg<=0)begin
sda_reg<=1'bx;
state<=STATE_DATA;
//end else begin
//state<=STATE_START;
//end
scl_enable<=1;
end
STATE_DATA:
begin
scl_enable<=1;
data[count3]<=sda_reg;
if(count3==0) state<=STATE_ACK3;
else count3<=count3-1;
end
STATE_ACK3:
begin
sda_reg<=1'bx;
scl_enable<=1;
state<=STATE_STOP;
end
STATE_STOP:
begin
sda_reg<=1;
scl_enable<=0;
state<=STATE_IDLE;
end
endcase
end//end else
end // end always
endmodule
module i2cio3(
input wire clk,
input wire reset,
inout wire sda,
output wire scl,
output reg [7:0] data,
output reg [7:0] state,
output wire i2c_clk
);
localparam STATE_IDLE =0; //
localparam STATE_START_WRITE =1; //
localparam STATE_I2C_ADD_CALL1 =2; //
localparam STATE_RW1 =3; //
localparam STATE_ACK1 =4;
localparam STATE_REG_ADD1 =5;
localparam STATE_ACK2 =6; //
localparam STATE_START_READ =7;
localparam STATE_I2C_ADD_CALL2 =8; //
localparam STATE_RW2 =9; //
localparam STATE_ACK3 =10; //
localparam STATE_DATA =11; //
localparam STATE_ACK4 =12; //
localparam STATE_STOP =13; //
localparam STATE_REG_ADD =14;
reg [7:0] addr;
reg [6:0] adcall;
reg [7:0] count;
reg ack1;
reg ack2;
reg ack3;
reg sda_reg;
reg scl_enable;
reg rw1;
reg rw2;
initial scl_enable<=0;
i2c_clk_divider instance_name (
.clk(clk),
.reset(reset),
.i2c_clk(i2c_clk)
);
assign scl=(scl_enable==0) ? 1:~i2c_clk;
assign sda=sda_reg;
always @ (posedge i2c_clk)begin
if(reset==1)begin
scl_enable<=0;
sda_reg<=1;
state<=STATE_IDLE;
adcall<=8'b00101001;
addr<=8'b10011000;//'h0x98;
rw1<=0;
rw2<=1;
data<=8'b10101010;
end
else begin
case(state)
STATE_IDLE:
begin //IDDLE
sda_reg<=1;
state<=STATE_START_WRITE;
scl_enable<=0;
end
STATE_START_WRITE:
begin //START
sda_reg<=0;
state<=STATE_I2C_ADD_CALL1;
scl_enable <= 0;
count<=6;
end
STATE_I2C_ADD_CALL1:
begin
sda_reg<=adcall[count];
scl_enable<=1;
if(count==0) state<=STATE_RW1;
else count<=count-1;
end
STATE_RW1:
begin
sda_reg<=rw1;
state<=STATE_ACK1;
scl_enable<=1;
count<=7;
end
STATE_ACK1:
begin
sda_reg<=1'bz;
state<=STATE_REG_ADD1;
scl_enable<=1;
end
STATE_REG_ADD1:
begin
sda_reg<=addr[count];
scl_enable<=1;
if(count==0) state<=STATE_ACK2;
else count<=count-1;
end
STATE_ACK2:
begin
sda_reg<=1'bz;
state<=STATE_START_READ;
scl_enable<=1;
end
STATE_START_READ:
begin
sda_reg<=0;
state<=STATE_I2C_ADD_CALL2;
scl_enable<=0;
count<=6;
end
STATE_I2C_ADD_CALL2:
begin //MSB ADDRESS BIT
sda_reg<=addr[count];
scl_enable<=1;
if(count==0) state<=STATE_RW2;
else count<=count-1;
end
STATE_RW2:
begin //BIT 5
sda_reg<=rw2;
state<=STATE_ACK3;
scl_enable<=1;
end
STATE_ACK3:
begin
sda_reg<=1'bz;
state<=STATE_DATA;
scl_enable<=1;
count<=7;
end
STATE_DATA:
begin
sda_reg<=1'bz;
scl_enable<=1;
data[count]<=sda_reg;
if(count==0) state<=STATE_ACK4;
else count<=count-1;
end
STATE_ACK4:
begin
sda_reg<=1'bz;
scl_enable<=1;
state<=STATE_STOP;
end
STATE_STOP:
begin
sda_reg<=1;
scl_enable<=0;
state<=STATE_IDLE;
end
endcase
end//end else
end // end always
endmodule
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?