OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5224|回复: 3

[ALTERA] IIC通信协议实现EEPROM 24LC04的读写

[复制链接]

24

主题

57

帖子

0

精华

高级会员

Rank: 4

积分
800
金钱
800
注册时间
2016-11-25
在线时间
93 小时
发表于 2019-11-7 10:46:47 | 显示全部楼层 |阅读模式
很感谢正点原子团队将各种学习资料免费分享,而且各自资料都做的很详细,很有条例。自己学习了提供的FPGA资料之后,写的一个IIC通信,读写EEPROM 24LC04,仿真通过,亲测能用,感谢这个免费平台,我也免费分享一下,当然代码中肯定存在很多问题,希望各位批评指正!
代码部分:
//IIC驱动模块
module I2C_Driver(
         input                        sys_clk_50m    ,
         input                        sys_rst_n    ,
                           
         input                        iic_en        ,    //IIC使能
         input                        wr_control    ,    //IIC读写控制信号,0:写 1:读
         input                        addr_control,    //地址字节控制,0:1字节地址,1:2字节地址
         input[15:0]                iic_addr        ,    //IIC字部地址输入
         input[ 7:0]                write_data    ,    //写入IIC器件的数据
           
         output reg[7:0]            read_data    ,    //读取IIC器件的数据
         output reg                    iic_done        ,    //一次IIC操作完成信号
           
        
         output reg                    ACK            ,    //应答信号
         output reg                 iic_scl        ,    //IIC时钟输出
                           
         inout                          iic_sda            //IIC数据线(双向)
                           
);  
  
parameter   SLAVE_ADDR     = 7'b1010000                            ;//IIC器件地址
parameter    Write         = 1'b0                                    ;//写
parameter    Read          = 1'b1                                    ;//读
parameter   CLK_FREQ       = 26'd50_000_000                        ;//IIC模块的驱动时钟频率(CLK_FREQ),即系统时钟50MHz
parameter   I2C_FREQ       = 20'd250_000                             ;//IIC的SCL时钟频率为250kHz
parameter    CLK_Devide     = (CLK_FREQ / I2C_FREQ) >> 2'd3    ;//分频系数


parameter    WRITE_FLAG    = 1'b0                                    ;//写标志位
parameter    READ_FLAG    = 1'b1                                    ;//读标志位


//localparam define
localparam  iic_idle     = 8'b0000_0001;              //空闲状态
localparam  iic_sladdr   = 8'b0000_0010;              //器件地址
localparam  iic_addr16   = 8'b0000_0100;              //发送16位字地址
localparam  iic_addr8    = 8'b0000_1000;              //发送8位字地址
localparam  iic_data_wr  = 8'b0001_0000;              //写数据(8 bit)
localparam  iic_addr_rd  = 8'b0010_0000;              //器件地址读
localparam  iic_data_rd  = 8'b0100_0000;              //读数据(8 bit)
localparam  iic_stop     = 8'b1000_0000;              //结束I2C操作

reg         sda_dir     ;                              //I2C数据(SDA)方向控制,1ut,0:高阻,可以输出
reg         iic_sda_out ;                                  //SDA输出
wire            iic_sda_in    ;                                      //SDA输入



reg[7:0]        current_state;               
reg[7:0]        next_state;

reg         state_done1;                         //状态结束
reg         state_done2;                         //状态结束
reg         state_done3;                         //状态结束
reg         state_done4;                         //状态结束
reg         state_done5;                         //状态结束
reg         state_done6;                         //状态结束
reg         state_done7;                         //状态结束

reg         wr_flag        ;                        //读写标志
reg[15:0]    addr_buff    ;                                //写地址地址缓存
reg[ 7:0]    wdata_buff    ;                                 //写数据缓存
reg[ 7:0]    rdata_buff    ;                                //读取数据缓存


reg[11:0]    sys_clk_cnt    ;                                //系统时钟计数器
reg[ 5:0]    dri_clk_cnt    ;
reg            dri_clk        ;                                //驱动iic时钟


assign          iic_sda         = sda_dir ?  iic_sda_out : 1'bz; //SDA数据输出或高阻,高阻状态时数据线的状态不定这是就可以由从机来控制数据线的状态,主机负责读取状态
assign         iic_sda_in  = iic_sda ;                      //SDA数据输入


