EEPROM(基于IIC协议)

IIC

由两根线组成,I2C_SCL是串行时钟线,I2C_SDA是串行数据线,一般采用开漏模式于总线项链,所以需接上上拉电阻。

整体时序

1.空闲模式

I2C_SDA和I2C_SCL由于上拉的原因,处于高电平状态

2.起始信号

I2C_SCL为高电平时将 I2C_SDA 线拉低,产生一个起始信号

3.数据传输状态
4.停止信号

I2C_SCL 为高电平时,I2C_ SDA 从低电平跳变到高电平

IIC读写时序

单次写

连续写

连续写和单次写的区别在于在发送完一个地址位的时候发送几个数据

随机读

(写还分为读当前地,连续读当前地址,连续读随机地址,但使用这些方式会导致代码适应范围少)

IIC读写实验

顶层文件

module top_e2prom(
    input               sys_clk    ,      //系统时钟
    input               sys_rst_n  ,      //系统复位
    //eeprom interface
    output              iic_scl    ,      //eeprom的时钟线scl
    inout               iic_sda    ,      //eeprom的数据线sda
);
//e2prom读写测试模块
e2prom_rw #(
    .MAX_BYTE    (MAX_BYTE  )   //读写测试的字节个数
) u_e2prom_rw(
    .clk         (dri_clk   ),  //时钟信号
    .rst_n       (sys_rst_n ),  //复位信号
    //i2c interface
    .i2c_exec    (i2c_exec  ),  //I2C触发执行信号
    .i2c_rh_wl   (i2c_rh_wl ),  //I2C读写控制信号
    .i2c_addr    (i2c_addr  ),  //I2C器件内地址
    .i2c_data_w  (i2c_data_w),  //I2C要写的数据
    .i2c_data_r  (i2c_data_r),  //I2C读出的数据
    .i2c_done    (i2c_done  ),  //I2C一次操作完成
    .i2c_ack     (i2c_ack   ),  //I2C应答标志 
    //user interface
    .rw_done     (rw_done   ),  //E2PROM读写测试完成
    .rw_result   (rw_result )   //E2PROM读写测试结果 0:失败 1:成功
);
​
//i2c驱动模块
i2c_dri #(
    .SLAVE_ADDR  (SLAVE_ADDR),  //EEPROM从机地址
    .CLK_FREQ    (CLK_FREQ  ),  //模块输入的时钟频率
    .I2C_FREQ    (I2C_FREQ  )   //IIC_SCL的时钟频率
) u_i2c_dri(
    .clk         (sys_clk   ),  
    .rst_n       (sys_rst_n ),  
    //i2c interface
    .i2c_exec    (i2c_exec  ),  //I2C触发执行信号
    .bit_ctrl    (BIT_CTRL  ),  //器件地址位控制(16b/8b)
    .i2c_rh_wl   (i2c_rh_wl ),  //I2C读写控制信号
    .i2c_addr    (i2c_addr  ),  //I2C器件内地址
    .i2c_data_w  (i2c_data_w),  //I2C要写的数据
    .i2c_data_r  (i2c_data_r),  //I2C读出的数据
    .i2c_done    (i2c_done  ),  //I2C一次操作完成
    .i2c_ack     (i2c_ack   ),  //I2C应答标志
    .scl         (iic_scl   ),  //I2C的SCL时钟信号
    .sda         (iic_sda   ),  //I2C的SDA信号
    //user interface
    .dri_clk     (dri_clk   )   //I2C操作时钟
);

IIC驱动模块

(最重要的模块)

module i2c_dri
    #(
      parameter   SLAVE_ADDR = 7'b1010000   ,  //EEPROM从机地址
      parameter   CLK_FREQ   = 26'd50_000_000, //模块输入的时钟频率
      parameter   I2C_FREQ   = 18'd250_000     //IIC_SCL的时钟频率
    )
   (                                                            
    input                clk        ,    
    input                rst_n      ,   
                                         
    //i2c interface                      
    input                i2c_exec   ,  //I2C触发执行信号
    input                bit_ctrl   ,  //字地址位控制(16b/8b)
    input                i2c_rh_wl  ,  //I2C读写控制信号
    input        [15:0]  i2c_addr   ,  //I2C器件内地址
    input        [ 7:0]  i2c_data_w ,  //I2C要写的数据
    output  reg  [ 7:0]  i2c_data_r ,  //I2C读出的数据
    output  reg          i2c_done   ,  //I2C一次操作完成
    output  reg          i2c_ack    ,  //I2C应答标志 0:应答 1:未应答
    output  reg          scl        ,  //I2C的SCL时钟信号
    inout                sda        ,  //I2C的SDA信号
                                       
    //user interface                   
    output  reg          dri_clk       //驱动I2C操作的驱动时钟
     );
   
E2PROM读写测试
module e2prom_rw(
    input                 clk        , //时钟信号
    input                 rst_n      , //复位信号
​
    //i2c interface
    output   reg          i2c_rh_wl  , //I2C读写控制信号
    output   reg          i2c_exec   , //I2C触发执行信号
    output   reg  [15:0]  i2c_addr   , //I2C器件内地址
    output   reg  [ 7:0]  i2c_data_w , //I2C要写的数据
    input         [ 7:0]  i2c_data_r , //I2C读出的数据
    input                 i2c_done   , //I2C一次操作完成
    input                 i2c_ack    , //I2C应答标志
);
移植代码介绍:

读写一体化的组合逻辑时序,通过控制st_data_wr和st_addr_rd信号来操控是需要都还是写

st_idle: begin                          //空闲状态
           if(i2c_exec) begin
               next_state = st_sladdr;
           end
           else
               next_state = st_idle;
        end
        st_sladdr: begin
            if(st_done) begin
                if(bit_ctrl)                    //判断是16位还是8位字地址
                   next_state = st_addr16;
                else
                   next_state = st_addr8 ;
            end
            else
                next_state = st_sladdr;
        end
        st_addr16: begin                        //写16位字地址
            if(st_done) begin
                next_state = st_addr8;
            end
            else begin
                next_state = st_addr16;
            end
        end
        st_addr8: begin                         //8位字地址
            if(st_done) begin
                if(wr_flag==1'b0)               //读写判断
                    next_state = st_data_wr;
                else
                    next_state = st_addr_rd;
            end
            else begin
                next_state = st_addr8;
            end
        end
        st_data_wr: begin                       //写数据(8 bit)
            if(st_done)
                next_state = st_stop;
            else
                next_state = st_data_wr;
        end
        st_addr_rd: begin                       //写地址以进行读数据
            if(st_done) begin
                next_state = st_data_rd;
            end
            else begin
                next_state = st_addr_rd;
            end
        end
        st_data_rd: begin                       //读取数据(8 bit)
            if(st_done)
                next_state = st_stop;
            else
                next_state = st_data_rd;
        end
        st_stop: begin                          //结束I2C操作
            if(st_done)
                next_state = st_idle;
            else
                next_state = st_stop ;
        end

通过写两个个.v文件来传递要读数据的地址和数据和要写的数据地址

再通过一个.v文件来控制是还是写

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值