欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > 56.基于IIC协议的EEPROM驱动控制(3)跨时钟域处理

56.基于IIC协议的EEPROM驱动控制(3)跨时钟域处理

2024/10/24 3:23:30 来源:https://blog.csdn.net/2301_80417284/article/details/140855818  浏览:    关键词:56.基于IIC协议的EEPROM驱动控制(3)跨时钟域处理

        (1)跨时钟域处理:在使用低频时钟去采集高频信号时,会出现采集不正确的现象,因此需要进行跨时钟域处理。

        多比特信号的跨时钟域处理可以使用FIFO、RAM等IP核进行处理;

        单比特信号低频到高频可以使用打拍的方式进行处理;

        将高频脉冲信号跨时钟到低频域时,中间有效信号变量持续时间需要大于两倍的低频信号周期。

        在IIC_rw_data模块中,经过按键消抖模块处理后的key_rd和key_wr信号是只会在高频系统时钟域下保持一个时钟周期高电平的脉冲信号,因此需要经过上述跨时钟域处理后,才能同步到IIC_clk时钟域下。

  • 高频信号跨时钟域到低频示意图:

        (2)查阅M24C64硬件手册,可以得知字节时间间隔为5ms,因此,需要保证开始写入信号和下一个开始写入信号之间需要存在5000us的时间间隔,而IIC_clk为1MHz,周期为1us,可以设置一个计数5000的计数器。

        (3)IIC_rw_data模块代码:

