同步FIFO的verilog实现(2)——高位扩展法

2023-11-11

一、前言

        在之前的文章中,我们介绍了同步FIFO的verilog的一种实现方法:计数法。其核心在于:在同步FIFO中,我们可以很容易的使用计数来判断FIFO中还剩下多少可读的数据,从而可以判断空、满。

        关于计数法实现同步FIFO的详细内容,请参考:同步FIFO的verilog实现(1)——计数法

二、高位扩展法原理

        我们知道对于FIFO的设计来说,其核心在于设计读写指针,并且生成可靠的空、满信号。

        当读/写地址指针在复位操作期间被置为零时,或者当读指针在从FIFO中读取了最后一个字之后追上了写指针,此时读指针和写指针相等代表着FIFO为空状态。而当写指针再次追上读指针时,此时读指针和写指针相等代表着FIFO为写满。也就是说当读写指针相等时,FIFO要么为空,要么为满。
   因此我们可以将地址位扩展一位,用最高位来判断空满,其余低位还是正常用于读写地址索引。当写指针递增超过FIFO的最大地址时,写指针的MSB位将置为1,同时将其余低位设置回零。读指针也是如此。如果读指针和写指针的MSB不同,则意味着写指针比读指针多绕了一次,表示FIFO写满。如果两个指针的MSB相同,则表示两个指针的回绕次数相同,表示FIFO读空。如下图所示:

        当最高位不同,且其他位相同,则表示读指针或者写指针多跑了一圈,这显然不可能发生,情况只能是写指针多跑了一圈,与就意味着FIFO被写满了。
        当最高位相同,且其他位相同,则表示读指针追到了写指针或者写指针追到了读指针,而显然不会让写指针追读指针(这种情况只能是写指针超过读指针一圈),所以可能出现的情况只能是读指针追到了写指针,也就意味着FIFO被读空了。

三、同步FIFO的verilog实现

        理解了原理,我们就能很快设计出相应的verilog代码:

//------------------------<高位扩展法设计同步FIFO>----------------------------
module sync_fifo1#(  
//-----------------------------<参数定义>---------------------------------
    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满标志 
); 

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

//-----------------------------<wire定义>---------------------------------     
    wire [$clog2(FIFO_DEPTH) - 1 : 0]	wr_addr_true;	//真实写地址指针
    wire [$clog2(FIFO_DEPTH) - 1 : 0]	rd_addr_true;   //真实读地址指针
    wire								wr_addr_msb;	//写地址指针地址最高位
    wire								rd_addr_msb;	//读地址指针地址最高位
 
    assign {wr_addr_msb,wr_addr_true} = wr_addr;		//将最高位与其他位拼接
    assign {rd_addr_msb,rd_addr_true} = 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_true];               //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_true] <= din;              //数据写入fifo
	end
	else begin
		wr_addr	<=	wr_addr;                            
	end
end

//-----------------------------<通过地址扩展位更新空/满信号>-----------------------------------
assign	empty = ( wr_addr == rd_addr ) ? 1'b1 : 1'b0;                                              //当所有位相等时,读指针追到了写指针,FIFO被读空
assign	full  = ((wr_addr_msb != rd_addr_msb ) && ( wr_addr_true == rd_addr_true )) ? 1'b1 : 1'b0; //当最高位不同但是其他位相等时,写指针超过读指针一圈,FIFO被写满

endmodule

四、测试代码

        给出如下的测试代码:

