基于System verilog的同步FIFO实现(二)
上一篇博客基于System verilog的同步FIFO实现(一)
通过设置一个计数器,来判断FIFO的空或满状态,该方法由于多设置了一个计数器,因此会产生额外的资源,当fifo比较大时,会降低fifo最终可以达到的速度。本文则通过另一种方式生成full与empty信号:比较读指针和写指针。
判断方法:
1.当FIFO复位之后,读指针和写指针的都指向第0个位置,此时FIFO为空;
2.当写指针绕了一圈又追上读指针后,即wr_ptr=rd_ptr,此时FIFO为满;
3.当读指针也绕了一圈追上写指针后,即wr_ptr=rd_ptr,此时FIFO为空。
鉴于上述判断方法,为了区分到底是满状态还是空状态,可以采用以下方法进行电路的设计:
在指针中添加一个额外的位(extra bit),当写指针增加并越过最后一个FIFO地址时,就将写指针这个未用的MSB加1,其它位回零。对读指针也进行同样的操作。此时,对于深度为2n2^n2n的FIFO,需要的读/写指针位宽为(n+1)(n+1)(n+1)位,如对于深度为8的FIFO,需要采用4bit的计数器,MSB作为折回标志位,而低3位作为地址指针。
如果两个指针的MSB不同,说明写指针比读指针多折回了一次,FIFO为满。
如果两个指针的MSB相同,则说明两个指针折回的次数相等。其余位相等,说明FIFO为空。
代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/02/22 00:05:11
// Design Name:
// Module Name: sync_fifo
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module sync_fifo
#(parameter DATA_WIDTH = 32,parameter FIFO_DEPTH = 32)
(
input logic clk,
input logic rst,
input logic wr_en,
input logic [DATA_WIDTH-1:0] wdata,
input logic rd_en,
output logic [DATA_WIDTH-1:0] rdata,
output logic full,
output logic empty);
logic [$clog2(FIFO_DEPTH)-1:0] wr_ptr; //指向下一个要写的地址
logic [$clog2(FIFO_DEPTH)-1:0] rd_ptr; //指向下一个要读的地址
logic [$clog2(FIFO_DEPTH):0] wr_addr; //最高位用来标记空满
logic [$clog2(FIFO_DEPTH):0] rd_addr; //最高位用来标记空满
//
assign wr_ptr=wr_addr[$clog2(FIFO_DEPTH)-1:0];
assign rd_ptr=rd_addr[$clog2(FIFO_DEPTH)-1:0];
//
logic [DATA_WIDTH-1:0] FIFO [0:FIFO_DEPTH-1];
//wr_addr
always_ff@(posedge clk,posedge rst)
if(rst)wr_addr<=0; //复位时写指针为0
else if(wr_en&&~full) //写使能信号有效且fifo未满wr_addr<=wr_addr+1;
//rd_addr
always_ff@(posedge clk,posedge rst)
if(rst)rd_addr<=0;
else if(rd_en&&~empty) //写使能信号有效且FIFO非空rd_addr<=rd_addr+1;
//flag
assign full=(rd_addr=={~wr_addr[$clog2(FIFO_DEPTH)],wr_ptr})?1'b1:1'b0;
assign empty=(rd_addr==wr_addr)?1'b1:1'b0;
//write
always_ff@(posedge clk)
if(wr_en&&~full)FIFO[wr_ptr]<=wdata;
//read
always_ff@(posedge clk,posedge rst) //rd_en拉高后的下一个周期读出
if(rst)rdata<=0;
else if(rd_en&&~empty)rdata<=FIFO[rd_ptr];
endmodule
测试平台如下,error信号为高说明fifo出错:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/02/22 00:27:44
// Design Name:
// Module Name: test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module test;
parameter DATA_WIDTH = 32;
parameter FIFO_DEPTH = 32;
logic wr_en_r;
logic rd_en_r;
logic clk;
logic rst;
logic wr_en;
logic rd_en;
logic [DATA_WIDTH-1:0] wdata;
logic [DATA_WIDTH-1:0] rdata;
logic empty;
logic full;
logic [DATA_WIDTH-1:0] ref_data;
logic rd_en_ff1;
logic error;
//ref_data
always_ff@(posedge clk,posedge rst)
if(rst)ref_data<=0;
else if(rd_en_ff1)ref_data<=ref_data+1;
//rd_en_ff1
always_ff@(posedge clk)rd_en_ff1<=rd_en;
//wr_en,rd_en
assign wr_en=(~full)?wr_en_r:1'b0;
assign rd_en=(~empty)?rd_en_r:1'b0;
//clk
initial beginclk=0;forever begin#5 clk=~clk;end
end
//rst
initial
beginrst=1;#20rst=0;
end
//wdata
always_ff@(posedge clk,posedge rst)
if(rst)wdata<=0;
else if(wr_en&&~full) //每写入一个数据,加1wdata<=wdata+1;
//wr_en
always_ff@(posedge clk,posedge rst)
if(rst)wr_en_r<=0;
else if($random%100<80) //有60%的几率写数据,衡量数据写入速率wr_en_r<=1'b1;
elsewr_en_r<=1'b0;
//rd_en
always_ff@(posedge clk,posedge rst)
if(rst)rd_en_r<=0;
else if($random%100<40) //有40%的几率读数据,衡量数据读出速率rd_en_r<=1'b1;
else rd_en_r<=1'b0;
//check result
always_comb
if(rd_en_ff1&&ref_data!=rdata)error=1;
elseerror=0;//inst
sync_fifo
#(
.DATA_WIDTH(32),
.FIFO_DEPTH(32)
)
U
(.*);
// input logic clk,
// input logic rst,
// input logic wr_en,
// input logic [DATA_WIDTH-1:0] wdata,
// input logic rd_en,
// output logic [DATA_WIDTH-1:0] rdata,
// output logic full,
// empty
endmodule
仿真波形如下图所示,可以看到error信号始终为低电平,说明设计无误。
基于System verilog的同步FIFO实现(二)相关推荐
- 跨时钟域信号处理(二)——异步fifo的Verilog实现(附同步fifo的实现)
需要回答几个问题: 1.什么是异步FIFO,异步FIFO有什么功能? 跨时钟域的数据交换,防止亚稳态. 2.在产生写满与读空信号时需要进行跨时钟域如何做的,且如何能正确指示空满状态? 寄存器打两拍+格 ...
- 同步FIFO和异步FIFO的Verilog实现
FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据, 其 ...
- 【FPGA——基础篇】同步FIFO与异步FIFO——Verilog实现
FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据, 其 ...
- 01 【Verilog实战】同步FIFO的设计(附源码RTL/TB)
虚拟机:VMware -14.0.0.24051 环 境:ubuntu 18.04.1 脚 本:makefile(点击查看) 应用工具:vcs 和 verdi 写在前面 这个专栏的内容记录的是个人学习 ...
- 手把手Verilog HDL同步Vaild-Ready握手FIFO机制
这里写目录标题 一级目录 二级目录 三级目录 1.V-R握手FIFO简介 2.先实现一个同步FIFO 2.1 FIFO简介 2.2 同步FIFO指标 2.3 同步FIFO设计 2.4 计数器法实现同步 ...
- 【FPGA】FIFO的Verilog设计之同步FIFO的设计
这个同步FIFO的设计方法是调用异步读写双端口RAM来实现的. 关于异步读写双端口RAM的设计,前面博文已经讲到过了:[FPGA]双端口RAM的设计(异步读写) 此时使用双端口RAM来设计FIFO,可 ...
- (28)System Verilog进程间同步(事件event)
(28)System Verilog进程间同步(事件event) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(事件eve ...
- (30)System Verilog进程间同步(邮箱mailbox)
(30)System Verilog进程间同步(邮箱mailbox) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(邮箱m ...
- (29)System Verilog进程间同步(旗语semaphore)
(29)System Verilog进程间同步(旗语semaphore) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(旗 ...
最新文章
- 2021年大数据Flink(十二):流批一体API Transformation
- 跨工厂物料状态/特定工厂的物料状态
- HTML5实战 学习笔记
- 微信小程序自定义组件
- UVA621 Secret Research【水题】
- 数据分析必备算法(算数平均值,加权平均值,最值,中位数,标准差,时间数据处理 ,数组的轴向汇总, 移动均线 ,卷积(简单概念))
- 黑盒测试和白盒测试的基本原理/区别是什么?
- 7个月吐血整理!Android面试相关文章及Github学习资料(标星3.2K)
- Maven项目集成cxf框架发布WebService
- 重磅!这可能是史上最全的AI产业链地图了
- 要成为游戏开发人员需要有以下书籍(二)
- 微信小程序:购物车总结(商品左右联动)
- 用命令提示符运行java_怎么用命令提示符运行java程序?
- STM32F407ZG 实现DMA收发数据
- VR全景照片拍摄小技巧分享
- MySQL Workbench构建ER图(实体关系图)
- 机器学习 逻辑回归算法应用案例
- MTK-手机锁等相关密码配置
- 全自动加药装置特点和组成部分以及操作过程介绍
- 飞鸽传书网,打造精准化生活搜索
热门文章
- 无效的 ProgID“ShockwaveFlash.ShockwaveFlash” 导入 progid 时遇到错误: “ShockwaveFlash.ShockwaveFlash”
- 俊成码付出修复版源码
- 如何做好项目工时管理?
- nginx 反向代理到域名
- 卡尔曼滤波与组合导航原理_基于RAEKF的GPS/INS紧组合导航方法研究
- 大教堂终将倒下,但集市永存
- Ros结合科大讯飞linuxSDK进行离线语唤醒、命令识别
- 001.网络TCP/IP工程知识点
- 肖锰:浪潮GS开发平台学习札记(五)——数据对象和数据模型
- java计算机毕业设计医护人员排班系统源码+系统+lw+数据库+调试运行