module IIC_rw_data(input   wire                clk         ,input   wire                reset_n     ,input   wire                key_rd      ,input   wire                key_wr      ,input   wire                IIC_clk     ,input   wire                IIC_end     ,input   wire    [7:0]       rd_data     ,output  wire    [7:0]       fifo_rd_data,output  reg                 IIC_start   ,output  reg                 wr_en       ,output  reg                 rd_en       ,output  reg     [15:0]      byte_addr   ,output  reg     [7:0]       wr_data     );wire                 fifo_wr_en      ;reg                  fifo_rd_en      ;wire     [6:0]       fifo_data_count ;reg      [7:0]       cnt_wr          ;reg      [7:0]       cnt_rd          ;reg                  write_vaild     ;reg                  read_vaild      ;reg      [15:0]      cnt_start       ;reg      [7:0]       wr_data_num     ;reg      [7:0]       rd_data_num     ;reg                  fifo_rd_vaild   ;reg      [19:0]      cnt_wait        ;reg      [7:0]       fifo_rd_num     ;parameter            CNT_VAILD           =   8'd200      ;parameter            CNT_START_MAX       =   16'd5000    ;parameter            SET_NUM             =   8'd20       ;parameter            CNT_WAIT_MAX        =   20'd500_000 ;/*------------fifo设置--------------*/
myfifo myfifo_inst 
(.clk          (IIC_clk        ),              // input wire clk.din          (rd_data        ),              // input wire [7 : 0] din.wr_en        (fifo_wr_en     ),              // input wire wr_en.rd_en        (fifo_rd_en     ),              // input wire rd_en.dout         (fifo_rd_data   ),              // output wire [7 : 0] dout.full         (               ),              // output wire full.empty        (               ),              // output wire empty.data_count   (fifo_data_count)               // output wire [6 : 0] data_count);assign fifo_wr_en = IIC_end && rd_en;/*-----------cnt_wr 、 cnt_rd设置-----------*/
always@(posedge clk or negedge reset_n)if(!reset_n)cnt_wr <= 8'd0;else if(write_vaild == 1'd0)cnt_wr <= 8'd0;else cnt_wr <= cnt_wr + 8'd1;always@(posedge clk or negedge reset_n)if(!reset_n)cnt_rd <= 8'd0;else if(read_vaild == 1'd0)cnt_rd <= 8'd0;else cnt_rd <= cnt_rd + 8'd1;/*-----------wr_en 、wr_data_num设置-----------*/   
always@(posedge IIC_clk or negedge reset_n)if(!reset_n)wr_en <= 1'd0;else if((wr_data_num == SET_NUM - 1'd1) && (IIC_end == 1'd1) && (wr_en == 1'd1))wr_en <= 1'd0;else if(write_vaild)wr_en <= 1'd1;else wr_en <= wr_en;always@(posedge IIC_clk or negedge reset_n)if(!reset_n)wr_data_num <= 8'd0;else if(wr_en == 1'd0)wr_data_num <= 8'd0;else if((wr_en == 1'd1) && (IIC_end == 1'd1))wr_data_num <= wr_data_num + 8'd1;else wr_data_num <= wr_data_num;/*-----------write_vaild 、 read_vaild设置-----------*/
always@(posedge clk or negedge reset_n)if(!reset_n)write_vaild <= 1'd0;else if(cnt_wr == CNT_VAILD - 1'd1)write_vaild <= 1'd0;else if(key_wr)write_vaild <= 1'd1;else write_vaild <= write_vaild;always@(posedge clk or negedge reset_n)if(!reset_n)read_vaild <= 1'd0;else if(cnt_rd == CNT_VAILD - 1'd1)read_vaild <= 1'd0;else if(key_rd)read_vaild <= 1'd1;else read_vaild <= read_vaild;/*-----------rd_en 、rd_data_num设置-----------*/   
always@(posedge IIC_clk or negedge reset_n)if(!reset_n)rd_en <= 1'd0;else if((rd_data_num == SET_NUM - 1'd1) && (IIC_end == 1'd1) && (rd_en == 1'd1))rd_en <= 1'd0;else if(read_vaild)rd_en <= 1'd1;else rd_en <= rd_en;always@(posedge IIC_clk or negedge reset_n)if(!reset_n)rd_data_num <= 8'd0;else if(rd_en == 1'd0)rd_data_num <= 8'd0;else if((rd_en == 1'd1) && (IIC_end == 1'd1))rd_data_num <= rd_data_num + 8'd1;else rd_data_num <= rd_data_num;/*-----------cnt_start 、IIC_start设置-----------*/        
//查阅芯片数据手册可知,M24C64芯片每次读写操作之间的时间间隔最少为5ms,即5000个IIC_clk时钟周期。
always@(posedge IIC_clk or negedge reset_n)if(!reset_n)cnt_start <= 16'd0;else if((wr_en == 1'd0) && (rd_en == 1'd0))cnt_start <= 16'd0;else if(cnt_start == CNT_START_MAX - 1'd1)cnt_start <= 16'd0;else cnt_start <= cnt_start + 16'd1;always@(posedge IIC_clk or negedge reset_n)if(!reset_n)IIC_start <= 1'd0;else if(cnt_start == CNT_START_MAX - 1'd1)IIC_start <= 1'd1;else IIC_start <= 1'd0;/*-----------byte_addr读写地址设置-----------*/   
always@(posedge IIC_clk or negedge reset_n)if(!reset_n)byte_addr <= 16'h005A;else if((wr_en == 1'd0) && (rd_en == 1'd0))byte_addr <= 16'h005A;else if((wr_en == 1'd1) || (rd_en == 1'd1)&& (IIC_end == 1'd1))byte_addr <= byte_addr + 16'h0001;else byte_addr <= byte_addr;/*----------------wr_data设置--------------*/ 
always@(posedge IIC_clk or negedge reset_n)if(!reset_n)  wr_data <= 8'd10;else if(wr_en == 1'd0)wr_data <= 8'd10;else if((wr_en == 1'd1) && (IIC_end == 1'd1))wr_data <= wr_data + 8'd1;else wr_data <= wr_data  ;/*-----------fifo_rd_vaild 、 cnt_wait 、 fifo_rd_en 、fifo_rd_num设置-----------*/   
always@(posedge IIC_clk or negedge reset_n)if(!reset_n)fifo_rd_vaild <= 1'd0;else if((fifo_rd_num == SET_NUM) && (cnt_wait == CNT_WAIT_MAX - 1'd1))fifo_rd_vaild <= 1'd0;else if(fifo_data_count == SET_NUM)fifo_rd_vaild <= 1'd1;elsefifo_rd_vaild <= fifo_rd_vaild;always@(posedge IIC_clk or negedge reset_n)if(!reset_n)cnt_wait <= 20'd0;else if(fifo_rd_vaild == 1'd0)cnt_wait <= 20'd0;else if(cnt_wait == CNT_WAIT_MAX - 1'd1)cnt_wait <= 20'd0;else cnt_wait <= cnt_wait + 20'd1;always@(posedge IIC_clk or negedge reset_n)if(!reset_n)fifo_rd_en <= 1'd0;else if((fifo_rd_num < SET_NUM) && (cnt_wait == CNT_WAIT_MAX - 1'd1))fifo_rd_en <= 1'd1;else fifo_rd_en <= 1'd0;always@(posedge IIC_clk or negedge reset_n)if(!reset_n)fifo_rd_num <= 1'd0;else if(fifo_rd_vaild == 1'd0)fifo_rd_num <= 1'd0;else if(fifo_rd_en)fifo_rd_num <= fifo_rd_num + 1'd1;else fifo_rd_num <= fifo_rd_num;endmodule

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com