`timescale 1ns/1ns
//-----------------------------<高位扩展法同步FIFO测试>---------------------------------
module tb_sync_fifo1();
    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       ;

//-----------------------------<测试模块例化>---------------------------------
sync_fifo1 #(
	.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		)	
);

//-----------------------------<模块测试>---------------------------------
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

五、结果

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

同步FIFO的verilog实现(2)——高位扩展法 的相关文章

  • PyOpenCL 中的时间测量

    我正在 FPGA 和 GPU 中使用 PyOpenCL 运行内核 为了测量执行所需的时间 我使用 t1 time event mykernel queue c width c height block size block size d c
  • verilog 中的“<<”运算符

    我有一个verilog代码 其中有一行如下 parameter ADDR WIDTH 8 parameter RAM DEPTH 1 lt lt ADDR WIDTH 这里将存储什么RAM DEPTH以及什么是 lt lt 操作员在这里做
  • 模拟器和合成器之间初始化状态机的差异

    我的问题是关于合成状态机中使用的第一个状态 我正在使用莱迪思 iCE40 FPGA 用于仿真的 EDA Playground 和用于综合的莱迪思 Diamond Programmer 在下面的示例中 我生成一系列信号 该示例仅显示引用状态机
  • 如何获取值数组作为 plusargs?

    如何获取值数组作为参数 我需要从命令行获取一组未定义大小的命令 如何将这些参数放入数组或队列中 Eg CMDS READ WRITE READ N WRITE 它应该被带到一个数组中 value plusargs不支持数组 但支持字符串 看
  • 在verilog中将wire值转换为整数

    我想将电线中的数据转换为整数 例如 wire 2 0 w 3 b101 我想要一个将其转换为 5 并将其存储在整数中的方法 我怎样才能以比这更好的方式做到这一点 j 1 for i 0 i lt 2 i i 1 begin a a w i
  • if 语句导致 Verilog 中的锁存推断?

    我正在编写用于合成算法的 Verilog 代码 我对哪些情况可能导致推断锁存器有点困惑 下面是这样的一段代码 虽然它在模拟中工作得很好 但我担心它可能会导致硬件问题 always b1 or b2 b1 map b2 map m1 map
  • 在 C++ 中创建 Windows 命名管道

    我正在尝试在 C Windows 中创建两个进程之间的简单通信 就像 Linux 中的 FIFO 一样 这是我的服务器 int main HANDLE pipe CreateFile TEXT pipe Pipe GENERIC READ
  • 如何在Altera Quartus中生成.rbf文件?

    什么是 rbf 文件以及如何在 Windows 上从 Quartus 输出文件 sof 生成它们 An RBF is a 原始二进制文件例如 它代表原始数据 这些数据将被加载到闪存中 以便在上电时初始化 FPGA A SOF is an S
  • Verilog 中的“net”代表什么?

    我刚刚开始学习Verilog 据我了解 Verilog有net数据类型 什么是net代表 网络就是这样一种数据类型 您不使用它来存储值 它们代表物理连接 您可以将线路视为一种网络数据类型 你可以去网上看看更多here http www ee
  • FPGA 有哪些实际应用?

    我对我的程序为一个小型七段显示器提供动力感到非常兴奋 但是当我向不在现场的人展示它时 他们总是说 那么你能用它做什么 我永远无法给他们一个简洁的答案 谁能帮我吗 第一 它们不需要具有易失性存储器 事实上 大厂商 Xilinx Altera
  • 向左旋转 verilog 大小写

    我的任务是用verilog编写一个16位ALU 当我做需要旋转操作数和进行2的补码加法和减法的部分时 我发现了困难 我知道如何用纸和铅笔解决这个问题 但我无法弄清楚如何在 Verilog 中做到这一点 例如 A表示为a15 a14 a13
  • 映射 MMIO 区域写回不起作用

    我希望对 PCIe 设备的所有读写请求都由 CPU 缓存进行缓存 然而 它并没有像我预期的那样工作 这些是我对回写 MMIO 区域的假设 对 PCIe 设备的写入仅在缓存回写时发生 TLP 有效负载的大小是缓存块大小 64B 然而 捕获的
  • 在C中读/写结构到fifo

    我正在尝试使用命名管道在进程之间传递结构 我在尝试打开管道非阻塞模式时陷入困境 这是我写入 fifo 的代码 void writeUpdate Create fifo for writing updates strcpy fifo writ
  • 如何在Verilog中将二维数组中的所有位设置为0?

    我构建了一个 8 2bits 数组来表示 Verilog 中的一块内存 reg 1 0 m 0 7 该存储器有一个复位信号 如果复位为1 则该存储器中的所有位都应重置为0 但是我不知道如何以简洁的方式设置m的所有位 因为如果有数百个内存中有
  • 在测试台中显示信号名称/文字

    是否可以在 Verilog 中引用 显示信号的名称 文字 对于在 Verilog 测试台中创建通用信号检查功能来说 这将是一个有用的功能 我知道使用 display 时 m 将打印信号的范围 是否有显示信号名称的等效项 在 Verilog
  • 在内核 OpenCL 中实现 FIFO 的最佳方法

    目标 在 OpenCL 中实现下图所示 OpenCl 内核所需的主要内容是将系数数组和临时数组相乘 然后最后将所有这些值累加为 1 这可能是最耗时的操作 并行性在这里非常有帮助 我正在为内核使用一个辅助函数来执行乘法和加法 我希望这个函数也
  • SQL Server 中的 FIFO 查询

    我正在构建一个库存管理应用程序c with SQL server 我想做一个FIFO从我的表查询 我以可变价格购买了相同的产品 之后我卖掉了其中一些 我想根据 先进先出 进行查询BatchDate柱子 所以我想通过PurchasePrice
  • Verilog:如何取绝对值

    在 verilog 中 我有一个二进制值数组 如何取减去值的绝对值 Verilog代码 module aaa clk input clk reg 7 0 a 1 9 reg 7 0 s 1 9 always posedge clk begi
  • 从测试台访问子模块中的输入和输出

    我的被 测设备 DUT 有许多子模块 我想测试其中的一些 我的测试夹具将是我的项目的顶层 比 DUT 高一级 并且由于我似乎只能访问下一层模块的输入和输出 所以我只能访问顶层的输入和输出被测设备 我希望能够从测试夹具下方的两层或多层模块访问
  • 修改verilog模式缩进

    我试图让 verilog 模式使用 2 个空格缩进除 decls 和always 之外的所有内容 这是我添加到 emacs 中的内容 define are not indented setq veril

随机推荐

  • JVM && 软件测试的目的和原则 && Spring基本概念 && 项目创建 && 软件测试的生命周期 && SpringBoot创建和运行 && Bean作用域

    第 1 题 多选题 题目名称 以下哪些属于 JVM 题目内容 A JRockit B HotSpot C V8Worker D Clang 第 2 题 单选题 题目名称 在代码中创建一个 java lang String 这样的类 这个类最
  • 关键元器件器件选型设计指引--LED

    前言 LED 发光二极管 是一种将电能转换为光能的固体电致发光器件 由于具有体积小 重量轻 工作电压低 耗能低 响应时间短 寿命长 抗震性能好等优点 LED得到广泛的应用 在网通 数通领域 LED应用于指示功能 功能主要包括 Power L
  • 百度后台开发类笔试题2014校园招聘 武汉站

    软件开发试题 1 简答题 1 说明动态链接库和静态链接库的区别 2 轮询任务调度和抢占式任务调度的特点 3 简要说明数据库锁机制以及描述 2 算法题 1 给出任意一个正整数 算出大于它的最小不重复数 即不存在相邻两个数相同的情况 2 给出一
  • 超详细!Jmeter性能测试

    前言 性能测试是一个全栈工程师 架构师必会的技能之一 只有学会性能测试 才能根据得到的测试报告进行分析 找到系统性能的瓶颈所在 而这也是优化架构设计中重要的依据 测试流程 需求分析 环境搭建 测试计划 脚本开发 执行与监控 缺陷管理 结果与
  • 电磁屏蔽知多少?

    原文来自公众号 工程师看海 不管什么电子产品 EMC始终是其需要面对的问题 EMC全拼是Electromagnetic Compatibility即电磁兼容性 EMC分为EMS electromagnetic susceptibility
  • 【docker】dcoker-compose介绍

    文章目录 前言 一 Docker compose简介 1 docker compose基础概念 2 为什么要使用docker compose 二 YAML文件格式及编写注意事项 1 YAML文件格式 2 YAML格式的注意事项 3 YAML
  • 15.Xaml StackPanel控件 -->堆栈面板

    1 运行效果 2 运行源码 a Xaml源码
  • AIX7.1安装中文字符集

    为了安装中文字符集找了n多文章 下载n多安装包 就是没有一个好用的 所以跑官网上查询一翻 官网地址 https www ibm com support knowledgecenter zh ssw aix 71 install insgdr
  • 密码学的一些基本概念

    密码学是研究如何隐密地传递信息的学科 密码学的作用 机密性 是网络信息不泄露给非授权用户的特性 防止被动攻击 常用的保密技术包括 防侦听 防辐射 信息加密 物理保密等 完整性 完整性是网络信息未经授权不能进行改变的特性 完整性是一种面向信息
  • win7右键没有新建文本文档怎么办

    第一种方法 打开 开始 在搜索框内输入CMD 或者按快捷键WIN图标 R 复制reg add HKEY CLASSES ROOT txt ve d txtfile f 回车运行 再复制粘贴reg add HKEY CLASSES ROOT
  • numpy中设置始终使用定点表示法显示小数

    默认numpy会在某些情况触发科学计数法显示 scientific notation is used when absolute value of the smallest number is lt 1e 4 or the ratio of
  • 前置++和后置++的区别

    今天在阅读 google c 编程风格 的文档的时候 5 10 前置自增和自减 有一句话引起了我的注意 对于迭代器和其他模板对象使用前缀形式 i 的自增 自减运算符 理由是 前置自增 i 通常要比后置自增 i 效率更高 于是我查了查前置 和
  • 【C++学习第五讲】第一章总结 + 复习题(十一道)

    目录 第一章总结 一 总结 二 复习题 1 C 程序的模块叫什么 2 下面的预处理器编译指令的功能是什么 3 下面的语句的功能是什么 4 什么语句可以用来输出 hello world 然后开始新的一行 5 什么语句可以用来创建名为chees
  • TBDR下msaa 在metal vulkan和ogles的解决方案

    https developer arm com solutions graphics developer guides understanding render passes multi sample anti aliasing msaa在
  • 第十四届蓝桥杯大赛软件赛省赛(Java 大学B组)

    目录 试题 A 阶乘求和 1 题目描述 2 解题思路 3 模板代码 试题 B 幸运数字 1 题目描述 2 解题思路 3 模板代码 试题 C 数组分割 1 题目描述 2 解题思路 3 模板代码 试题 D 矩形总面积 1 问题描述 2 解题思路
  • (译)cocos2d-x跨android&ios平台开发入门教程

    免责申明 必读 本博客提供的所有教程的翻译原稿均来自于互联网 仅供学习交流之用 切勿进行商业传播 同时 转载时不要移除本申明 如产生任何纠纷 均与本博客所有人 发表该翻译稿之人无任何关系 谢谢合作 原文链接地址 http www raywe
  • Windows下小白安装Qt详细教程

    一 软件下载 官网下载地址 http download qt io 1 点击进入 2 archive 和 official releases 两个目录都有最新的 Qt 开发环境安装包 我们以 archive 目录里的内容为例来说明 点击进入
  • 太强大!发现一个数据分析老司机专用神器!

    去年秋招 字节跳动整体报录比降到了2 创造了150000人争3000岗位的盛况 今年909万毕业生再创新高 激烈程度可想而知 除了技术岗 大部分毕业生也瞄准了高薪高前景的数据分析师岗位 教育部关于高校毕业生就业工作通知 人才缺口 巨大 未来
  • 用python进行数据分析(一:数据理解)

    python作为当前主流的语言之一 他的功能是非常强大的 不论是在游戏行业还是数据分析行业还是软件开发啥的好像都可以用python 但作为一个数据分析师 并不需要用到他的全部功能 只是想要达到 能够用python完成数据分析工作 的效果来帮
  • 同步FIFO的verilog实现(2)——高位扩展法

    一 前言 在之前的文章中 我们介绍了同步FIFO的verilog的一种实现方法 计数法 其核心在于 在同步FIFO中 我们可以很容易的使用计数来判断FIFO中还剩下多少可读的数据 从而可以判断空 满 关于计数法实现同步FIFO的详细内容 请