同步FIFO的verilog实现(1)——计数法

news2024/11/25 13:15:10

一、FIFO概述

1、FIFO的定义

        FIFO是英文First-In-First-Out的缩写,是一种先入先出的数据缓冲器,与一般的存储器的区别在于没有地址线, 使用起来简单,缺点是只能顺序读写数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

2、FIFO的作用

(1)跨时钟域的数据传输

(2)对不同宽度的数据进行位宽转换

(3)数据缓存

3、FIFO的分类

        根据FIFO工作的时钟域的不同,可以将FIFO分为以下两类

        (1)同步FIFO:读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作。常用于对不同宽度的数据进行位宽转换

        (2)异步FIFO:读写时钟不一致,读写操作是互相独立的。常用于跨时钟域的数据传输

4、FIFO的一些重要参数

(1)FIFO宽度:指的是FIFO读写的数据位,就像MCU有8位和16位,ARM 32位等等,FIFO的宽度在单片成品IC中是固定的,也有可选择的,如果用FPGA自己实现一个FIFO,其数据位,也就是宽度是可以自己定义的。

(2)FIFO深度:指的是FIFO可以存储多少个N位的数据(假设FIFO宽度为N)。

(3)满标志(full):FIFO已满或将要满时由FIFO送出的状态信号,以阻止FIFO的写操作,避免数据溢出。

(4)空标志(empty):FIFO已空或将要空时由FIFO送出的状态信号,以阻止FIFO的读操作,避免数据读空。

(5)读时钟:读操作的时钟,在每个时钟沿来临时读数据。

(6)写时钟:写操作的时钟,在每个时钟沿来临时写数据。

(7)读指针:指向下一个要读出的地址,读完后自动加1。

(8)写指针:指向下一个要写入的地址,写完后自动加1。

读写指针其实就是读写的地址,只不过这个地址不能任意选择,而是连续的。

二、同步FIFO

        FIFO设计的关键在于读写指针的设计和生成可靠的空满信号

1、读写指针

  • 读指针:总是指向下一个将要读取的单元,复位时指向第一个单元(编号为0)。
  • 写指针:总是指向当前要被读出的数据,复位时指向第一个单元(编号为0)。

2、空/满信号

        FIFO设计中最重要的是空(Empty)、满(Full)信号的判断。

        当第一次读写指针相等时,表明FIFO为空,这种情况发生在复位操作时或者当读指针读出FIFO中最后一个字后,追赶上写指针时,此时读空信号有效:

        当读写指针再次相等时,表明FIFO为满,这种情况发生在,当写指针转了一圈折回来(wrapped around)又追上了读指针:

        两种方式都是以读写指针相等作为判断标志,所以我们需要寻找其它的方法进行判断。

三、计数法实现同步FIFO

        在同步FIFO中,我们可以很容易的使用计数来判断FIFO中还剩下多少可读的数据,从而可以判断空、满

1、verilog实现

//------------------------<计数法设计同步FIFO>----------------------------
module sync_fifo#(  
//-----------------------------<参数定义>---------------------------------
    parameter FIFO_WIDTH = 16,                          //FIFO宽度
    parameter FIFO_DEPTH = 16                           //FIFO深度
)(
//-----------------------------<接口定义>---------------------------------
    input clk,                                          //时钟信号
    input rst,                                          //复位信号
 
    input [FIFO_WIDTH-1:0] din,                         //FIFO输入数据(写数据)
    input rd_en,                                        //读使能信号 
    input wr_en,                                        //写使能信号

    output reg [FIFO_WIDTH-1:0] dout,                   //FIFO输出数据(读数据) 
    output empty,                                       //FIFO空标志 
    output full,                                        //FIFO满标志
    output reg [$clog2(FIFO_DEPTH):0] fifo_cnt		    //$clog2是以2为底取对数   
);  

