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

news2024/11/14 13:41:10

        (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;
    else
        fifo_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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2082341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GitLab私有代码仓库搭建与使用

文章目录 一、安装GitLab1、下载安装2、修改配置3、启动gitlab4、登录 二、使用1、ssh-key 参考资料 一、安装GitLab 1、下载安装 gitlab-ce的rpm包清华源地址&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/?CN&OD 本次使用gitlab-ce-17.1.1-c…

近500个自然助眠冥想白噪音ACCESS\EXCEL数据包

今天这份数据是从一款特别简单好用助眠辅助应用软件中提取出来的MP3数据包&#xff0c;包含很多纯净音乐、助眠音乐、冥想音乐&#xff0c;可以帮助用户轻松进行多种白噪音音乐播放&#xff0c;帮助用户更好进行压力释放&#xff0c;感受更多舒适身心纯音乐体验。分类非常多&am…

【Java】数据类型与变量(一)

目录 1.字面常量 1.1什么是常量 1.2字面常量的分类: 2.数据类型 2.1基本数据类型 2.2一个小问题&#xff1a;什么是字节&#xff1f; 1.字面常量 1.1什么是常量 在一篇文章HelloWorld程序中&#xff0c;System.Out.println("Hello World");语句,不论程序何时运…

上网行为管理是什么?上网行为管理系统分享(六款上网行为管理系统介绍)2024年必备!

早期的上网行为管理系统&#xff0c;主要是对一些网站进行拦截&#xff0c;但企业数据泄露的现象仍旧普遍&#xff0c;敌人不止黑客。在激烈的商业竞争中&#xff0c;面对利益的诱惑&#xff0c;掌握着公司重要数据的员工也是不可控的危险因素。 本文将深入探讨上网行为管理的概…

2008-2024年荣威汽车维修手册和电路图线路图接线图资料更新

经过整理&#xff0c;2009-2024年名爵汽车全系列已经更新至汽修帮手资料库内&#xff0c;覆盖市面上99%车型&#xff0c;包括维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针脚定义、模块传感器、保险丝盒图解对照表…

程序员阿龙【精选】计算机毕业设计之:基于java房屋租赁网站管理系统

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

【Datawhale X 李宏毅苹果书 AI夏令营】Task2笔记

第三章&#xff1a;深度学习基础 本章前部分的内容见&#xff1a;【Datawhale X 李宏毅苹果书 AI夏令营】Task1笔记-CSDN博客 3.6 分类 分类与回归的关系 假设三个类本身没有特定的关系&#xff0c;类 1 是 1&#xff0c;类 2 是 2 类 3 是 3。这种情况需要引入独热&#xff…

kubernetes培训

基本概念 Node 节点可以是物理机或虚拟机&#xff0c;每个节点上都运行着容器运行时环境&#xff1b; Pod Pod是k8s中的最小调度单元&#xff0c;一个Pod可以包含一个或多个容器&#xff0c;同一Pod内的容器共享存储卷和网络空间。容器则是轻量级、可移植的执行单元&#xf…

四、LogicFlow 自定义左侧菜单Menu

目录 前文LogicFlow 介绍实现基础界面框架实现左侧菜单组件将左侧菜单引入到demo组件中最后 前文 这篇相对来讲就稍微平凡了一点&#xff0c;只要有前端的一些基础就能够轻松完成上图中左侧的菜单&#xff0c;但是为了能够让前后文章能够连贯起来&#xff0c;所以还是要厚着脸…

一文彻底搞懂ZooKeeper选举机制

原文阅读&#xff1a;【巨人肩膀社区博客分享】一文彻底搞懂ZooKeeper选举机制 1. ZooKeeper 集群 ZooKeeper 是一个高性能分布式的开源协调服务&#xff0c;用于构建分布式应用程序和服务。 一个 ZooKeeper 集群通常由多个 ZooKeeper 服务器组成&#xff0c;这些服务器分布在…

C语言基础(二十三)

在C语言中&#xff0c;修改链表中的数据涉及遍历链表以找到要修改的元素&#xff0c;然后更新该元素的值。链表是一种动态数据结构&#xff0c;它由一系列节点组成&#xff0c;每个节点包含数据部分和指向列表中下一个节点的指针&#xff08;双向链表&#xff0c;还会有指向前一…

<Rust>egui学习之小部件(四):如何在窗口中添加滑动条部件?

前言 本专栏是关于Rust的GUI库egui的部件讲解及应用实例分析&#xff0c;主要讲解egui的源代码、部件属性、如何应用。 环境配置 系统&#xff1a;windows 平台&#xff1a;visual studio code 语言&#xff1a;rust 库&#xff1a;egui、eframe 概述 本文是本专栏的第四篇博…

Ubuntu 24.04 安装 intel 编译器

目录 1.采用用户界面 GUI 安装英特尔基本工具包 Intel oneAPI Base Toolkit 1.1 下载离线英特尔基本工具包 1.2 安装英特尔基本工具包 1.3 英特尔基本工具包 Intel oneAPI Base Toolkit 环境设置 2.安装英特尔基本工具包 Intel HPC Toolkit 2.1 下载离线英特尔高性能计算…

智能座舱高通8155摄像头方案

高通汽车开发平台 &#xff08;ADP&#xff09;基于8155的多媒体硬件框图如下所示&#xff1a;有4个4路CSI摄像头处理通路&#xff0c;2个4路DSI屏幕处理通路&#xff0c;1个DisplayPort。 基于摄像头的详细方案如下&#xff1a;可以处理4路MAX9296解串后信号。 再深入细化基于…

Java10 集合

集合 集合集合接口等级&#xff1a;Collection&#xff1a;单例集合接口,将数据一个一个存储&#xff0c;存储的是值。ArrayList类&#xff1a;泛型集合Linkedlist集合&#xff1a;Vector集合&#xff1a;Stack集合&#xff1a;Vetor的子类 Set接口&#xff1a;存储是无序的&am…

【使用 Python 进行截图的两种方法】

在 Python 中&#xff0c;可以使用 pyautogui 和 Pillow 进行截图 使用 pyautogui 进行截图时&#xff0c;其提供了方便的函数。例如&#xff0c;使用 pyautogui.screenshot() 函数可以获取整个屏幕的截图&#xff0c;该函数返回一个包含屏幕截图的图像对象。如果不想截取整个…

最大噪音值甚至受法规限制,如何基于LBM算法有效控制风扇气动噪音

风扇的气动噪声 在工业设备行业&#xff0c;最大噪音值受法规限制。在很多使用风扇冷却的设备上&#xff0c;风扇噪声通常是这些设备工作噪声的最大贡献量。而在家电民用行业&#xff0c;例如空调、空气净化器、油烟机等&#xff0c;其噪音大小直接关系到用户的体验感受&#x…

从零开始掌握容器技术:Docker的奇妙世界

容器技术在当今的云计算和软件开发领域中扮演着越来越重要的角色。如果你是一名计算机专业的学生或从事IT行业的从业者&#xff0c;可能已经听说过Docker这个词。它在软件开发、部署、运维等环节中大放异彩&#xff0c;但对于刚接触这个概念的朋友来说&#xff0c;可能还是有些…

【乐企】有关乐企能力测试接口对接(详细)

1、申请密钥 2、验证本地服务器与乐企服务器的连通性 乐企服务器生产和测试域名均为&#xff1a;https://lqpt.chinatax.gov.cn:8443。开发者可以在“能力中心”查看基础公用能力详情&#xff0c;按照能力接入和开发指引完成接口对接&#xff0c;验证服务器连通性和证书配置正确…

给一个web网站,如何开展测试?

前言 Web测试是指针对Web应用程序(网站或基于Web的系统)进行的测试活动&#xff0c;以确保其质量、性能、安全性、可用性和兼容性等方面符合预期标准。Web测试涵盖了从前端用户界面(UI)到后端逻辑和数据库的各个方面&#xff0c;确保Web应用程序在不同环境和条件下都能正常运行…