首先是写的时序:

如上所示:
第一个是字节写,即每次写一个字节。顺序是首先写器件地址,然后是数据地址,最后是数据。因为IIC可以外挂很多器件,所以需要一个器件地址要表明是对哪一个外设进行操作。
第二个是多字节写,即每次写多个字节。每写一个字节,数据地址会自己加1。比如对数据地址0写数据DATA(n),那么写DATA(n+1)的时候,数据地址会自己加1,即对地址0写数据DATA(N+1)。但是这里要相当注意,这个数据n的个数是有限制的。由每页规定的字节数据个数规定的。AT24C02每页有8字节,所以最高只能写8字节的数据。超过8字节的数据,会覆盖当前页之前的数据。这里要相当注意。
至于这里的回应信号ACK,这里也要注意都是低有效,而且这个ACK信号是AT24C02器件给的。
器件地址,数据手册也有说明:

前4位的值都是1010,后面3位是由你外接的A2,A1,A0电平决定的。后面的R/W是读写位。0表示写,1表示读。

上图是AT24C02的封装图,有三个管脚A2,A1,A0,这里就是器件地址中的A2,A1,A0。这三个可以接不同的电平。所以在一个IIC总线上,最多可以外挂8个AT24C02器件。
然后是读的时序:

读的部分要比写要麻烦很多。下面逐次介绍一下:
第一个图:
读当前数据地址的值。这个当前数据地址是由上次操作的地址决定的。比如,在之前的一次操作,对0x00地址写数据,那么目前的当前数据地址就是0x00。
第二个图:
随机读数据。读取指定的数据地址的值。
第三个图:
读多个数据。读取制定的数据首地址的多个数据的值。这里只要有首地址,每读完一个数据,数据地址会自己加1,这样就可以读取下一个数据。
这里要注意第一个和后面两个在时序上有点不一样。
对于第一个:首先是发器件地址,但是读写位为1。
对于后面两个:也是发器件地址,但是读写位要为0。然后发数据地址。在然后要重新发送起始信号,然后在发器件地址,但是这时候读写位要为1,表示读数据。后面就是读取的数据。如果读的数据不是最后一个,ACK信号为低,如果是最后一个,ACK信号要为高。
这里要注意的地方:
1、随机读数据和连续读数据,第一个发的器件地址的读写位要为0,然后是发数据地址,然后要重新发送起始信号,这个相当重要,不发重新起始信号,是读不到数据的。然后在重新发送器件地址,然后读写位要为1.然后就读数据了。
2、这里的响应信号ACK,要注意这个ACK信号时主机给的,不是AT24C02给的。没有读最后一个数据,主机发ACK低,从机接收到低,表示读数据继续。读最后一个数据,主机发ACK高,从机接收到高,表示数据读取结束。
以上就是读数据要注意的地方,我就是在读数据这里卡了很久,第一个是没有注意,器件地址要发两次,第二个是没有注意要重新发送起始信号,第三个就是ACK信号给错,以为这ACK信号时从机给的。造成数据一直读取不成功。
具体的IIC协议的内容,大家可自行百度查询。
如果注意到了以上的问题,那么写程序控制IIC器件就比较容易了。根据数据手册的时序,注意各个信号之间的时间要求,如保持时间,建立时间要求,然后写程序即可。
采用状态机设计:
首先是定义各个状态:

这里说明一下各个状态作用以及状态中的代码:
这里先说明几个变量的作用:
delay_time_next,delay_time:用来记录每个状态中的计数,该计数是用来使每个状态保持一个固定的时间。
bit_counter_next,bit_counter:用来记录发送8-bit数据的哪一位数据。
counter_number_next, counter_number: 用来记录发送的第几个数据或者是接收的第几个数据。因为考虑到传输多个数据的情况。
i2c_sda_reg: 是FPGA的SDA输出。
i2c_sda: FPGA的SDA输入。 因为SDA是双向的,所以需要将输入和输出分开。向SDA写数据,就向i2c_sda_reg写数据即可。而要读取SDA数据,就只要读取i2c_sda的值即可。
first_byte_to_send:起始信号后发送的第一个字节数据,即器件地址加RW。
第一个idle_state:空闲状态,即没有数据传输时的状态。
+ 查看代码
 idle_state: begin
     delay_time_next  =  'd0; 
     bit_counter_next =  'd0;    //send bit counter 
     counter_number_next = 'd0;  //send data counter 
     read_data_reg  = 'd0; 
     write_idle = 1'b1; 
     i2c_sda_reg = 1'b1;  //if no data transfer ,i2c data is 1       
 if(start) 
    state_next = ready_state; 
 end 
