|
1.接触IIC的人,网上都可以了解到IIC有着严格的时序图,IIC在传输过程中需要起始信号、停止信号、应答信号。
开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变。
停止信号:SCL为高电平时,SDA由低电平向高电平跳变。
应答信号:应答信号由接受设备产生,在 SCL 为高电平时,接受设备将 SDA 拉为低电
平表示传输正确,产生应答,否则为非应答
2.下面基于fpga的IIC设计,该设计HMDI sil9136的IIC控制程序
module sii_i2c_cfg(
input clk,
input rst,
input start,
output reg check_done,
output [7:0]odata,
output reg scl,
inout sda
);
reg link_sda;
reg sda_buf;
wire link_sda_o;
wire sda_buf_o;
reg FF;
reg [5:0]main_state;
reg [5:0]iic_state;
reg [7:0]sh8out_buf;
reg [3:0]cnt;
reg [7:0]rdata;
reg [10:0]time_cnt;
reg [10:0]wait_cnt;
assign odata=rdata;
assign sda = (link_sda_o)?sda_buf_o:1'bz;
assign sda_buf_o=(sda_buf)?1'bz:1'b0;
assign link_sda_o=(link_sda)?1'b1:1'b0;
//i2c scl
always @(negedge clk or posedge rst)
if(rst) scl<=0;
else scl<=~scl;
//i2c sda
always @(posedge clk or posedge rst)
if(rst)
begin
main_state<=0;
FF<=0;
iic_state<=0;
sh8out_buf<=0;
cnt<=0;
rdata<=0;
check_done<=0;
time_cnt<=0;
wait_cnt<=0;
end
else
begin
case(main_state)
0: if(start) main_state<=1;
else main_state<=0;
1: if(FF)
begin
FF<=0;
main_state<=2;
end
else
begin
iic_write(8'h72,8'hC7,8'h00);
main_state<=1;
end
2: if(wait_cnt==10)
begin
wait_cnt<=0;
main_state<=3;
end
else wait_cnt<=wait_cnt+1;
3: if(FF)
begin
FF<=0;
main_state<=4;
end
else
begin
iic_write(8'h72,8'h1a,8'h01);
main_state<=3;
end
4: if(wait_cnt==10)
begin
wait_cnt<=0;
main_state<=5;
end
else wait_cnt<=wait_cnt+1;
5: main_state<=5;
default:
begin
main_state<=0;
FF<=0;
iic_state<=0;
sh8out_buf<=0;
cnt<=0;
rdata<=0;
end
endcase
end
task iic_write;
input [7:0] slv_addr;
input [7:0] addr;
input [7:0] wdata;
begin
case (iic_state)
0:
if(!scl) //start
begin
link_sda <= 1;
sda_buf <= 1;
iic_state <= 1;
end
1:
if(scl)
begin
sh8out_buf[7:0] <= {slv_addr[7:1],1'b0};
link_sda <= 1;
sda_buf <= 0;
iic_state <= 2;
end
2:
if(!scl) //device address
begin
if(cnt==8)
begin
link_sda <= 0;
cnt <= 0;
iic_state <= 3;
end
else
begin
link_sda <= 1;
sda_buf <= sh8out_buf[7];
cnt <= cnt+1;
sh8out_buf <= sh8out_buf<<1;
end
end
3:
if(scl&&!sda) //ack
begin
iic_state <= 4;
// link_sda <= 1;
sh8out_buf[7:0] <= addr;
end
4:
if(!scl) //addr
begin
if(cnt==8)
begin
link_sda <= 0;
cnt <= 0;
iic_state <= 5;
end
else
begin
link_sda <= 1;
sda_buf <= sh8out_buf[7];
cnt <= cnt+1;
sh8out_buf <= sh8out_buf<<1;
end
end
5:
if(scl&&!sda) //receive ack
begin
iic_state <= 6;
//link_sda <= 1;
sh8out_buf <=wdata;
end
6:
if(!scl) //data
begin
if(cnt==8)
begin
link_sda <= 0;
cnt <= 0;
iic_state <= 7;
end
else
begin
link_sda <= 1;
sda_buf <= sh8out_buf[7];
cnt <= cnt+1;
sh8out_buf <= sh8out_buf<<1;
end
end
7:
if(scl&&!sda) //receive ack
begin
iic_state <= 8;
// link_sda <= 1;
end
8:
if(!scl) //stop
begin
sda_buf <= 0;
link_sda <= 1;
iic_state <= 9;
end
9:
if(scl)
begin
sda_buf <= 1;
iic_state <= 10;
end
10:
begin
FF <= 1;
sh8out_buf <= 0;
link_sda <= 0;
iic_state <= 0;
end
endcase
end
endtask
task iic_read;
input [7:0] slv_addr;
input [7:0] addr;
output [7:0] odata;
begin
case (iic_state)
0:
if(!scl) //start
begin
link_sda <= 1;
sda_buf <= 1;
iic_state <= 1;
end
1:
if(scl)
begin
sh8out_buf[7:0] <= {slv_addr[7:1],1'b0};
link_sda <= 1;
sda_buf <= 0;
iic_state <= 2;
end
2:
if(!scl) //device address
begin
if(cnt==8)
begin
link_sda <= 0;
cnt <= 0;
iic_state <= 3;
end
else
begin
link_sda <= 1;
sda_buf <= sh8out_buf[7];
cnt <= cnt+1;
sh8out_buf <= sh8out_buf<<1;
end
end
3:
if(scl&&!sda) //ack
begin
iic_state <= 4;
//link_sda <= 1;
sh8out_buf[7:0] <= addr;
end
4:
if(!scl) //write addr
begin
if(cnt==8)
begin
link_sda <= 0;
cnt <= 0;
iic_state <= 5;
end
else
begin
link_sda <= 1;
sda_buf <= sh8out_buf[7];
cnt <= cnt+1;
sh8out_buf <= sh8out_buf<<1;
end
end
5:
if(scl&&!sda) //receive ack
begin
iic_state <= 6;
end
6:
if(!scl) //restart
begin
link_sda <= 1;
sda_buf <= 1;
iic_state <= 7;
end
7:
if(scl)
begin
sh8out_buf[7:0] <= {slv_addr[7:1],1'b1};
link_sda <= 1;
sda_buf <= 0;
iic_state <= 8;
end
8:if(!scl) //device address
begin
if(cnt==8)
begin
link_sda <= 0;
cnt <= 0;
iic_state <= 9;
end
else
begin
link_sda <= 1;
sda_buf <= sh8out_buf[7];
cnt <= cnt+1;
sh8out_buf <= sh8out_buf<<1;
end
end
9:
if(scl&&!sda) //receive ack
begin
iic_state <= 10;
end
10:
if(scl) //read data
begin
if(cnt==7)
begin
cnt <= 0;
//odata[0] <=sda;
iic_state <= 11;
end
else
begin
odata[7-cnt]<=sda;
cnt<=cnt+1;
end
end
11:
if(!scl) //send ack
begin
sda_buf <= 1;
link_sda <= 1;
end
else
begin
iic_state <= 12;
end
12:
if(!scl) //stop
begin
sda_buf<=0;
link_sda <= 1;
iic_state <= 13;
end
13:
if(scl)
begin
sda_buf<=1;
iic_state <= 14;
end
14:
begin
FF<=1;
sh8out_buf <= 0;
link_sda <= 0;
iic_state <= 0;
end
endcase
end
endtask
endmodule |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?我要注册
x
|