//对系统时钟计数
always @ ( posedge sys_clk_50m or negedge sys_rst_n )    begin
    if( !sys_rst_n )
        sys_clk_cnt <= 12'd0;
    else if( sys_clk_cnt == CLK_Devide - 1 )
        sys_clk_cnt <= 12'd0;
    else
        sys_clk_cnt <= sys_clk_cnt + 1'b1;
end

//获得驱动IIC时钟,IIC时钟250khz,驱动IIC时钟为4*250khz=1Mhz
always @ ( posedge sys_clk_50m or negedge sys_rst_n )    begin
    if( !sys_rst_n )
        dri_clk <= 1'b1;
    else if( sys_clk_cnt == CLK_Devide - 1 )
        dri_clk <= ~dri_clk;        
    else
        dri_clk <= dri_clk;
end



//(三段式状态机)同步时序描述状态转移
always @ ( posedge sys_clk_50m or negedge sys_rst_n )    begin
    if( !sys_rst_n )
        current_state <= iic_idle;
    else
        current_state <= next_state;
end
//组合逻辑判断状态转移
always @ ( * ) begin
    case( current_state )
        iic_idle   : if( iic_en )//1                            //iic使能之后
                            next_state <= iic_sladdr;        //进入器件地址状态
                         else
                            next_state <= iic_idle;                                
        iic_sladdr : if( state_done1 ) begin//2
                            if( addr_control == 0)            //进入字地址为1字节状态,直接发一个字节的地址
                                next_state <= iic_addr8;
                           else                                     //进入字地址为2字节状态,先发高字节地址
                                next_state <= iic_addr16;
                         end
                         else
                            next_state <= iic_sladdr;                                
        iic_addr16 : if( state_done2 )    //4                        
                            next_state <= iic_addr8;        //进入地址低字节
                         else
                            next_state <= iic_addr16;
                           
        iic_addr8  : if( state_done3 )    begin    //8               
                            if( wr_flag  == 1'b1 )                        //进入读数据
                                next_state <= iic_addr_rd;
                            else                                  //进入写数据
                                next_state <= iic_data_wr;
                         end
                         else
                            next_state <= iic_addr8;                           
        iic_data_wr : if( state_done4 )                    //写数据,16
                            next_state <= iic_stop;
                         else
                            next_state <= iic_data_wr;                           
        iic_addr_rd : if( state_done5 )
                            next_state <= iic_data_rd;        //写地址读取数据,32
                         else
                            next_state <= iic_addr_rd;                                
        iic_data_rd : if( state_done6 )                        //读取数据,64
                            next_state <= iic_stop;
                         else
                            next_state <= iic_data_rd;                           
        iic_stop   : if( state_done7 )                        //停止信号,128
                            next_state <= iic_idle;
                         else
                            next_state <= iic_stop;                           
        default      :   next_state <= iic_idle;            //空闲状态
    endcase
end

//时序电路描述状态输出
always @ ( posedge dri_clk or negedge sys_rst_n )    begin
    if( !sys_rst_n ) begin
        iic_scl            <= 1'b1;        //时钟线拉高
        sda_dir             <= 1'b1;        //数据线输出
        iic_sda_out        <= 1'b1;        //数据线拉高
        addr_buff         <= 16'd0;    //字地址缓存
        wdata_buff         <= 8'd0;        //写数据缓存
        read_data         <= 8'd0;        //读数据寄存器
        rdata_buff        <= 8'd0;        //读数据缓存
        wr_flag             <= 1'b0;        //读写标志位
        dri_clk_cnt     <= 6'd0;        //IIC驱动时钟计数器   
        state_done1     <= 1'b0;        //各个状态结束标志位
        state_done2     <= 1'b0;
        state_done3     <= 1'b0;
        state_done4     <= 1'b0;
        state_done5     <= 1'b0;
        state_done6     <= 1'b0;
        state_done7     <= 1'b0;
        ACK                <= 1'b0;        //应答标志位
        iic_done         <= 1'b0;        //IIC计数操作
    end
    else begin
        dri_clk_cnt <= dri_clk_cnt + 1'b1;
        state_done1     <= 1'b0;
        state_done2     <= 1'b0;
        state_done3     <= 1'b0;
        state_done4     <= 1'b0;
        state_done5     <= 1'b0;
        state_done6     <= 1'b0;
        state_done7     <= 1'b0;
        addr_buff          <= iic_addr        ;        //将字地址缓存
        wdata_buff         <= write_data    ;        //将待写进从机的数据缓存
        wr_flag             <= wr_control    ;        //获得读写信号
        ACK                <= 1'b0;                    //应答标志位
        iic_done         <= 1'b0;                    //IIC结束标志信号为低电平
        case( current_state )
            iic_idle  :     begin
                                    iic_scl         <= 1'b1;        //空闲时:时钟线和数据线拉高
                                    sda_dir         <= 1'b1;        //输出
                                    iic_sda_out <= 1'b1;        //拉高
                                    dri_clk_cnt <= 6'd0;        //IIC驱动时钟计数器
                                    if( iic_en )  begin
                                        wr_flag     <= wr_control;    //获得读写信号
                                    end
                                end
            iic_sladdr :    begin
                                    case( dri_clk_cnt )
                                        6'd0    :    iic_scl <= 1'b1;            //拉低数据线准备
                                        6'd1    :    begin
                                                        sda_dir         <= 1'b1;    //输出
                                                        iic_sda_out <= 1'b0;    //数据线拉低,发送起始信号
                                                    end
                                       
                                        6'd2    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd3    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd4    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd5    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd6    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd7    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd8    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                       
                                        6'd9    :    iic_scl        <= 1'b0;        //拉低数据线准备
                                        6'd10    :    iic_sda_out <= SLAVE_ADDR[6];//器件地址
                                        6'd11    :    iic_scl        <= 1'b1;    //拉高锁存数据
                                        6'd12    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd13    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd14    :    iic_sda_out <= SLAVE_ADDR[5];//器件地址
                                        6'd15    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd16    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd17    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd18    :    iic_sda_out <= SLAVE_ADDR[4];//器件地址
                                        6'd19    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd20    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd21    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd22    :    iic_sda_out <= SLAVE_ADDR[3];//器件地址
                                        6'd23    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd24    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd25    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd26    :    iic_sda_out <= SLAVE_ADDR[2];//器件地址
                                        6'd27    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd28    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd29    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd30    :    iic_sda_out <= SLAVE_ADDR[1];//器件地址
                                        6'd31    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd32    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd33    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd34    :    iic_sda_out <= SLAVE_ADDR[0];//器件地址
                                        6'd35    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd36    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd37    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd38    :    iic_sda_out <= WRITE_FLAG;//写
                                        6'd39    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd40    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd41    :    iic_scl        <= 1'b0;//拉低数据线准备                                                                        
                                        6'd42    :    begin//从机应答
                                                        sda_dir <= 1'b0;//让数据线变为高阻态,主机读取数据线的电平,低电平为有效应答
                                                    end
                                        6'd43    :    iic_scl    <= 1'b1;//拉高锁存数据   
                                        6'd44    :    begin
                                                        iic_scl     <= 1'b1;//拉高锁存数据   
                                                        ACK        <=    iic_sda_in;
                                                    end
                                        6'd45    :    begin
                                                        iic_scl        <= 1'b0;//拉低数据线准备   
                                                        dri_clk_cnt    <= 6'd0;//
                                                        state_done1    <= 1'b1;
                                                    end
                                        default : ;
                                    endcase
                                end
            iic_addr16 : begin                           
                                case( dri_clk_cnt )
                                        6'd0    :    begin
                                                        iic_scl        <= 1'b0;
                                                        sda_dir         <= 1'b1;
                                                        iic_sda_out <= addr_buff[15];
                                                    end
                                        6'd1    :    iic_scl        <= 1'b1;
                                        6'd2    :    iic_scl        <= 1'b1;
                                        6'd3    :    iic_scl        <= 1'b0;
                                        6'd4    :    iic_sda_out <= addr_buff[14];
                                        6'd5    :    iic_scl        <= 1'b1;
                                        6'd6    :    iic_scl        <= 1'b1;
                                        6'd7    :    iic_scl        <= 1'b0;
                                        6'd8    :    iic_sda_out <= addr_buff[13];
                                        6'd9    :    iic_scl        <= 1'b1;
                                        6'd10    :    iic_scl        <= 1'b1;
                                        6'd11    :    iic_scl        <= 1'b0;
                                        6'd12    :    iic_sda_out <= addr_buff[12];
                                        6'd13    :    iic_scl        <= 1'b1;
                                        6'd14    :    iic_scl        <= 1'b1;
                                        6'd15    :    iic_scl        <= 1'b0;
                                        6'd16    :    iic_sda_out <= addr_buff[11];
                                        6'd17    :    iic_scl        <= 1'b1;
                                        6'd18    :    iic_scl        <= 1'b1;
                                        6'd19    :    iic_scl        <= 1'b0;
                                        6'd20    :    iic_sda_out <= addr_buff[10];
                                        6'd21    :    iic_scl        <= 1'b1;
                                        6'd22    :    iic_scl        <= 1'b1;
                                        6'd23    :    iic_scl        <= 1'b0;
                                        6'd24    :    iic_sda_out <= addr_buff[9];
                                        6'd25    :    iic_scl        <= 1'b1;
                                        6'd26    :    iic_scl        <= 1'b1;
                                        6'd27    :    iic_scl        <= 1'b0;
                                        6'd28    :    iic_sda_out <= addr_buff[8];
                                        6'd29    :    iic_scl        <= 1'b1;
                                        6'd30    :    iic_scl         <= 1'b1;                                    
                                        6'd31    :    iic_scl        <= 1'b0;
                                        6'd32    :    begin                        //从机应答
                                                        sda_dir     <= 1'b0;
                                                    end
                                        6'd33    :    iic_scl         <= 1'b1;   
                                        6'd34    :    begin
                                                        iic_scl     <= 1'b1;
                                                        ACK        <=    iic_sda_in;
                                                    end
                                        6'd35    :    begin
                                                        iic_scl         <= 1'b0;   
                                                        state_done2    <= 1'b1;//4
                                                        dri_clk_cnt    <= 6'd0;//
                                                    end
                                        default : ;
                                    endcase
                             end
            iic_addr8 : begin
                                case( dri_clk_cnt )
                                        6'd0    :    begin
                                                        iic_scl        <= 1'b0;
                                                        sda_dir         <= 1'b1;
                                                        iic_sda_out <= addr_buff[7];
                                                    end
                                        6'd1    :    iic_scl        <= 1'b1;
                                        6'd2    :    iic_scl        <= 1'b1;
                                        6'd3    :    iic_scl        <= 1'b0;
                                        6'd4    :    iic_sda_out <= addr_buff[6];
                                        6'd5    :    iic_scl        <= 1'b1;
                                        6'd6    :    iic_scl        <= 1'b1;
                                        6'd7    :    iic_scl        <= 1'b0;
                                        6'd8    :    iic_sda_out <= addr_buff[5];
                                        6'd9    :    iic_scl        <= 1'b1;
                                        6'd10    :    iic_scl        <= 1'b1;
                                        6'd11    :    iic_scl        <= 1'b0;
                                        6'd12    :    iic_sda_out <= addr_buff[4];
                                        6'd13    :    iic_scl        <= 1'b1;
                                        6'd14    :    iic_scl        <= 1'b1;
                                        6'd15    :    iic_scl        <= 1'b0;
                                        6'd16    :    iic_sda_out <= addr_buff[3];
                                        6'd17    :    iic_scl        <= 1'b1;
                                        6'd18    :    iic_scl        <= 1'b1;
                                        6'd19    :    iic_scl        <= 1'b0;
                                        6'd20    :    iic_sda_out <= addr_buff[2];
                                        6'd21    :    iic_scl        <= 1'b1;
                                        6'd22    :    iic_scl        <= 1'b1;
                                        6'd23    :    iic_scl        <= 1'b0;
                                        6'd24    :    iic_sda_out <= addr_buff[1];
                                        6'd25    :    iic_scl        <= 1'b1;
                                        6'd26    :    iic_scl        <= 1'b1;
                                        6'd27    :    iic_scl        <= 1'b0;
                                        6'd28    :    iic_sda_out <= addr_buff[0];
                                        6'd29    :    iic_scl        <= 1'b1;
                                        6'd30    :    iic_scl        <= 1'b1;                                
                                        6'd31    :    iic_scl        <= 1'b0;
                                        6'd32    :    begin            //从机应答
                                                        sda_dir     <= 1'b0;
                                                    end
                                        6'd33    :    iic_scl         <= 1'b1;   
                                        6'd34    :    begin
                                                        iic_scl     <= 1'b1;   
                                                        ACK        <= iic_sda_in;        
                                                    end   
                                        6'd35    :    begin
                                                        iic_scl         <= 1'b0;   
                                                        state_done3 <= 1'b1;//8
                                                        dri_clk_cnt    <= 6'd0;//
                                                    end
                                        default : ;
                                    endcase
                            end
            iic_data_wr : begin   
                                case( dri_clk_cnt )
                                        6'd0    :    begin
                                                        iic_scl        <= 1'b0;
                                                        sda_dir         <= 1'b1;
                                                        sda_dir         <= 1'b1;
                                                        iic_sda_out <= wdata_buff[7];
                                                    end
                                        6'd1    :    iic_scl        <= 1'b1;
                                        6'd2    :    iic_scl        <= 1'b1;
                                        6'd3    :    iic_scl        <= 1'b0;
                                        6'd4    :    iic_sda_out <= wdata_buff[6];
                                        6'd5    :    iic_scl        <= 1'b1;
                                        6'd6    :    iic_scl        <= 1'b1;
                                        6'd7    :    iic_scl        <= 1'b0;
                                        6'd8    :    iic_sda_out <= wdata_buff[5];
                                        6'd9    :    iic_scl        <= 1'b1;
                                        6'd10    :    iic_scl        <= 1'b1;
                                        6'd11    :    iic_scl        <= 1'b0;
                                        6'd12    :    iic_sda_out <= wdata_buff[4];
                                        6'd13    :    iic_scl        <= 1'b1;
                                        6'd14    :    iic_scl        <= 1'b1;
                                        6'd15    :    iic_scl        <= 1'b0;
                                        6'd16    :    iic_sda_out <= wdata_buff[3];
                                        6'd17    :    iic_scl        <= 1'b1;
                                        6'd18    :    iic_scl        <= 1'b1;
                                        6'd19    :    iic_scl        <= 1'b0;
                                        6'd20    :    iic_sda_out <= wdata_buff[2];
                                        6'd21    :    iic_scl        <= 1'b1;
                                        6'd22    :    iic_scl        <= 1'b1;
                                        6'd23    :    iic_scl        <= 1'b0;
                                        6'd24    :    iic_sda_out <= wdata_buff[1];
                                        6'd25    :    iic_scl        <= 1'b1;
                                        6'd26    :    iic_scl        <= 1'b1;
                                        6'd27    :    iic_scl        <= 1'b0;
                                        6'd28    :    iic_sda_out <= wdata_buff[0];
                                        6'd29    :    iic_scl        <= 1'b1;
                                        6'd30    :    iic_scl        <= 1'b1;                                
                                        6'd31    :    iic_scl        <= 1'b0;
                                        6'd32    :    begin            //从机应答
                                                        sda_dir     <= 1'b0;
                                                    end
                                        6'd33    :    begin
                                                        iic_scl     <= 1'b1;
                                                        ACK        <= iic_sda_in;
                                                    end
                                        6'd34    :    iic_scl         <= 1'b1;        
                                        6'd35    :    begin
                                                        iic_scl         <= 1'b0;   
                                                        state_done4    <= 1'b1;//16
                                                        dri_clk_cnt    <= 6'd0;//
                                                    end
                                        default : ;
                                    endcase                                 
                              end
            iic_addr_rd : begin
                                    case( dri_clk_cnt )
                                        6'd0    :    begin
                                                        iic_scl         <= 1'b0;    //拉低数据线准备
                                                        sda_dir         <= 1'b1;    //输出
                                                        iic_sda_out <= 1'b1;    //数据线拉低,发送起始信号
                                                    end
                                        6'd1    :    begin
                                                        iic_scl         <= 1'b1;    //拉低数据线准备
                                                        sda_dir         <= 1'b1;    //输出
                                                        iic_sda_out <= 1'b1;    //数据线拉低,发送起始信号
                                                    end
                                       
                                        6'd2    :    iic_sda_out    <= 1'b1;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd3    :    iic_sda_out    <= 1'b1;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd4    :    iic_sda_out    <= 1'b1;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd5    :    iic_sda_out    <= 1'b1;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd6    :    iic_sda_out    <= 1'b1;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd7    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd8    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd9    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd10    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd11    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                        6'd12    :    iic_sda_out    <= 1'b0;        //SDA低电平时间持续要大于4us时SCL才能拉低
                                       
                                        6'd13    :    iic_scl        <= 1'b0;        //拉低数据线准备
                                        6'd14    :    iic_sda_out <= SLAVE_ADDR[6];//器件地址
                                        6'd15    :    iic_scl        <= 1'b1;    //拉高锁存数据
                                        6'd16    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd17    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd18    :    iic_sda_out <= SLAVE_ADDR[5];//器件地址
                                        6'd19    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd20    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd21    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd22    :    iic_sda_out <= SLAVE_ADDR[4];//器件地址
                                        6'd23    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd24    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd25    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd26    :    iic_sda_out <= SLAVE_ADDR[3];//器件地址
                                        6'd27    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd28    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd29    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd30    :    iic_sda_out <= SLAVE_ADDR[2];//器件地址
                                        6'd31    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd32    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd33    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd34    :    iic_sda_out <= SLAVE_ADDR[1];//器件地址
                                        6'd35    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd36    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd37    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd38    :    iic_sda_out <= SLAVE_ADDR[0];//器件地址
                                        6'd39    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd40    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd41    :    iic_scl        <= 1'b0;//拉低数据线准备
                                        6'd42    :    iic_sda_out <= READ_FLAG;//写
                                        6'd43    :    iic_scl        <= 1'b1;//拉高锁存数据
                                        6'd44    :    iic_scl        <= 1'b1;//拉高锁存数据
                                       
                                        6'd45    :    iic_scl        <= 1'b0;//拉低数据线准备                                                                        
                                        6'd46    :    begin//从机应答
                                                        sda_dir <= 1'b0;//让数据线变为高阻态,主机读取数据线的电平,低电平为有效应答
                                                    end
                                        6'd47    :    iic_scl    <= 1'b1;//拉高锁存数据   
                                        6'd48    :    begin
                                                        iic_scl     <= 1'b1;//拉高锁存数据   
                                                        ACK        <=    iic_sda_in;
                                                    end
                                        6'd49    :    begin
                                                        iic_scl        <= 1'b0;//拉低数据线准备   
                                                        dri_clk_cnt    <= 6'd0;//
                                                        state_done5    <= 1'b1;
                                                    end
                                        default : ;
                                    endcase
                            end
            iic_data_rd : begin
                                    case( dri_clk_cnt )
                                        6'd0    :    begin
                                                        iic_scl        <= 1'b0;
                                                        sda_dir         <= 1'b0;
                                                    end
                                        6'd1    :    iic_scl            <= 1'b1;
                                        6'd2    :    rdata_buff[7]    <= iic_sda_in;
                                        6'd3    :    iic_scl            <= 1'b0;
                                        6'd4    :    iic_scl            <= 1'b0;
                                        6'd5    :    iic_scl            <= 1'b1;
                                        6'd6    :    rdata_buff[6]    <= iic_sda_in;
                                        6'd7    :    iic_scl            <= 1'b0;
                                        6'd8    :    iic_scl            <= 1'b0;
                                        6'd9    :    iic_scl            <= 1'b1;
                                        6'd10    :    rdata_buff[5]    <= iic_sda_in;
                                        6'd11    :    iic_scl            <= 1'b0;
                                        6'd12    :    iic_scl            <= 1'b0;
                                        6'd13    :    iic_scl            <= 1'b1;
                                        6'd14    :    rdata_buff[4]    <= iic_sda_in;
                                        6'd15    :    iic_scl            <= 1'b0;
                                        6'd16    :    iic_scl            <= 1'b0;
                                        6'd17    :    iic_scl            <= 1'b1;
                                        6'd18    :    rdata_buff[3]    <= iic_sda_in;
                                        6'd19    :    iic_scl            <= 1'b0;
                                        6'd20    :    iic_scl            <= 1'b0;
                                        6'd21    :    iic_scl            <= 1'b1;
                                        6'd22    :    rdata_buff[2]    <= iic_sda_in;
                                        6'd23    :    iic_scl            <= 1'b0;
                                        6'd24    :    iic_scl            <= 1'b0;
                                        6'd25    :    iic_scl            <= 1'b1;
                                        6'd26    :    rdata_buff[1]    <= iic_sda_in;
                                        6'd27    :    iic_scl            <= 1'b0;
                                        6'd28    :    iic_scl            <= 1'b0;
                                        6'd29    :    iic_scl             <= 1'b1;
                                        6'd30    :    rdata_buff[0]    <= iic_sda_in;                                
                                        6'd31    :    iic_scl            <= 1'b0;
                                        6'd32    :    begin            
                                                        sda_dir         <= 1'b1;//非应答
                                                        iic_sda_out    <= 1'b1;
                                                    end
                                        6'd33    :    iic_scl     <= 1'b1;   
                                        6'd34    :    iic_scl     <= 1'b1;        
                                        6'd35    :    begin
                                                        iic_scl         <= 1'b0;   
                                                        state_done6    <= 1'b1;//64
                                                        dri_clk_cnt    <= 6'd0;//
                                                        read_data    <= rdata_buff;
                                                    end
                                        default : ;
                                    endcase               
                                end
            iic_stop : begin                                                    //结束IIC操作
                                sda_dir         <= 1'b1;
                             case( dri_clk_cnt )
                                6'd0     :    begin                                    //从机应答
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b0;
                                            end
                                6'd1    :     iic_scl         <= 1'b1;   
                                6'd2    :     iic_sda_out    <= 1'b0;               
                                6'd3    :     iic_sda_out    <= 1'b0;   
                                6'd4    :     iic_sda_out    <= 1'b0;   
                                6'd5    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b0;   
                                            end
                                6'd6    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b0;   
                                            end
                                6'd7    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b0;   
                                            end
                                6'd8    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b0;   
                                            end
                                6'd9    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b0;   
                                            end
                                6'd10    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b0;   
                                            end
                                6'd11    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd12    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd13    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd14    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd15    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd16    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd17    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd18    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd19    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd20    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd21    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd22    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd23    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd24    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd25    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd26    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd27    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd28    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd29    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd30    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd31    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd32    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd33    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd34    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;   
                                            end
                                6'd35    :    begin
                                                iic_scl         <= 1'b1;
                                                sda_dir         <= 1'b1;
                                                iic_sda_out    <= 1'b1;
                                                dri_clk_cnt    <= 6'd0;//
                                                iic_done        <= 1'b1;
                                                state_done7 <= 1'b1;//128   
                                            end
                                        default : ;
                             endcase
                          end
        endcase
    end
end
endmodule


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

31

主题

2183

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
14253
金钱
14253
注册时间
2018-8-3
在线时间
1146 小时
发表于 2019-11-7 12:38:49 | 显示全部楼层
谢谢分享 不过你可以打包成压缩包 发上来哦 这样别人下载下来 更方便看呢
回复 支持 1 反对 0

使用道具 举报

4

主题

231

帖子

0

精华

高级会员

Rank: 4

积分
755
金钱
755
注册时间
2018-12-7
在线时间
131 小时
发表于 2019-11-7 12:26:36 | 显示全部楼层
帮顶 很棒
回复 支持 反对

使用道具 举报

24

主题

57

帖子

0

精华

高级会员

Rank: 4

积分
800
金钱
800
注册时间
2016-11-25
在线时间
93 小时
 楼主| 发表于 2019-11-7 17:54:44 | 显示全部楼层
这是quartus ii工程文件。

I2C_Driver.rar

5.66 MB, 下载次数: 47

工程文件

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-10-3 07:23

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表