在这个状态下,SCL和SDA都为高电平。
第二个ready_state:准备状态,这里其实就是产生开始信号。即SCL保持高,SDA拉低。产生一个开始信号,开始进行IIC通信。
+ 查看代码
ready_state: begin
    i2c_sda_reg = 1'b0;  //ic2 data pull down.mean begin to transfer data  
 if(delay_time >= 99) //delay 2us, meeting i2c data  setup and hole timing 
 begin
    delay_time_next = 'd0; 
 state_next = send_device_address_state; 
 end
 else
    delay_time_next = delay_time + 1'b1; 
 end 
第三个状态send_device_address_state:发送器件地址状态,在这个状态中,FPGA将器件地址和RW组成的8-bits数据发送给AT24C02。
+ 查看代码
//send first byte. including  device address and r/w enable
 send_device_address_state: begin 
    if(delay_time == 16) //delay 320ns ,let i2c data meet setup and hold time
     i2c_sda_reg = first_byte_to_send[7-bit_counter]; 
    if(delay_time >= 199)    //delay 4us , 1-bits data transfer finish 
    begin 
    if(bit_counter_next >= 7)  //send_8-bits data  finish 
   begin 
   bit_counter_next = 'd0; 
   state_next = wait_device_ack_state; 
 delay_time_next = 'd0; 
 i2c_sda_reg = 1'b0; 
 end 
 else
   begin 
   bit_counter_next = bit_counter + 1'b1; 
 delay_time_next = 'd0; 
 end 
 end 
 else
    delay_time_next = delay_time + 1'b1; 
 end 
第四个状态wait_device_ack_state:等待响应ACK信号。在发完器件地址8-bits数据后,FPGA要等待从AT24C02发来的响应信号。该响应信号为低,表示通信正常,否则通信不正常。回到idle状态。
+ 查看代码
 //wait ack signal. in this condition ,i2c_sda is input. when i2c_sda is low ,mean receive ack signal success 
 wait_device_ack_state: begin     
    if(delay_time >= 199)    //delay 4us 
   begin
   if(!i2c_sda)  //receive ack signal 
    begin
    state_next       = send_rom_address_state; 
 delay_time_next  = 'd0; 
 end
 else   //if no receice ack signal , means communication is wrong , back to idle state 
    begin
    delay_time_next = 'd0; 
 state_next = idle_state; 
 end
 end
 else
   delay_time_next = delay_time + 1'b1; 
 end 
第五个状态,发送数据地址状态:即发送需要操作的地址。
+ 查看代码
 //send the address will be write or read 
 send_rom_address_state: begin
    if(delay_time == 16)     //delay 320ns ,let data meet setup and hold time 
     i2c_sda_reg = rom_address[7-bit_counter]; 
    if(delay_time >= 199)    //delay 4us , 1-bit dats transfer finish 
    begin 
    if(bit_counter_next >= 7)  //send_8-bits data finish 
   begin
   bit_counter_next = 'd0; 
   state_next = wait_address_ack_state; 
 delay_time_next = 'd0; 
 i2c_sda_reg = 1'b0; 
 end
 else
   begin
   bit_counter_next = bit_counter + 1'b1; 
 delay_time_next = 'd0; 
 end
 end
 else
    delay_time_next = delay_time + 1'b1; 
 end 
第六个状态,等待数据地址写入回应ACK信号状态:在发完数据地址8-bits数据后,FPGA要等待从AT24C02发来的响应信号。该响应信号为低,表示通信正常,否则通信不正常。回到idle状态。这里要注意了,如果是写数据的话,要跳转到写数据的状态,而如果是读数据的话,要调到重新产生起始信号状态。因为前面说过,读操作的时候,在写完数据地址后,需要重新产生起始信号。
+ 查看代码
 wait_address_ack_state: begin
    i2c_sda_reg = 1'b1; 
    if(delay_time >= 199)     //delay 2us 
   begin
   if(!i2c_sda)  //receive ack signal 
    begin
    //according to the write_or_read  decide enter write state or read state 
 //0 mean write state    1 mean read state 
    if(!write_or_read) 
        state_next       = send_write_data_state; 
 else
     state_next        = regenerate_start_state; 
 delay_time_next  = 'd0; 
 end
 else   //if no receice ack signal , means communication is wrong , back to idle state 
    begin
    delay_time_next = 'd0; 
 state_next = idle_state; 
 end
 end
 else
   delay_time_next = delay_time + 1'b1; 
 end 
