2 I2C模块的设计与实现
根据I2C协议中传输过程的特点,I2C模块可以划分为字节发送模块、字节接收模块、开始条件模块、停止条件模块。其中,字节发送模块、字节接收模块和停止条件模块为基本模块。在开始条件模块中,因为需要发送从器件地址,所以要调用字节发送模块。
下面给出用Verilog HDL语言实现字节发送模块的关键程序。相关变量的声明在此略去。程序在Max+PlusII环境下编译、调试、仿真。
assign en_sdao=tempen_sdao;//设置SDA三态输出使能
assign send_byte_over=tempsend_byte_over;
assign NO_ACK=tempNO_ACK;
assign sdao=tempsda;
assign sclo=tempscl;
always@(posedge send_byte_clk)
begin
case(send_byte_zt)
sendbit 1:
begin
if(send_byte_num==0)
begin
shiftdata[7:0]=indata[7:0];
end
shiftdata=shiftdata<<1;
tempsda=shiftdata[8];
tempscl=1; //置SCL为高电平
send_byte_zt=delay_1;
send_byte_num=send_byte_num+1;
end
delay_1: //延时三个周期
begin
if(delay_counter>=2)
begin
send_byte_zt=sendbit2;
delay_counter=0;
end
else
begin
delay_counter=delay_counter+1;
send_byte_zt=send_byte_zt;
end
end
sendbit2:
begin
tempsc1=0; //SCL置零
send_byte_zt=delay_2;
end
delay_2: //延时三个周期
begin
if(delay_counter>=2)
begin
send_byte_zt=sendbit3;
delay_counter=0;
end
else
begin
delay_counter=delay_counter+1;
send_byte_zt=send_byte_zt;
end
end
sendbit3: //判断是否字节中所有位都发送完毕
begin
if(send_byte_num<=8)
begin
send_byte_zt=sendbit1;
end
else
begin
send_byte_zt=ForACK1;
send_byte_num=0;
end
end
ForACK1:
begin
tempsda=1; //释放数据线,等待应答信号
send_byte_zt=delay_ACK;
end
delay_ACK: //延时
begin
if(delay_counter>=3)
begin
send_byte_zt=ForACK2;
delay_counter=0;
end
else
begin
delay_counter=delay_counter+1;
send_byte_zt=send_byte_zt;
tempscl=1;
end
end
ForACK2:
begin
send_byte_zt=AckYESNO;
tempen_sdao=0; //输出SDA使能信号,控制sdao和sdai
end
AckYESNO:
begin
if(sdai) //如果应答信号sdai为1,NO_ACK置1
begin
tempNO_ACK=1; //设置未应答标志信号
end
tempsc1=0; //终止应答位
send_byte_zt=Finish_delay;
end
Finish_delay: //延时
begin
if(delay_counter>=2)
begin
tempsend_byte_over=1;
send_byte_zt=FinishACK1;
delay_counter=0;
end
else
begin
delay_counter=delay_counter+1;
send_byte_zt=send_byte_zt;
end
end
FinishACK1:
begin
send_byte_zt=sendbit1;
send_byte_num=0;
end
default:
begin
send_byte_zt=sendbit1;
send_byte_num=0;
end
endcase
end