基于Robei EDA实现FIFO(非IP核)及FIFO求和

一、FIFO简介

        FIFO( First in First out) 使用在需要产生数据接口的部分,用来存储、缓冲在两个异步
时钟之间的数据传输
。在异步电路中,由于时钟之间周期和相位完全独立,因此数据丢失概
率不为零。使用 FIFO 可以在两个不同时钟域系统之间快速而方便地传输实时数据。

在此给自己挖个坑:是否以后会遇到FIFO解决不同时钟域用来同步信号


注:上图为异步FIFO

        如果是一个单端口的存储器,还应包含一个仲裁器,保证同一时刻只能进行一项操作(读或写),我们选择双口 RAM(无需真正的双口 RAM,因为我们只是希望有一个简单的相互独立的读写端口)是因为这些实例非常接近实际情况。读、写端口拥有两个计数器( wr_ptr、 rd_ptr)产生的互相独立的读、写地址。计数器的值在读写使能信号来临时传递给“ 读指针” ( rd)和“ 写指针” ( wr)。写指针指向下一个将要写入的位置,读指针指向下一个将要读取的位置。每次写操作使写指针加 1,读操作使读指针加1。左右两侧的模块为读写指针与满空信号产生模块。这两个模块的任务是给 FIFO 提供“ 空”( empty)和“ 满” ( full)信号。这些信号告诉外部电路 FIFO 已经达到了临界条件:如果出现“ 满” 信号,那么 FIFO 为写操作的临界状态,如果出现“ 空” 信号,则 FIFO 为读操作的临界状态。写操作的临界状态表示 FIFO 已经没有空间来存储更多的数据,读操作的临界表示 FIFO 没有更多的数据可以读出。读写指针与满空信号产生模块还可告诉 FIFO 中“ 满”或“ 空” 位置的数值。这是由指针的算术运算来完成了。实际的“ 满” 或“ 空” 位置计算并不是为 FIFO 自身提供的。它是作为一个报告机构给外部电路用的。但是, “ 满” 和“ 空”信号在 FIFO 中却扮演着非常重要的角色,它为了能实现读与写操作各自的独立运行而阻塞性的管理数据的存取。
这种阻塞性管理的重要性不是将数据复写(或重读),而是指针位置。可以控制整个 FIFO,并且使读、写操作改变着指针数值。
FIFO 的工作原理如下所述:复位时,读、写指针均为 0。这是 FIFO 的空状态,空标志(empty)为高电平,此时满标志( full)为低电平。当 FIFO 出现空标志( empty)时,不允许读操作,只能允许写操作。写操作写入到位置 0,并使写指针加 1。此时,空标志( empty)变为低电平。假设没有发生读操作且随后的一段时间中 FIFO 只有写操作,一定时间后,写指针的值等于 7。这就意味着在存储器中,要写入数据的最后一个位置就是下一个位置。在这种情况下,写操作将写指针变为 0,并将输出满标志( full)。

二、同步FIFO框图设计

端口类型作用
clkinput提供时钟信号
resetinput提供复位信号
data_ininput数据输入
wr_eninput写使能信号
rd_eninput读使能信号
fifo_cntoutput还未读出的数据
data_outouput缓存数据输出
fulloutput“满“信号
emptyoutput”空“信号

三、波形图绘制

四、程序编写

多仿真多改正

fifo.v