第七个状态:写数据状态。发送8-bit数据。
+ 查看代码
send_write_data_state: begin
if(delay_time == 16) //delay 320ns ,let data meet hold time
i2c_sda_reg = rom_write_data[7-bit_counter];
if(delay_time >= 199) //delay 4us ,1-bits transfer finish
begin
if(bit_counter_next >= 7) //send_8-bits data finish
begin
bit_counter_next = 'd0;
state_next = wait_write_data_ack_state;
delay_time_next = 'd0;
counter_number_next = counter_number + 1'b1; // send 1 8-bits data
i2c_sda_reg = 1'b0;
end
else
begin
bit_counter_next = bit_counter + 1'b1;
delay_time_next = 'd0;
end
end
else
delay_time_next = delay_time + 1'b1;
end
第八个状态:等待写数据响应ACK信号:在发完数据8-bits数据后,FPGA要等待从AT24C02发来的响应信号。该响应信号为低,表示通信正常,否则通信不正常。回到idle状态。
+ 查看代码
wait_write_data_ack_state: begin
i2c_sda_reg = 1'b0;
if(delay_time >= 199) //delay 4us
begin
if(!i2c_sda) //receive ack signal
begin
//when write operation number == data_number ,means this write operation is finish
//otherwise continue write operation
if( counter_number == write_data_number)
state_next = stop_state;
else
state_next = send_write_data_state;
delay_time_next = 'd0;
write_finish = 1'b1;
end
else //if no receice ack signal , means communication is wrong , back to idle state
begin
delay_time_next = 'd0;
state_next = idle_state;
end
end
else
delay_time_next = delay_time + 1'b1;
end
以上就是写的状态机设计。
之后是读的状态机设计。
第九个状态,重新产生起始信号状态。即重新产生起始信号,SCL保持高电平,SDA先保持高然后在拉低。
+ 查看代码
regenerate_start_state: begin
if(delay_time <= 40)
i2c_sda_reg = 1'b1;
else
i2c_sda_reg = 1'b0; //ic2 data pull down.mean begin to transfer data
if(delay_time >= 99) //delay 2us, meeting i2c data setup and hole timing
begin
delay_time_next = 'd0;
state_next = rewrite_device_address_state;
end
else
delay_time_next = delay_time + 1'b1;
end
第十个状态:发送数据地址和读。此时的first_byte_to_send的最低位为1,表示为读数据。
+ 查看代码
rewrite_device_address_state: begin
if(delay_time == 16) //delay 320ns ,let i2c data meet setup and hold time
i2c_sda_reg = first_byte_to_send[7-bit_counter];
if(delay_time >= 199) //delay 4us , 1-bits data transfer finish
begin
if(bit_counter_next >= 7) //send_8-bits data finish
begin
bit_counter_next = 'd0;
state_next = wait_rewrite_ack_state;
delay_time_next = 'd0;
i2c_sda_reg = 1'b0;
end
else
begin
bit_counter_next = bit_counter + 1'b1;
delay_time_next = 'd0;
end
end
else
delay_time_next = delay_time + 1'b1;
end
第十个状态:等待重新写器件地址回应信号。在发完8-bits数据后,FPGA要等待从AT24C02发来的响应信号。该响应信号为低,表示通信正常,否则通信不正常。回到idle状态。
+ 查看代码
wait_rewrite_ack_state: begin
i2c_sda_reg = 1'b0;
if(delay_time >= 199) //delay 4us
begin
if(!i2c_sda) //receive ack signal
begin
state_next = read_data_state;
delay_time_next = 'd0;
end
else //if no receice ack signal , means communication is wrong , back to idle state
begin
delay_time_next = 'd0;
state_next = idle_state;
end
end
else
delay_time_next = delay_time + 1'b1;
end
下面才是读数据的状态。
第十一个状态:读数据状态。在SCL高电平读取SDA数据,将数据移位至read_data_reg中保存。这里要注意,有个counter_number_next判断。这个counter_number_next用来表示已经读取的数据个数,因为支持连读,所以当已经读取的个数和设定的个数一致时,就要停止读取。而停止读取和继续读取的响应信号是不一样的。
+ 查看代码
read_data_state: begin
if(delay_time == 160) //delay3.2us ,let data meet setup and hold time
read_data_reg = {read_data[6:0],i2c_sda};
if(delay_time >= 199) //delay 4us
begin
if(bit_counter_next >= 7) //read_8-bits data
begin
bit_counter_next = 'd0;
delay_time_next = 'd0;
counter_number_next = counter_number + 1'b1;
//if the read data is the last data,goto the no ack state
//if the read data is not the last data,goto the ack state
if(counter_number_next == read_data_number )
state_next = get_read_data_no_ack_state;
else
state_next = get_read_data_ack_state;
end
else
begin
bit_counter_next = bit_counter + 1'b1;
delay_time_next = 'd0;
end
end
else
delay_time_next = delay_time + 1'b1;
end
第十二个状态:发送读取信号响应ACK信号。读取8-bit数据后,如果读取继续,FPGA要向AT24C02发送ACK低电平信号,表示要继续读取数据。
+ 查看代码
get_read_data_ack_state: begin
i2c_sda_reg = 1'b0;
if(delay_time >= 199) //delay 4us
begin
// if(!i2c_sda) //receive ack signal
// begin
//// when write operation number == data_number ,means this control is finish
//// otherwise continue write operation
state_next = read_data_state;
delay_time_next = 'd0;
read_finish = 1'b1;
// end
// else //if no receice ack signal , means communication is wrong , back to idle state
// begin
// delay_time_next = 'd0;
// state_next = idle_state;
// end
end
else
delay_time_next = delay_time + 1'b1;
end
第十三个状态:发送读取非响应ACK信号。读到最后一个8-bit数据后,要结束读取,FPGA要向AT24C02发送ACK高电平信号,表示读取结束。
+ 查看代码
get_read_data_no_ack_state: begin
i2c_sda_reg = 1'b1;
if(delay_time >= 199) //delay 4us
begin
// if(!i2c_sda) //receive ack signal
// begin
//when write operation number == data_number ,means this control is finish
//otherwise continue write operation
state_next = stop_state;
delay_time_next = 'd0;
read_finish = 1'b1;
// end
// else //if no receice ack signal , means communication is wrong , back to idle state
// begin
// delay_time_next = 'd0;
// state_next = idle_state;
// end
end
else
delay_time_next = delay_time + 1'b1;
end
最后一个状态;发送停止信号状态。SCL保持高电平,SDA数据先保持低,然后在拉高。产生一个结束信号。
+ 查看代码
stop_state: begin
if(delay_time >= 150)
i2c_sda_reg = 1'b1;
else
i2c_sda_reg = 1'b0;
if(delay_time >= 199)
state_next = idle_state;
else
delay_time_next = delay_time + 1'b1;
end
这样,就完成了IIC的状态机设计。这里有几个地方要注意:
1、 读取数据,要重新产生起始信号,如果不重新产生起始信号,读取不到数据。
2、 读取数据的时候,ACK信号是由FPGA给的。这要特别注意,不然的话,状态就直接跳转到idle状态了。既不能读取数据。
因为SDA数据是双向IO口,所以这里要判断SDA什么时候为输入,什么时候为输出。
reg i2c_sda_reg;
assign enable_read = (state == wait_device_ack_state ||state == wait_address_ack_state ||
state == read_data_state ||
//state == wait_read_data_ack_state ||
state == wait_write_data_ack_state ||
state == wait_rewrite_ack_state)?1'b1:1'b0;
assign i2c_sda = enable_read ? 1'bz : i2c_sda_reg_reg;
这里,定义了一个i2c_sda_reg,用来保存SDA的输出值。Enable_read为输入输出判断信号。为1,表示输入,为0,表示输出。那在什么为1,什么时候为0.只需判断现在的状态即可。即在需要从机ACK信号和读取数据是为1.
下面就是SCL。
+ 查看代码
always@(*) begin
//in idle_state , stop_state and ready_state, I2C clk is 1
if(state == idle_state || state == ready_state || state == regenerate_start_state)
i2c_scl = 1'b1;
// //in ready_state,to meet timing require . I2C clk is 0, wait to transfer data
// else if(state == ready_state)
// i2c_scl = 1'b0;
else
begin
//I2C clk period is 4us. so counter value is 200 . set duty is 50%
if(delay_time < 100)
i2c_scl = 1'b0;
else
i2c_scl = 1'b1;
end
end
这里如果不是产生起始信号,空闲状态和重新产生起始信号状态是,前半个状态为0,后半个状态为高。这里要注意,为什么不把停止信号状态放到第一个if中,那是为了防止误产生判断起始信号。
假设在前一个状态,SDA为高,到了停止状态,SCL为高,此时SDA变低,那就误产生了一个起始信号。
而first_byte_to_send,这里代码为:
+ 查看代码
reg [7:0] first_byte_to_send;
always@(*) begin
//first write device address,the last bit is 0,mean write
if( state == send_device_address_state )
first_byte_to_send = {4'b1010,device_address,1'b0};
//when read data ,should rewrite device address, and the last bit is 1,mean read
else
first_byte_to_send = {4'b1010,device_address,1'b1};
end
这里就是确定最低位为低还是高,从而表示还是写还是读。
按照这样一个状态机弄下来,就完成了IIC协议的AT24C02的驱动。然后添加串口模块,将串口发送的数据写入到AT24C02中,然后在将该数据读取回来,看看是否一样。