//-----------------------------<reg定义>---------------------------------
    reg [FIFO_WIDTH-1:0] fifo_buffer[FIFO_DEPTH-1:0];	//用二维数组实现RAM	
    reg [$clog2(FIFO_DEPTH)-1:0] wr_addr;				//写地址(写指针)
    reg [$clog2(FIFO_DEPTH)-1:0] rd_addr;				//读地址(读指针)                                   

//-----------------------------<读操作>-----------------------------------
always@(posedge clk or posedge rst)begin 
	if(rst)
		rd_addr <= 0;
	else if(rd_en && !empty)begin                       //读使能有效且FIFO非空
		rd_addr	<=	rd_addr + 1'd1;                     //读指针递增
		dout	<=	fifo_buffer[rd_addr];               //fifo读出数据
	end
	else begin
		rd_addr	<=	rd_addr;                            
		dout	<=	dout;
	end
end

//-----------------------------<写操作>-----------------------------------
always@(posedge clk or posedge rst)begin 
	if(rst)
		wr_addr <= 0;
	else if(wr_en && !full)begin                       //写使能有效且FIFO非满
		wr_addr	<=	wr_addr + 1'd1;                    //读指针递增
		fifo_buffer[wr_addr] <= din;                   //数据写入fifo
	end
	else begin
		wr_addr	<=	wr_addr;                            
	end
end

//-----------------------------<fifo_cnt>-----------------------------------
always@(posedge clk or posedge rst)begin 
	if(rst)
		fifo_cnt <=	0;
	else if(wr_en && !full && !rd_en)                   //只写不读且FIFO没有满,fifo_cnt递增
		fifo_cnt <=	fifo_cnt + 1'd1;  
	else if(rd_en && !empty && !wr_en)                  //只读不写且FIFO没有空,fifo_cnt递减
		fifo_cnt <=	fifo_cnt - 1'd1;	                
	else                                                //同时读写或者不读不写,fifo_cnt不变
		fifo_cnt <=	fifo_cnt;                           
end

//-----------------------------<空/满信号>-----------------------------------
assign full  = (fifo_cnt == FIFO_DEPTH) ? 1'b1 : 1'b0;		//满信号
assign empty = (fifo_cnt == 0) ? 1'b1 : 1'b0;				//空信号

endmodule

2、功能测试

