开发FPGA时,使用EDA东西规划芯片完成体系功用已经成为支撑电子规划的通用渠道,并逐渐向支持体系级的规划方向开展。在软件规划进程中,越来越着重模块化规划。I2C总线是Philips公司推出的双向两线串行通讯规范,具有接口线少?通讯功率高级特色。把I2C总线规划成相应的模块,有利于相关FPGA的开发。现在有一些介绍相关开发的材料[1],但都是使用VHDL言语或AHDL言语完成的。本文给出使用Verilog HDL言语规划的I2C总线模块。
1 I2C总线概述
I2C总线体系由两根总线即SCL(串行时钟)线和SDA(串行数据)线构成。这种总线可以规划成很多种通讯装备,但本文只评论主从体系的使用。主器材操控总线通讯,开端/结束传送?发送信息并发生I2C体系时钟。在写操作进程中,从器材一旦被主控器材寻址,就履行特定的相应功用。在读操作进程中,主控器材从从器材那里取得数据。在整个主从传送进程中,一切的事情都经过主控器材的SCL时钟线到达同步。连到总线上的器材的接口方式有必要是漏极开路或集电极开路输出状况。经过上拉电阻,使得两根总线在闲暇的状况下都为高电平状况。因而I2C总线上具有线与功用,即总线上的一切器材都到达高电平状况时,I2C总线才干到达高电平状况,从而使总线上的高速器材和慢速器材作业同步。
在I2C协议中,从器材地址是一个仅有的7位地址。接下来是一个读写方向标志位,读状况是高电平?写状况是低电平。
2 I2C模块的规划与完成
依据I2C协议中传输进程的特色,I2C模块可以划分为字节发送模块、字节接纳模块、开端条件模块、中止条件模块。其间,字节发送模块、字节接纳模块和中止条件模块为根本模块。在开端条件模块中,因为需求发送从器材地址,所以要调用字节发送模块。
下面给出用Verilog HDL言语[3]完成字节发送模块的要害程序。相关变量的声明在此省略。程序在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)
sendbit1:
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
tempscl=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
tempscl=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
程序中sdao、sclo为输出信号,sdai为应对信号,en_sdao是对sdao和sdai进行切换的信号。I2C总线具有SDA和SCL两根信号线,所以在整个模块规划中,把sdao/sclo和sdai/scli作为两组信号。当需求向外部SDA信号线上输出信息时,sdao连到SDA信号线上;当需求从外部SDA信号线上读入信息时,置sdao成高阻态,sdai连到SDA信号线上。en_sdao信号作为这一进程的切换信号。在程序中界说了一些状况信号:NO_ACK、send_byte_over。其间,NO_ACK信号判别从器材是否对发送的信号给予了应对。send_byte_over信号判别字节是否传输结束。这些信号可以传递给上一层规划模块,以操控程序的流程。为了使I2C总线可以有效地通讯,有必要考虑信号的树立和坚持时刻,所以程序中设置了相应的延时部分。别的,在以clk为触发信号的进程模块中,界说send_byte_clk信号为时钟信号的两倍频信号,并参加字节发送模块使能信号start_send_byte操控模块作业,因为篇幅所限,省略该进程模块。
字节发送模块的仿真测验成果如图1所示。
依据I2C总线规范,使用Verilog HDL很简单完成字节接纳模块?开端条件模块?中止条件模块这三个模块。图2是数据发送进程的仿真测验成果。从器材的7位地址为101011,向从器材发送的数据为00010111。aensclo和aensdao分别是sclo/scli和sdao/sdai的切换信号。
图3是数据接纳进程的仿真测验成果。从器材的7位地址为0011001,从器材发送的数据为11111111。ensclo和ensdao分别是sclo/scli和sdao/sdai的切换信号。
将图2和图3所模仿的I2C总线时序与I2C总线协议中相关要求进行比较,满意I2C总线的时序要求。
对各个模块进行多层次处理,构成I2C总线模块。
以该I2C总线模块为根底,编写FPGA与AT24C01A(ATMEL公司出产的E2PROM)的通讯程序。然后把相关程序下载到EPF10K10LC84-3中,与AT24C01A进行实践通讯试验,作用杰出。