预先向0x0地址连续写入16个数据。也就是向0x0到0xf 16个地址写入数据。读17个数据,发现前16个数据是一样的,但是最后一个数据是FF。因为这个地址还没有写入数据,所以数据就是0xff。
以下附上的的程序端口部分:
+ 查看代码
module AT24C02_module(
input clk,
input rst_n,
input start,
input [2:0] device_address, //the device AT24C02 address
input [7:0] rom_address, //the rom address
input [7:0] rom_write_data, //write 8-bits data to the AT24C02
input write_or_read, //write mode or read mode 0 write 1 read
input [7:0] write_data_number, // write data number
input [7:0] read_data_number, //read data number
output reg[7:0] row_read_data, //read 8-bits data from AT24C02 in rom_address
output reg read_finish, //read data finish,mean external can read data
output reg write_finish, //write one byte data finsih.
output reg write_idle, //write data state, 1 mean external can write new data
inout i2c_sda, //I2C data , bidirectional port
output reg i2c_scl, //I2C clk 250K
output enable_read
);
可以看出端口还是比较复杂的,加一些额外信号时为了外部控制方便。
有注释的话,就很容易看出各个端口的作用。
这里最后一个enable_read,这个是为了使用chioscope查看信号而添加的端口。
我在外部有一段代码
assign look_i2c_sda = enable_read==1? i2c_sda:1'b0;
用来查看SDA作为输入时候的值,直接assign look_i2c_sda = i2c_sda。生成bit流会报错,所以这里采用这样的一个方式。
只要注意我说的那些问题,就一定是可以驱动IIC器件的了。。。。
最后贴上整个源代码以及testbench代码:
源代码:
+ 查看代码
`timescale 1ns / 1ps 
////////////////////////////////////////////////////////////////////////////////// 
// Company:  
// Engineer:  
//  
// Create Date:    21:05:22 11/12/2014  
// Design Name:  
// Module Name:    AT24C02_module  
// Project Name:  
// Target Devices:  
// Tool versions:  
// Description:  
// 
// Dependencies:  
// 
// Revision:  
// Revision 0.01 - File Created 
// Additional Comments:  
// 
////////////////////////////////////////////////////////////////////////////////// 
module AT24C02_module( 
            input                           clk, 
            input                           rst_n, 
              
            input                           start,               
            input       [2:0]               device_address,    //the device AT24C02 address 
            input       [7:0]               rom_address,       //the rom address 
            input       [7:0]           rom_write_data,    //write 8-bits data to the AT24C02 
            input                           write_or_read,       //write mode or read mode   0 write  1 read 
              
            input    [7:0]              write_data_number,       // write data number 
            input    [7:0]          read_data_number,  //read  data number 
              
              
            output  reg[7:0]       row_read_data,     //read 8-bits data from AT24C02 in rom_address 
              
            output  reg             read_finish,       //read data finish,mean external can read data 
            output   reg                write_finish,     //write one byte data finsih. 
            output   reg                write_idle,       //write data state, 1 mean external can write new data 
              
            inout                           i2c_sda,            //I2C    data   , bidirectional port 
            output  reg             i2c_scl,             //I2C    clk   250K 
              
            output                      enable_read 
    ); 
  
  
    localparam  idle_state                      =    'd0; 
     localparam  ready_state                    =     'd1; 
     localparam  send_device_address_state     =      'd2; 
     localparam  wait_device_ack_state          =    'd3; 
     localparam  send_rom_address_state         =    'd4; 
     localparam  wait_address_ack_state         =    'd5; 
     localparam  send_write_data_state          =    'd6; 
     localparam  wait_write_data_ack_state      =    'd7; 
     localparam  regenerate_start_state       =    'd8;  //regenerate start ,begin to read  
     localparam  rewrite_device_address_state =       'd9;   
     localparam  wait_rewrite_ack_state         =    'd10; 
     localparam  read_data_state                    =     'd11; 
     localparam  get_read_data_ack_state        =    'd12;  
     localparam  get_read_data_no_ack_state  =    'd13; 
     localparam  stop_state                         =    'd14; 
       
       
     reg [3:0]  state;       //current state 
     reg [3:0]  state_next;  //next  state 
     always@(posedge clk or negedge rst_n)  begin
        if(!rst_n) 
             state <= idle_state; 
         else
             state <= state_next; 
     end
       
       
     //record delay time, because every state has different time. 
     reg [7:0] delay_time; 
     reg [7:0] delay_time_next; 
     always@(posedge clk or negedge rst_n)  begin
        if(!rst_n) 
             delay_time  <= 'd0; 
         else
             delay_time  <= delay_time_next; 
     end
       
     //record transfer which bit, serial transfer,so need a variable value  
     reg [2:0] bit_counter;        //current transfer bit 
     reg [2:0] bit_counter_next;   //next transfer bit 
     always@(posedge clk or negedge rst_n)  begin
        if(!rst_n) 
             bit_counter <= 'd0; 
         else
             bit_counter <= bit_counter_next; 
     end
       
       
     reg [7:0] first_byte_to_send; 
     always@(*) begin
        //first write device address,the last bit is 0,mean write 
        if( state == send_device_address_state )  
             first_byte_to_send = {4'b1010,device_address,1'b0}; 
         //when read data ,should rewrite device address, and the last bit is 1,mean read 
         else
             first_byte_to_send = {4'b1010,device_address,1'b1}; 
     end
  
       
       
     //when enable_read is 1, i2c_sda is input, otherwise is output 
     //wire enable_read; 
     reg i2c_sda_reg; 
     assign  enable_read = (state == wait_device_ack_state ||state == wait_address_ack_state ||  
                                    state == read_data_state ||  
                                    //state == wait_read_data_ack_state || 
                                    state == wait_write_data_ack_state || 
                                    state == wait_rewrite_ack_state)?1'b1:1'b0; 
     assign  i2c_sda  = enable_read ? 1'bz : i2c_sda_reg_reg; 
       
       
     reg i2c_sda_reg_reg; 
     always@(posedge clk or negedge rst_n) begin
        if(!rst_n) 
             i2c_sda_reg_reg = 1'b1; 
         else
             i2c_sda_reg_reg = i2c_sda_reg; 
     end
       
     //write data number or read data number 
     //because write and read can be continuous,so need a counter_number to record the already write or read address number 
     //when counter_number == data_number,that means control finish  
     reg [7:0] counter_number; 
     reg [7:0] counter_number_next;  
     always@(posedge clk or negedge rst_n)  begin
        if(!rst_n) 
            counter_number = 8'd0; 
         else
            counter_number = counter_number_next; 
     end
       
       
     reg [7:0]  read_data; 
     reg [7:0]  read_data_reg; 
     always@(posedge clk or negedge rst_n) begin
        if(!rst_n)  
            read_data <= 8'd0; 
         else
            read_data <= read_data_reg; 
     end
       
       
     always@(*)  begin
        state_next       = state; 
         delay_time_next = delay_time; 
         bit_counter_next = bit_counter; 
         counter_number_next = counter_number; 
         read_data_reg = read_data; 
         i2c_sda_reg = i2c_sda_reg_reg;  
         read_finish = 1'b0; 
         write_finish = 1'b0; 
         write_idle = 1'b0; 
         case(state) 
         idle_state: begin
            delay_time_next  =  'd0; 
             bit_counter_next =  'd0;    //send bit counter 
             counter_number_next = 'd0;  //send data counter 
             read_data_reg  = 'd0; 
             write_idle = 1'b1; 
             i2c_sda_reg = 1'b1;  //if no data transfer ,i2c data is 1        
             if(start) 
                state_next = ready_state; 
         end
         ready_state: begin
            i2c_sda_reg = 1'b0;  //ic2 data pull down.mean begin to transfer data  
             if(delay_time >= 99) //delay 2us, meeting i2c data  setup and hole timing 
                 begin
                    delay_time_next = 'd0; 
                     state_next = send_device_address_state; 
                 end
             else
                delay_time_next = delay_time + 1'b1; 
         end
         //send first byte. including  device address and r/w enable 
         send_device_address_state: begin
            if(delay_time == 16) //delay 320ns ,let i2c data meet setup and hold time 
                 i2c_sda_reg = first_byte_to_send[7-bit_counter]; 
            if(delay_time >= 199)    //delay 4us , 1-bits data transfer finish 
                begin
                    if(bit_counter_next >= 7)  //send_8-bits data  finish 
                       begin
                           bit_counter_next = 'd0; 
                           state_next = wait_device_ack_state; 
                            delay_time_next = 'd0; 
                            i2c_sda_reg = 1'b0; 
                        end
                     else
                       begin
                           bit_counter_next = bit_counter + 1'b1; 
                            delay_time_next = 'd0; 
                        end
                 end
             else
                delay_time_next = delay_time + 1'b1; 
         end
         //wait ack signal. in this condition ,i2c_sda is input. when i2c_sda is low ,mean receive ack signal success 
         wait_device_ack_state: begin     
            if(delay_time >= 199)    //delay 4us 
               begin
                   if(!i2c_sda)  //receive ack signal 
                        begin
                            state_next       = send_rom_address_state; 
                             delay_time_next  = 'd0; 
                         end
                    else   //if no receice ack signal , means communication is wrong , back to idle state 
                        begin
                            delay_time_next = 'd0; 
                             state_next = idle_state; 
                         end
                end
             else
               delay_time_next = delay_time + 1'b1; 
         end
         //send the address will be write or read 
         send_rom_address_state: begin
            if(delay_time == 16)     //delay 320ns ,let data meet setup and hold time 
                 i2c_sda_reg = rom_address[7-bit_counter]; 
            if(delay_time >= 199)    //delay 4us , 1-bit dats transfer finish 
                begin 
                    if(bit_counter_next >= 7)  //send_8-bits data finish 
                       begin
                           bit_counter_next = 'd0; 
                           state_next = wait_address_ack_state; 
                            delay_time_next = 'd0; 
                            i2c_sda_reg = 1'b0; 
                        end
                     else
                       begin
                           bit_counter_next = bit_counter + 1'b1; 
                            delay_time_next = 'd0; 
                        end
                 end
             else
                delay_time_next = delay_time + 1'b1; 
         end
         wait_address_ack_state: begin
            i2c_sda_reg = 1'b1; 
            if(delay_time >= 199)     //delay 2us 
               begin
                   if(!i2c_sda)  //receive ack signal 
                        begin
                            //according to the write_or_read  decide enter write state or read state 
                             //0 mean write state    1 mean read state 
                            if(!write_or_read) 
                                state_next       = send_write_data_state; 
                             else
                                 state_next      = regenerate_start_state; 
                             delay_time_next  = 'd0; 
                         end
                    else   //if no receice ack signal , means communication is wrong , back to idle state 
                        begin
                            delay_time_next = 'd0; 
                             state_next = idle_state; 
                         end
                end
             else
               delay_time_next = delay_time + 1'b1; 
         end
         send_write_data_state: begin
            if(delay_time == 16)     //delay 320ns ,let data meet hold time 
                  i2c_sda_reg = rom_write_data[7-bit_counter]; 
            if(delay_time >= 199)    //delay 4us ,1-bits transfer finish 
                begin
                    if(bit_counter_next >= 7)  //send_8-bits data finish 
                       begin
                           bit_counter_next = 'd0; 
                           state_next = wait_write_data_ack_state; 
                            delay_time_next = 'd0; 
                            counter_number_next = counter_number + 1'b1; // send 1  8-bits data 
                            i2c_sda_reg = 1'b0; 
                        end
                     else
                       begin
                           bit_counter_next = bit_counter + 1'b1; 
                            delay_time_next = 'd0; 
                        end
                      畅学电子
畅学电子








