孩子都能学会的FPGA:第二十四课——用FPGA和格雷码实现异步FIFO

news2024/9/19 10:47:29

(原创声明:该文是作者的原创,面向对象是FPGA入门者,后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门作者不光让大家知其然,还要让大家知其所以然!每个工程作者都搭建了全自动化的仿真环境,只需要双击top_tb.bat文件就可以完成整个的仿真(前提是安装了modelsim),降低了初学者的门槛。如需整个工程请留言(WX:Blue23Light),不收任何费用,但是仅供参考,不建议大家获得资料后从事一些商业活动!

上节课格雷码的编码,格雷码适用于连续变化的信号,比如递增和递减,这样一次只有一位信号反转变化,在跨时钟域同步时减低了同步的难度。

下面我们考虑一下格雷码应用的场景,在异步RAM中,读数据和写数据可以是不同的时钟域,读写地址信号都是连续变化的,有时候写时钟域要知道读时钟域的地址,以判断RAM是不是要写满了;有时候读时钟域要知道写时钟域的地址,以判断RAM是不是要被读空了;上述的情况下都需要两个不同时钟域的地址信号进行同步,用格雷码是最好的选择。

我们来看一下异步RAM的接口,主要有读写时钟信号,读写使能信号,读写地址信号,读写数据信号。

再看看异步FIFO的接口,主要有读写时钟信号,读写使能信号,读写数据信号,还有就是标志信号fullempty,表示FIFO是满还是空。从信号上来说FIFO的信号要比RAM的信号少,主要是少了读写地址信号,所以控制相对也简单很多。对异步FIFO的控制,在FIFO非满的情况下(full未拉高)就可以写入新的数据;在FIFO非空的情况下(empty未拉高)就可以读出新的数据。所异步FIFO就是在异步RAM的基础上,通过读写地址信号产生空满信号。下面我们就在异步RAM的基础上来实现异步FIFO

如下是异步RAM实现异步FIFO的框图,思路很简单,写地址信号格雷码编码后由写时钟域同步到读时钟域,然后格雷码解码,和读地址信号产生空EMPTY信号;读地址信号格雷码编码后由读时钟域同步到写时钟域,然后格雷码解码,和写地址信号产生满FULL信号。当然也可以设定来产生快满(nearly_full),快空(nearly_empty)信号,FPGA程序里面有涉及。

下面用FPGA来实现异步FIFO。接口信号如下所示,和异步FIFO接口信号一致。设置了两个参数,lower_threshold来指示FIFO内的数据的下限值,当FIFO内的数据少于这个值几乎空nearly_empty信号就会拉高,upper_threshold来指示FIFO内的数据的上限值,当FIFO内的数据多于这个值几乎满nearly_full信号就会拉高。

当有新的数据要写入RAM,产生写使能wr_enable,写数据dina和写地址addra信号,保证数据可以写入RAM。

写地址信号格雷码编码,读时钟域clk_rd的读地址信号格雷码编码后同步到写时钟域clk_wr,采用3级打拍的方式进行同步,然后对同步后的读地址信号进行格雷码解码,最后将写地址信号和同步解码后的读地址信号相减,根据差值wr_occupancy来判断RAM是快写满了nearly_full还是已经写满了FULL。

同理在读时钟域clk_rd产生读使能信号rd_enable,读地址信号addrb,并将读地址信号进行格雷码编码。写时钟域clk_wr的写地址信号格雷码编码后同步到读时钟域clk_rd,采用3级打拍的方式进行同步。

然后对同步后的写地址信号进行格雷码解码,最后将同步后的写地址信号和读地址信号相减,根据差值rd_occupancy来判断RAM是快读空了nearly_empty还是已经读空了EMPTY最后是例化异步RAM,RAM的读数据和使能输出即可。

在仿真文件中产生递增数,按照FIFO的常规操作进行控制,非满就写,非空就读,如下所示。

双击sim目录下的top_tb.bat文件,如下所示。

首先看一下写时钟快于读时钟的仿真波形。由于写时钟快于读时钟,RAM很快就会写满了,后续是RAM被读一个数据才能写入一个数据,仿真结果和分析一致。

再看一下写时钟慢于读时钟的仿真,由于写时钟满于读时钟,RAM很快就会读空了,后续是RAM写入一个数据才能被读出一个数据,仿真结果和分析一致。大家如果感兴趣可以好好的看看仿真的波形。

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

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

相关文章

加载离线镜像包:在线镜像离线为tar包、tar离线镜像包加载并根据imageId打tag

第一步:在线环境压缩离线镜像: 需要两个文件,第一个是脚本文件image_offline_load.sh脚本,第二个是image_list.txt 按行 存放需要离线的镜像名称 ./image_offline_load.sh save image_list.txt output.tar第二步:在离…

Nginx 简单入门操作

前言:之前的文章有些过就不罗嗦了。 Nginx 基础内容 是什么? Nginx 是一个轻量级的 HTTP 服务器,采用事件驱动、异步非阻塞处理方式的服务器,它具有极好的 IO 性能,常用于 HTTP服务器(包含动静分离)、正向代理、反向代理、负载均衡 等等. Nginx 和 Node.js 在很多方…

Docker快速理解及简介

docker快速理解及简介 1.Docker为什么出现? 迁移一个项目时,运行文档、配置环境、运行环境、运行依赖包、操作系统发行版、内核等都需要重新安装配置,比较麻烦。 2.Docker是什么? Docker是基于Go语言实现的云开源项目。解决了运行…

Altium Designer实用系列(五)----整理并导出PCB的BOM表

一、引言 最近老师安排了一个小的任务,就是把我们项目的两个电路板BOM整合一下,要注明元器件的耐温、耐压、购买渠道等等内容。    一开始我觉得这工作内容太简单了,两分钟的事。但是当我实际开始干的时候,才发现,好…

【react】动态页面转换成html文件下载,解决样式问题

需求 今天遇到一个需求,挺恶心人的,将一个在线文档页面,可以导出成为html页面查看。 看到网上有使用fs模块,通过react的ReactDOMServer.renderToStaticMarkup将组件转成html字符串,输出文件了。 但是我尝试了&#x…

CodeSys学习笔记

文章目录 1.运动控制的两种方式1.1.SM3_CNC1.2.SM3_Robotics 2.两种运动控制方式的速度、加速度等参数的控制2.1.SM3_CNC2.2.SM3_Robotics 3.CNC的M指令的使用(实现)逻辑。4.SM3_Robotics中的坐标系5.SM3_Robotics如何实现插补并连续执行? 记…

【Linux】diff命令使用

diff命令 是一个用于比较两个文件或目录之间差异的命令。它可以显示两个文件之间的行级别差异,并以易于阅读的格式输出结果。 著者 由保罗艾格特、迈克海特尔、大卫海耶斯、理查德史泰尔曼和Len Tower撰写。 diff命令 -Linux手册页 语法 diff [选项] [文件1]…

设备间的指令通信

指令通信的概念 要进行设备和设备之间的交流就需要通过串口发送数据进行交流 而串口发送简单的数据只需要传输介质 但是要发送复杂的数据就需要介质和传输的规则了 三种应用场景 比如在上位机和mcu之间 通过上位机管理控制器 从而控制电池 单片机和单片机之间 用户输入数据到…

MySQl int(1)、int(20) 的区别到底在哪里

MySQl int(1)、int(20) 的区别到底在哪里 常思一二,便得自然… int(1)数据类型介绍 在MySQL中,INT(1) 是一种定义整数类型的数据字段,其中的数字表示显示宽度而不是存储范围。具体说,INT(1) 中的数字 1 表示显示宽度&#xff0…

VividTalk创新AI语音匹配图片技术:照片+语音=逼真说话视频!

VividTalk是一个由南京大学、阿里巴巴、字节跳动和南开大学共同开发的项目工具。它通过先进的音频到3D网格映射技术和网格到视频的转换技术,实现了高质量、逼真的音频驱动的说话头像视频生成。这一创新技术使得只需提供一张人物的静态照片和一段语音录音&#xff0c…

KeePass开源密码管理器

KeePass开源密码管理器 KeePass 是一款免费的开源密码管理器,KeePass 将密码存储为一个数据库,而这个数据库由一个主密码或密码文件锁住,也就是说我们只需要记住一个主密码,或使用一个密码文件,就可以解开这个数据库&a…

JavaSE基础50题:8. 获取一个数二进制序列中所有的偶数和奇数位,分别输出二进制序列。

概述 获取一个数二进制序列中所有的偶数和奇数位,分别输出二进制序列。 如:从右往左数 0111(如图) 偶数位:01 奇数位:11 代码 public static void main(String[] args) {Scanner scanner new Scanner(Sys…

动态规划学习——最长回文子序列,让字符串变成回文串的最小插入次数

一,最长回文串 1.题目 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 示例 1: 输入&…

Dockerfile详解#如何编写自己的Dockerfile

文章目录 前言编写规则指令详解FROM:基础镜像LABEL:镜像描述信息MAINTAINER:添加作者信息COPY:从宿主机复制文件到镜像中ADD:从宿主机复制文件到镜像中WORKDIR:设置工作目录 前言 Dockerfile是编写docker镜…

#HarmonyOS:装饰器UI描述---@Link

装饰器 装饰器(Decorator)是一种语法结构,用来在定义时修改类(class)的行为。 在语法上,装饰器有如下几个特征。 第一个是字符(或者说前缀)是,后面是一个表达式后面的…

机器学习算法(7)-朴素贝叶斯算法和K最近邻算法

一、说明 在在这篇文章中,我将解释两种机器学习算法,称为贝叶斯定理和 K 最近邻算法。贝叶斯定理以 18 世纪英国数学家托马斯贝叶斯的名字命名,是确定条件概率的数学公式。k 最近邻算法,也称为 KNN 或 k-NN,是一种非参…

Python基础知识-变量、数据类型(整型、浮点型、字符类型、布尔类型)详解

1、基本的输出和计算表达式: prinit(12-3) printf(12*3) printf(12/3) prinit(12-3) printf(12*3) printf(12/3) 形如12-3称为表达式 这个表达式的运算结果称为 表达式的返回值 1 2 3 这样的数字,叫做 字面值常量 - * /称为 运算符或者操作符 在C和j…

k8s中的Pod网络;Service网络;网络插件Calico

Pod网络;Service网络;网络插件Calico Pod网络 在K8S集群里,多个节点上的Pod相互通信,要通过网络插件来完成,比如Calico网络插件。 使用kubeadm初始化K8S集群时,有指定一个参数–pod-network-cidr10.18.0…

再识二叉树

1. 二叉树的存储 二叉树的存储结构分为:顺序存储和类似于链表的链式存储。 其中二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有二叉和三叉表示方式(这里本主主要讲的是链式存储),具体代码如下&…

2个月拿下信息系统项目管理师攻略(攻略超级全)

信息系统项目管理师(高项)一次性过啦!结合这次备考经验,给大家总结一下复习方法。 先上图,开心一下! 一、我为什么选择了高项 为什么我会选信息系统项目管理师,也就是我们常说的高项。 原因1…