module fifo(
	clk,
	reset,
	data_in,
	wr_en,
	rd_en,
	full,
	empty,
	data_out,
	fifo_cnt);

	//---Ports declearation: generated by Robei---
	input clk;
	input reset;
	input [7:0] data_in;
	input wr_en;
	input rd_en;
	output full;
	output empty;
	output [7:0] data_out;
	output [3:0] fifo_cnt;

	wire clk;
	wire reset;
	wire [7:0] data_in;
	wire wr_en;
	wire rd_en;
	wire full;
	wire empty;
	reg [7:0] data_out;
	reg [3:0] fifo_cnt;

	//----Code starts here: integrated by Robei-----
	//fifo存储空间
	reg [7:0]fifo_ram[0:7];
	//rd_ptr和wr_ptr指针
	reg [3:0]rd_ptr,wr_ptr;
	
	/*空和满信号产生*/
	assign empty = (fifo_cnt == 0);//存储0个数据
	assign full = (fifo_cnt == 8); //存储8个数据
	/*写操作*/
	always@(posedge clk or negedge reset)
	if(reset == 0)
		begin
			fifo_ram[0]=8'hff;
			fifo_ram[1]=8'hff;
			fifo_ram[2]=8'hff;
			fifo_ram[3]=8'hff;
			fifo_ram[4]=8'hff;
			fifo_ram[5]=8'hff;
			fifo_ram[6]=8'hff;
			fifo_ram[7]=8'hff;
		end
	else if(wr_en == 1 && (!full))    //写信号并且没有满
		fifo_ram[wr_ptr] <= data_in;//数据写入
	else if(wr_en == 1&&rd_en == 1)			//同时读写,只是指针不移动(后面体现)
		fifo_ram[wr_ptr] <= data_in;
	
	/*读操作*/
	always@(posedge clk)
	if(reset == 0)
		data_out <= 0;
	else if((rd_en == 1) && (empty == 0))
		data_out <= fifo_ram[rd_ptr];
	else if(wr_en== 1&&rd_en == 1)   	//同时读写,只是指针不移动(后面体现)
		data_out <= fifo_ram[rd_ptr];	
	else
		data_out <= data_out;
	/*指针移动--wr_ptr*/
	always@(posedge clk)
	if(reset == 0)
		wr_ptr <= 0;
	else if((wr_en == 1) && (full == 0))
		wr_ptr <= wr_ptr + 1'b1;
	else if((wr_en == 1)&&(rd_en == 1))
		wr_ptr <= wr_ptr + 1'b1;
	else if(full)
		wr_ptr <= 0;
	else
		wr_ptr <= wr_ptr;
		//wr_ptr <= ((wr == 1 && full == 0)||((wr==1)&&(rd==1)))?wr_ptr+1:wr_ptr;
	
	/*指针移动--rd_ptr*/
	always@(posedge clk)
	if(reset == 0)
		rd_ptr <= 0;
	else if((rd_en == 1'b1)&&(wr_en == 1'b1))
		rd_ptr <= rd_ptr + 1'b1;
	else if((rd_en == 1'b1)&&(empty == 0))
		rd_ptr <= rd_ptr + 1'b1;
	else if(empty)
		rd_ptr <= 0;
	else
		rd_ptr <= rd_ptr;
		//rd_ptr <= ((rd_en == 1 && empty == 0)||((wr_en==1)&&(rd_en==1)))?rd_ptr+1:rd_ptr;
	
	/*fifo_cnt */
	always@(posedge clk)
	if(reset == 0)
		fifo_cnt <= 0;
	else
		case({wr_en,rd_en})
			2'b00:fifo_cnt <= fifo_cnt;
			2'b01:fifo_cnt <= (fifo_cnt == 0)?0:fifo_cnt - 1;
			2'b10:fifo_cnt <= (fifo_cnt == 8)?8:fifo_cnt + 1;
			2'b11:fifo_cnt <= fifo_cnt;
			default:fifo_cnt <= fifo_cnt;
		endcase
	
	
endmodule    //fifo

fifo_tb.v 

module fifo_tb();

	reg clk;
	reg reset;
	reg [7:0] data_in;
	reg wr;
	reg rd;
	wire full;
	wire empty;
	wire [7:0] data_out;
	wire [3:0] fifo_cnt;

	//----Code starts here: integrated by Robei-----
	always #2  clk =~clk;				//产生时钟
	initial begin
			clk = 1;
	end
	initial begin
	reset =0;
	wr=0;
	rd=0;
	#1 reset=1;
	#3 wr=1;
	#5 rd=1;
	#5 rd=0;
	#5 wr=0;
	#5 wr=1;
	#10 rd=1;
	#10 rd=0;
	
	#3 wr=1;
	#5 rd=1;
	#5 rd=0;
	#5 wr=0;
	#5 wr=0;
	#10 rd=1;
	#10 rd=0;
	  wr=1;
	#4 wr = 0;
	#14 $finish;
	end
	
	always @(posedge clk or negedge reset )
	begin
	if (reset == 0)
	begin
	data_in<=8'hbc;
	wr<=0;
	rd<=0;
	end
	else
	data_in<=$random;
	end
	initial begin
		$dumpfile ("F:/Robei/Robei_study_fifo/fifo_tb.vcd");
		$dumpvars;
	end
	//---Module instantiation---
	fifo fifo1(
		.clk(clk),
		.reset(reset),
		.data_in(data_in),
		.wr_en(wr),
		.rd_en(rd),
		.full(full),
		.empty(empty),
		.data_out(data_out),
		.fifo_cnt(fifo_cnt));

endmodule    //fifo_tb

仿真波形

写在最后,有任何不对的希望及时指正我的错误,感激不尽!

五、FIFO求和原理和方法

为什么要用FIFO求和?

要完成3行数据的SUM求和,需要调用2个FIFO。

六、FIFO求和系统框图

串口收发模块哦我们之前写过,现在光编写fifo求和顶层模块

还在编写ing

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【ChatIE】论文解读:Zero-Shot Information Extraction via Chatting with ChatGPT

文章目录 介绍ChatIEEntity-Relation Triple Extration (RE)Named Entity Recognition (NER)Event Extraction (EE) 实验结果结论 论文&#xff1a;Zero-Shot Information Extraction via Chatting with ChatGPT 作者&#xff1a;Xiang Wei, Xingyu Cui, Ning Cheng, Xiaobin W…

【电源】POE系统供电原理(二)

转载本博客文章&#xff0c;请注明出处 ​ 上一篇文章中&#xff0c;有提到POE系统工作原理及动态检测机制&#xff0c;下面我们继续介绍受电端PD技术及原理。POE供电系统包含PSE、PD及互联接口部分组成&#xff0c;如下图所示。 图1 POE供电系统 PSE控制器的主要作用&#xff…

无人机基本知识,无人机遥控器功能详解与调试方法

无人机作为一种新兴的飞行器&#xff0c;近年来在各个领域得到了广泛的应用。而无人机遥控器则是控制无人机飞行的重要工具。 无人机遥控器是一种无线设备&#xff0c;通过它来远程控制无人机的飞行。遥控器通常包括一个或多个摇杆&#xff0c;用于控制无人机的各种动作&#x…

FL Studio 21中文破解激活版2024免费下载安装图文教程

FL Studio 21.2.1.3859中文破解激活版是我见过更新迭代最快的宿主软件&#xff0c;没有之一。FL Studio12、FL Studio20、FL Studio21等等。有时甚至我刚刚下载好了最新版本&#xff0c;熟悉了新版本一些好用的操作&#xff0c;Fl Studio就又推出了更新的版本&#xff0c;而且F…

【STM32 CubeMX】串口编程DMA+IDLE中断

文章目录 前言一、为什么要引入IDLE中断二、IDLE中断使用方式2.1 接收的三种情况2.2 函数的使用查询方式中断方式DMA方式分析一个问题 总结 前言 在嵌入式系统中&#xff0c;串口通信是一项关键的任务&#xff0c;而使用DMA&#xff08;直接内存访问&#xff09;结合IDLE中断进…

基于springboot特产销售平台源码和论文

“互联网”的战略实施后&#xff0c;很多行业的信息化水平都有了很大的提升。但是目前很多藏区特产销售信息仍是通过人工管理的方式进行&#xff0c;需要在各个岗位投入大量的人力进行很多重复性工作&#xff0c;使得对人力物力造成诸多浪费&#xff0c;工作效率不高等情况&…

【初始RabbitMQ】工作队列的实现

工作队列 工作队列&#xff08;又称为任务队列&#xff09;的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。 相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进 程将弹出任务并最终执行作业。当有多个工作线程…

电脑屏幕录制工具 Top10 榜单,免费无水印方法集

随着媒体行业的突飞猛进&#xff0c;不同服务之间对有效屏幕录制的竞争日益激烈。这导致市场上出现了质量参差不齐的屏幕录像机。特别是有些录屏器会自动给你录制的视频加上水印&#xff0c;给需要在公共场合使用的人留下不专业的印象。除此之外&#xff0c;它们甚至不能保护您…

【Google Bard】免费生成图像——功能和使用方法详解

Google Bard 关于Bard 图片生成功能打开Bard通过Bard来生成图片Bard Vs Bing Vs Dall-EBard的生成结果Bing的生成结果Dall-E 的生成结果 总结 关于Bard 图片生成功能 Google在2月1日&#xff08;当地时间&#xff09;宣布&#xff0c;其对话型AI“Bard”新增了图像生成功能。 …

Mysql——update更新数据的方式

注&#xff1a;文章参考&#xff1a; MySQL 更新数据 不同条件(批量)更新不同值_update批量更新同一列不同值-CSDN博客文章浏览阅读2w次&#xff0c;点赞20次&#xff0c;收藏70次。一般在更新时会遇到以下场景&#xff1a;1.全部更新&#xff1b;2.根据条件更新字段中的某部分…

MATLAB离线文档安装

MATLAB离线文档安装 来源于最全matlab安装离线文档教程只是对内容进行了精简&#xff0c;同时更方便查找 一、下载离线文档 我上传的2023b离线文档 提供本体属于违规行为&#xff0c;本体下载链接已删除 为方便已安装好软件的朋友想安装离线帮助文档&#xff0c;由于官网下载…

模型 IPO(输入、处理、输出)学习模型

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_总纲目录。重在提升认知。信息转化与传递。 1 模型 IPO(输入、处理、输出)学习模型的应用 1.1 项目管理知识体系 PMBOK 中的IPO应用 在项目管理领域&#xff0c;PMBOK&#xff08;Project Management Body of Know…

究极小白如何自己搭建一个自动发卡网站-独角数卡

本人从来没接触过建站&#xff0c;我之前都是在TB上花90叫别人给我搭建的网站&#xff0c;前几天这个TB店倒闭跑路了&#xff0c;而我的发卡网也打不开了&#xff0c;没办法&#xff0c;逼上梁山&#xff0c;自己捣鼓出来了&#xff01;下面是2023/4/2自己建好的&#xff01; …

STM32F1 - 系统时钟SysTick

SysTick 1> SysTick硬件框图2> SysTick的时钟源3> 1ms定时_中断方式4> 思考&#xff1a;无符号数 0 - 255 ?相关资料 1> SysTick硬件框图 SysTick属于Cotex-M3&#xff0c;是CPU外设&#xff1b; SysTick: 位宽24bit&#xff0c; 递减计数&#xff0c;自动重装…

《Go 简易速速上手小册》第2章:控制结构与函数(2024 最新版)

文章目录 2.1 条件语句&#xff1a;决策的艺术2.1.1 基础知识讲解2.1.2 重点案例&#xff1a;用户角色权限判断实现用户角色权限判断扩展功能实现代码功能扩展&#xff1a;添加或删除用户 2.1.3 拓展案例 1&#xff1a;成绩等级判断实现成绩等级判断功能实现代码扩展功能&#…

【开源图床】使用Typora+PicGo+Github+CDN搭建个人博客图床

准备工作&#xff1a; 首先电脑得提前完成安装如下&#xff1a; 1. nodejs环境(node ,npm):【安装指南】nodejs下载、安装与配置详细教程 2. Picgo:【安装指南】图床神器之Picgo下载、安装与配置详细教程 3. Typora:【安装指南】markdown神器之Typora下载、安装与无限使用详细教…

canal监听binlog记录业务数据的变更;canalAdmin对instance做web配置

概述 平时在开发中会通过logback打印一些开发日志&#xff0c;有时也会需要记录一些业务日志&#xff0c;简单的就直接用log记录一下&#xff0c;但是系统中需要记录日志的地方越来越多时&#xff0c;不能每个地方都写一套log记录&#xff1b; 由于平常用的大多都是mysql&…

Linux进程间通信(三)-----System V消息队列

消息队列的概念及原理 消息队列实际上就是在系统当中创建了一个队列&#xff0c;队列当中的每个成员都是一个数据块&#xff0c;这些数据块都由类型和信息两部分构成&#xff0c;两个互相通信的进程通过某种方式看到同一个消息队列&#xff0c;这两个进程向对方发数据时&#x…

【C++ QT项目2】——高仿安信可串口调试助手

【C QT项目2】——高仿安信可串口调试助手 1. 项目概述2. 项目UI设计3. 串口通信核心代码开发3.1 QSerialPort介绍及示例3.2 扫描系统串口3.3 数据的收发3.4 定时发送&#xff08;QT定时器&#xff09;3.5 HEX显示与发送 4. 串口调试助手功能的优化4.1 串口的实时扫描4.2 获取系…

2024.2.15 模拟实现 RabbitMQ —— 消息持久化

目录 引言 约定存储方式 消息序列化 重点理解 针对 MessageFileManager 单元测试 小结 统一硬盘操作​​​​​​​ 引言 问题&#xff1a; 关于 Message&#xff08;消息&#xff09;为啥在硬盘上存储&#xff1f; 回答&#xff1a; 消息操作并不涉及到复杂的增删查改消…