由上图可以写出各个状态
1.Start
在scl高电平时,sda由高拉低
2.写入控制字
在scl低电平时写入八位控制字
3.接收ack
在scl高电平时,如果接收的ack为低电平,进行下一个状态,如果接收的ack为高电平,返回上一级
4.写入高位地址
在scl低电平时写入
5.接收ack
同3
6..写入地位地址
在scl低电平写入
7.接收ack
同3
8.将sda拉高
因为下一步要进行start,所以要保证sda,scl都为高电平
9.Start
同1
10.发送控制字
同2
11.接收ack
同3
12.读数据
此时要保证scl高电平,flag为0(flag为sda三态门开关
sda=(flag==1)?Data_out:1’bz)
13.NO ack
FPGA向e2prom传输信号,scl为低电平,flag=1,data_out=1;
14.将sda拉低
以为下一步要进行stop,所以先将sda置为低电平
15.Stop
在scl=1的时候将事先置为低电平的sda拉高,stop。
附图2为仿真波形
程序如下
module iic_rd(clk,rst_n,scl,sda,q);
module iic_rd(clk,rst_n,scl,sda,q);
input clk;
input rst_n;
output reg scl;
output reg [7:0]q;
inout sda;
reg inclk;
reg [31:0]count;
reg [31:0]count3;
reg [7:0]temp;
reg [15:0]addr;
reg [7:0]data_out;
reg [3:0]state;
reg flag;
reg [7:0]data;
always@(posedge clk or negedge rst_n)
begin
if(rst_n==0)
begin
inclk<=0;
count<=0;
end
else
begin
if(count<62)
begin
count<=count+1;
end
else
begin
inclk<=~inclk;
end
end
end
always@(negedge inclk or negedge rst_n)
begin
if(rst_n==0)
begin
scl<=1;
end
else
begin
if(state<14)
begin
scl=~scl;
end
else
begin
scl<=1;
end
end
end
assign sda=(flag==1)? data_out:1'bz;
always@(posedge inclk or negedge rst_n)
begin
if(rst_n==0)
begin
flag<=1;
data_out<=1;
count3<=0;
state<=0;
temp<=8'b1010_0000;
addr<=16'b0000_0000_0000_0000;
q<=8'b0000_0000;
end
else
begin
case(state)
0: //start
begin
if(scl==1)
begin
flag<=1;
data_out<=0;
state<=1;
end
end
1: //control
begin
if(scl==0 && count3<8)
begin
flag<=1;
data_out<=temp[7];
count3<=count3+1;
temp<={temp[6:0],temp[7]};
state<=1;
end
else if(scl==0 && count3==8)
begin
count3<=0;
state<=2;
flag<=0;
end
end
2: //ack
begin
if(scl==1)
//begin
//if(sda==0)
begin
state<=3;
data_out<=0;
end
//end
//else
//begin
//state<=1;
//end
end
3: //high addr
begin
if(scl==0 && count3<8)
begin
flag<=1;
data_out<=addr[15];
count3<=count3+1;
addr<={addr[14:0],addr[15]};
state<=3;
end
else if(scl==0 && count3==8)
begin
count3<=0;
state<=4;
flag<=0;
end
end
4: //ack
begin
if(scl==1)
//begin
//if(sda==0)
begin
state<=5;
data_out<=0;
end
//end
//else
//begin
//state<=3;
//end
end
5: //low addr
begin
if(scl==0 && count3<8)
begin
flag<=1;
data_out<=addr[15];
count3<=count3+1;
addr<={addr[14:0],addr[15]};
state<=5;
end
else if(scl==0 && count3==8)
begin
count3<=0;
state<=6;
flag<=0;
end
end
6: //ack
begin
if(scl==1)
//begin
//if(sda==0)
begin
state<=7;
data_out<=0;
end
//end
//else
//begin
//state<=5;
//end
end
7: //将sda拉高
begin
if(scl==0)
begin
flag<=1;
data_out<=1;
state<=8;
end
end
8: //start
begin
if(scl==1)
begin
flag<=1;
data_out<=0;
state<=9;
temp<=8'b1010_0001;
end
end
9: //control
begin
if(scl==0 && count3<8)
begin
flag<=1;
data_out<=temp[7];
count3<=count3+1;
temp<={temp[6:0],temp[7]};
state<=9;
end
else if(scl==0 && count3==8)
begin
count3<=0;
state<=10;
flag<=0;
end
end
10: //ack
begin
if(scl==1)
//begin
//if(sda==0)
begin
state<=11;
data_out<=0;
end
//end
//else
//begin
//state<=9;
//end
end
11: //data
begin
if(scl==1 && count3<8)
begin
flag<=0;
data<=sda;
count3<=count3+1;
data<={data[6:0],sda};
state<=11;
end
else if(scl==1 && count3==8)
begin
count3<=0;
state<=12;
flag<=1;
q<=data;
end
end
12: //no ack
begin
if(scl==0)
begin
flag<=1;
data_out<=1;
state<=13;
end
end
13: //sda拉低
begin
if(scl==0)
begin
flag<=1;
data_out<=0;
state<=14;
end
end
14: //stop
begin
if(scl==1)
begin
flag<=1;
data_out<=1;
end
end
default: //default
begin
state<=0;
end
endcase
end
end
endmodule
|