`timescale 1ns/1ns
//-----------------------------<计数法同步FIFO测试>---------------------------------
module tb_sync_fifo();
    parameter WIDTH	= 8;
    parameter DEPTH	= 8;

    reg                 clk         ;
    reg                 rst         ;

    reg  [WIDTH-1:0]	din    		;
    reg 				wr_en  		;
    reg 				rd_en  		;
    wire [WIDTH-1:0]	dout		;
    wire 				full        ;
    wire 				empty       ;
    wire [$clog2(DEPTH):0]	fifo_cnt;

//-----------------------------<测试模块例化>---------------------------------
sync_fifo #(
	.FIFO_WIDTH	(WIDTH),		 //FIFO宽度
    .FIFO_DEPTH (DEPTH)          //FIFO深度
)
sync_fifo_u1(
	.clk		(clk		),
	.rst		(rst		),
	.din     	(din 	    ),
	.rd_en		(rd_en		),
	.wr_en		(wr_en		),
                 
	.dout    	(dout	    ),	
	.empty		(empty		),	
	.full		(full		),
	.fifo_cnt	(fifo_cnt	)			
);

//-----------------------------<模块测试>---------------------------------
initial begin
	clk = 1'b0;							//初始时钟为0
	rst <= 1'b0;						//初始复位
	din <= 'd0;		
	wr_en <= 1'b0;		
	rd_en <= 1'b0;
#10
    rst <= 1'b1;
#10 
    rst <= 1'b0;
    repeat(10)
    #10 begin
        wr_en <= 1'b1;
        rd_en <= 1'b0;
        din <= $random;                   //生成8位的随机数
    end

    repeat(10)
    #10 begin
        wr_en <= 1'b0;
        rd_en <= 1'b1;
    end
$finish;
end

//------------------------------<设置时钟>----------------------------------------
always #5 clk = ~clk;			

endmodule

3、测试结果

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

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

相关文章

Flex 布局详解

Flex布局的概念与基础概况 Flex布局又称弹性布局。它使用Flex Box使得容器有了弹性&#xff0c;更加适应不同的设备的不同高度&#xff0c;而不必依赖于传统的块状布局和浮动布局。它是css3中新增的规范&#xff0c;目前主流的浏览器都已支持。但flex不支持IE9及以下版本。 F…

uniapp 解决跨域的问题

uniapp 解决跨域的问题 我真的是个 沙雕 找对了解决办法 写错了地方 "h5" : {"devServer" : {"disableHostCheck" : true,"https": false,"proxy" : {"/app" : {"target" : "https://192.16…

使用IntelliJ IDEA本地启动调试Flink流计算工程的2个异常解决

记录&#xff1a;471 场景&#xff1a;使用IntelliJ IDEA本地启动调试Flink流计算时&#xff0c;报错一&#xff1a;加载DataStream报错java.lang.ClassNotFoundException。报错二&#xff1a;No ExecutorFactory found to execute the application。 版本&#xff1a;JDK 1.…

Windows中多线程的基础知识1——互斥对象

目录 1 多线程的基本概念1.1 进程一、程序和进程的概念二、进程组成三、进程地址空间 1.2 线程一、线程组成二、线程运行三、线程创建函数 1.3 多进程与多线程并发一、多进程并发二、多线程并发 2 线程同步2.1 一个经典的线程同步问题2.2 利用互斥对象实现线程同步一、创建互斥…

模糊测试面面观 | 模糊测试是如何准确定位问题的?

​前几期我们介绍了常见的模糊测试工具、模糊测试的优势及异常发掘&#xff0c;本期我们就来聊一下模糊测试是如何准确定位问题的。我们知道模糊测试是一种通过向目标系统提供非预期的“坏数据”输入并监视异常结果来发现软件漏洞的方法&#xff0c;能否准确定位问题是模糊测试…

Elasticsearch Head的使用

目录 概述一、安装 Elasticsearch Head二、解压文件三、安装Elasticsearch Head依赖四、启动 Elasticsearch Head五、修改Elasticsearch Head启动端口号六、使用 Elasticsearch Head注意事项 概述 Elasticsearch Head 是一个用于管理和监控 Elasticsearch 集群的 Web 界面工具…

Python Flask Web开发三:数据表的字段增加和删除

前言 在实际的开发中&#xff0c;数据表中的字段的增加和删除是很正常的操作&#xff0c;在运营的不断提需求下&#xff0c;这个修改的频率是很高的&#xff0c;那么在flask中如何进行字段的增加和删除呢&#xff1f;下面我来给大家讲讲 一、创建迁移脚本 使用数据库迁移工具…

从0开始学go第四天

模板继承 继承根模板&#xff0c;重新定义“块模板” 【Go Web开发系列教程】07-Go模板继承_哔哩哔哩_bilibili 解析模板时&#xff0c;base模板要在前 渲染模板时&#xff1a; 要用ExecuteTemplate&#xff0c;而不是Excute 模板补充&#xff1a;Go语言标准库之http/templ…

免费在线行为验证,保护你的账号安全

前言 忘记繁琐的验证码吧&#xff01;免费在线行为验证服务&#xff0c;通过滑动图片、滑动拼图和文字点选等方式&#xff0c;确保只有真正的人类用户能够访问。 前端代码 <script src"https://cdn6.kgcaptcha.com/captcha.js"></script> <script&g…

从0到1实现播放控制器

这系列文章主要讲诉如何从0到1使用QT实现带时间显示、滚动字幕等的自定义配置视频播放控制器。平时我们乘坐地铁经常看到各条线的播放控制器都大同小异。其实都是通过QT等界面开发软件来实现的。 在具体开发之前&#xff0c;需要明确我们需要做什么&#xff1f; 1. 开发一个可…

Java中级面试题记录(三)

1.职业规划&#xff1f; 2.每家公司离职原因&#xff1f; 3.SpringCloud用到了哪些组件&#xff1f; GateWayNacosOpenFeignSeataHystrix 4.PG和Mysql的区别&#xff1f; 5.两种数据库的存储区别&#xff1f; 6.MySQL索引了解的内容&#xff1f; 一口气搞定索引的所有知识…

PCL入门(二):初识点云数据

目录 1. 点云数据2. 对点云数据的简单操作3. 结果 1. 点云数据 在pcl里面&#xff0c;定义了很多点云数据类型&#xff0c;比如PointXYZ、PointXYZI、PointXYZRGBA等等&#xff0c;每一个都可以看做是点云的一个点的数据。而整个点云的数据类型被定义为PointCloud。 以pcl::P…

19-springcloud(上)

一 微服务架构进化论 单体应用阶段 (夫妻摊位) 在互联网发展的初期&#xff0c;用户数量少&#xff0c;一般网站的流量也很少&#xff0c;但硬件成本较高。因此&#xff0c;一般的企业会将所有的功能都集成在一起开发一个单体应用&#xff0c;然后将该单体应用部署到一台服务器…

Build阶段-Maven安装配置

构建Java项目的工具一般有两种选择&#xff0c;一个是Maven&#xff0c;一个是Gradle。 这里我们选择Maven作为项目的编译工具。 具体安装Maven流程不做阐述&#xff0c;但是需要确保配置好Maven仓库私服以及JDK编译版本

财报解读:营收利润增长稳健,百果园产业链转型正在进行时?

百果园的精品水果之路越走越踏实。 近日&#xff0c;百果园发布了截至2023年6月30日止六个月的中期业绩报告。财报显示&#xff0c;2023年上半年&#xff0c;集团收入为62.94亿元人民币&#xff0c;同比增长6.4%&#xff1b;毛利为7.13亿元人民币&#xff0c;同比增长5.2%&…

Python列表排序

介绍一个关于列表排序的sort方法&#xff0c;看下面的案例&#xff1a; """ 列表的sort方法来对列表进行自定义排序 """# 准备列表 my_list [["a", 33], ["b", 55], ["c", 11]]# 排序&#xff0c;基于带名函数 …

sklearn中的数据集使用

导库 from sklearn.datasets import load_iris 实现 # 加载数据集 iris load_iris() print(f查看数据集&#xff1a;{iris}) print(f查看数据集的特征&#xff1a;{iris.feature_names}) print(f查看数据集的标签&#xff1a;{iris.target_names}) print(f查看数据集的描述…

【C++】atoi函数和itoa函数无废话极简概述

atoi和itoa这两个函数头文件均为<stdlib.h> atoi atoi全称&#xff1a;array to int&#xff0c;可以把字符串转换为整型 int atoi(const char *nptr); 使用演示&#xff1a; #1 char str[5]; cin>>str; int aatoi(str);#2 int a; aatoi("123");//a…

vue2中实现 TDesign 树形懒加载

之前我有写过Element ui的树形懒加载 其主要是通过load函数来实现 而TDesign也是照虎画猫 他也是主要靠load 我们先来看一个基本的组件 <template><t-tree :data"items" :load"load" /> </template><script lang"jsx">…

mysql忘记root密码如何解决?

第一步&#xff1a;首先右键此电脑打开管理器&#xff0c;查看mysql是否运行 第二步&#xff1a;用管理员模式打开命令框 输入net stop mysql暂停mysql运行 net stop mysql 然后输入下面指令 mysql --console --skip-grant-tables --shared-memory 显示如下 第三步&…