Verilog功能模块——同步FIFO

news2025/6/25 19:24:16

前言

FIFO功能模块分两篇文章,本篇为同步FIFO,另一篇为异步FIFO,传送门:

Verilog功能模块——异步FIFO-CSDN博客

同步FIFO实现起来是异步FIFO的简化版,所以,本博文不再介绍FIFO实现原理,感兴趣的同学可以去看我异步FIFO的文章,基本看懂了异步FIFO,同步FIFO自然就懂了。


二. 模块功能框图与信号说明

信号说明:

分类信号名称输入/输出说明
参数DATA_WIDTH数据位宽
ADDR_WIDTH地址位宽,FIFO深度=2**ADDR_WIDTH
FWFT_ENFirst word fall-through输出模式使能,高电平有效
FIFO写端口dininputFIFO数据输入
wr_eninputFIFO写使能
fulloutputFIFO满信号
almost_fulloutputFIFO快满信号,FIFO剩余容量<=1时置高
FIFO读端口doutoutputFIFO数据输出
rd_eninputFIFO读使能
emptyoutputFIFO空信号
almost_emptyoutputFIFO快空信号,FIFO内数据量<=1时置高
时钟与复位clkinputFIFO读时钟
rstinputFIFO读复位

注意:

  1. 信号的命名与Vivado中的FIFO IP核完全一致
  2. 复位均为高电平复位,与Vivado中的FIFO IP核保持一致
  3. 复位为异步复位
  4. FIFO深度通过ADDR_WIDTH来设置,所以FIFO的深度必然是2的指数,如2、4、8、16等

三. 部分代码展示

//++ 生成读写指针 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
reg  [ADDR_WIDTH:0] rptr;
always @(posedge clk or posedge rst) begin
  if (rst)
    rptr <= 0;
  else if (rd_en & ~empty)
    rptr <= rptr + 1'b1;
end


reg  [ADDR_WIDTH:0] wptr;
always @(posedge clk or posedge rst) begin
  if (rst)
    wptr <= 0;
  else if (wr_en & ~full)
    wptr <= wptr + 1'b1;
end


wire [ADDR_WIDTH-1:0] raddr = rptr[ADDR_WIDTH-1:0];
wire [ADDR_WIDTH-1:0] waddr = wptr[ADDR_WIDTH-1:0];


wire [ADDR_WIDTH:0] rptr_p1 = rptr + 1'b1;
wire [ADDR_WIDTH:0] wptr_p1 = wptr + 1'b1;
//-- 生成读写指针 ------------------------------------------------------------


//++ 生成empty与almost_empty信号 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always @(*) begin
  if (rst)
    empty <= 1'b1;
  else if (rptr == wptr)
    empty <= 1'b1;
  else
    empty <= 1'b0;
end


always @(*) begin
  if (rst)
    almost_empty <= 1'b1;
  else if (rptr_p1 == wptr || empty)
    almost_empty <= 1'b1;
  else
    almost_empty <= 1'b0;
end
//-- 生成empty与almost_empty信号 ------------------------------------------------------------


//++ 生成full与almost_full信号 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always @(*) begin
  if (rst)
    full  <= 1'b1;
  else if ((wptr[ADDR_WIDTH] != rptr[ADDR_WIDTH])
          && (wptr[ADDR_WIDTH-1:0] == rptr[ADDR_WIDTH-1:0])
          )
    full  <= 1'b1;
  else
    full  <= 1'b0;
end


always @(*) begin
  if (rst)
    almost_full <= 1'b1;
  else if (((wptr_p1[ADDR_WIDTH] != rptr[ADDR_WIDTH])
            && (wptr_p1[ADDR_WIDTH-1:0] == rptr[ADDR_WIDTH-1:0])
            )
          || full
          )
    almost_full <= 1'b1;
  else
    almost_full <= 1'b0;
end
//-- 生成full与almost_full信号 ------------------------------------------------------------

三. 功能仿真

比较以下情形中的fifo行为是否与FIFO IP核一致,

情形一:单次写单次读

情形二:写满后再读空

情形三:在读的过程中写,在写的过程中读

判断模块功能正常的依据:

  1. 写入数据是否按顺序正常读出
  2. 空信号和满信号是否正常输出。

为方便比较,编写了顶层文件,实例化了FIFO IP核与自编模块,部分代码如下:

vivado_sync_fifo vivado_sync_fifo_u0 (
  .clk          (clk                     ), // input wire clk
  .rst          (rst                     ), // input wire rst
  .din          (din                     ), // input wire [7 : 0] din
  .wr_en        (wr_en                   ), // input wire wr_en
  .rd_en        (rd_en                   ), // input wire rd_en
  .dout         (vivado_fifo_dout        ), // output wire [7: 0] dout
  .full         (vivado_fifo_full        ), // output wire full
  .almost_full  (vivado_fifo_almost_full ), // output wire almost_full
  .empty        (vivado_fifo_empty       ), // output wire empty
  .almost_empty (vivado_fifo_almost_empty)// output wire almost_empty
);


syncFIFO # (
  .DATA_WIDTH (DATA_WIDTH),
  .ADDR_WIDTH (ADDR_WIDTH),
  .FWFT_EN    (FWFT_EN   )
) syncFIFO_inst (
  .din          (din         ),
  .wr_en        (wr_en       ),
  .full         (full        ),
  .almost_full  (almost_full ),
  .dout         (dout        ),
  .rd_en        (rd_en       ),
  .empty        (empty       ),
  .almost_empty (almost_empty),
  .clk          (clk         ),
  .rst          (rst         )
);

testbench部分代码如下:

// 生成时钟
localparam CLKT = 2;
initial begin
  clk = 0;
  forever #(CLKT / 2) clk = ~clk;
end


// 读写使能控制
initial begin
  rst = 1;
  #(CLKT * 2)
  rst = 0;
  wr_en = 0;
  rd_en = 0;
  #(CLKT * 2)
  wait(~full && ~vivado_fifo_full); // 两个FIFO都从复位态恢复时开始写

  // 写入一个数据
  wr_en = 1;
  #(CLKT * 1)
  wr_en = 0;

  // 读出一个数据
  wait(~empty && ~vivado_fifo_empty);// 两个FIFO都非空时开始读,比较读数据和empty信号是否有差异
  rd_en = 1;
  #(CLKT * 1)
  rd_en = 0;

  // 写满
  wr_en = 1;
  wait(full && vivado_fifo_full); // 两个FIFO都满时停止写,如果两者不同时满,则先满的一方会有写满的情况发生,但对功能无影响
  // vivado FIFO IP在FWFT模式时, 设定深度16时实际深度为17, 但仿真显示full会在写入15个数据后置高, 过几个时钟后后拉低,
  // 再写入一个数据, full又置高; 然后过几个时钟又拉低, 再写入一个数据置高, 如此才能写入17个数据
  // 所以这里多等待12个wclk周期, 就是为了能真正写满vivado FWFT FIFO
  #(CLKT * 12)
  wr_en = 0;

  // 读空
  wait(~empty && ~vivado_fifo_empty);
  rd_en = 1;
  wait(empty && vivado_fifo_empty); // 两个FIFO都空时停止读,如果两者不同时空,则先空的一方会有读空的情况发生,但对功能无影响
  rd_en = 0;

  #(CLKT * 10)
  $stop;
end


// 使用以下代码时,先注释掉上面的读写使能控制initial
// 同时读写
// initial begin
//   #(CLKT * 30)
//   $stop;
// end

// assign wr_en = ~full || ~vivado_fifo_full; // 未满就一直写
// assign rd_en = ~empty || ~vivado_fifo_empty; // 未空就一直读

always @(posedge clk) begin
  if (rst)
    din <= 0;
  else if (wr_en && ~full && ~vivado_fifo_full)
    din <= din + 1;
end


endmodule

8bit,16深度,FWFT FIFO仿真,波形如下:

可以看到模块输出的自编fifo与vivado fwft fifo的写端口和读端口行为是一致的,只是可能会超前或滞后一定的clk周期。

可以看到empty拉低时,数据已经有效了,所以自编模块实现了FWFT功能,Vivado FIFO的实际深度为17,所以它多读出了一个数据,空信号更晚拉高。

因篇幅问题,其它条件下的仿真不再展示,感兴趣的同学可通过更改testbench自行验证。

  1. FWFT_EN改为0,注意同步修改Vivado FIFO的配置

四. 工程分享

Verilog功能模块——同步FIFO,Vivado 2021.2工程。

欢迎大家关注我的公众号:徐晓康的博客,回复以下四位数字获取。

8302

建议复制过去不会码错字!

或者在我的码云仓库获取,传送门:

徐晓康/Verilog功能模块 - 码云 - 开源中国 (gitee.com)


徐晓康的博客持续分享高质量硬件、FPGA与嵌入式知识,软件,工具等内容,欢迎大家关注。

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

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

相关文章

2023年中国电子白板市场规模、竞争格局及应用领域市场结构[图]

电子白板作为新型教育手段&#xff0c;如果合理地运用到现代教育活动中&#xff0c;使其自身的重视功能高效发挥出来&#xff0c;就能够极大地提升教育活动开展的顺利程度&#xff0c;加深学生对知识点的理解与把握&#xff0c;充分尊重学生是学习主体的地位&#xff0c;将保障…

【算法优选】 二分查找专题——贰

文章目录 &#x1f60e;前言&#x1f332;[山脉数组的峰顶索引](https://leetcode.cn/problems/peak-index-in-a-mountain-array/)&#x1f6a9;题目描述&#xff1a;&#x1f6a9;算法思路&#x1f6a9;代码实现&#xff1a; &#x1f334;[寻找峰值](https://leetcode.cn/pro…

Linus - make命令 和 makefile

make命令和 makefile 如果之前用过 vim 的话&#xff0c;应该会对 vim 又爱又恨吧&#xff0c;刚开始使用感觉非常的别扭&#xff0c;因为这种编写代码的方式&#xff0c;和在 windows 当中用图形化界面的方式编写代码的方式差别是不是很大。当你把vim 用熟悉的之后&#xff0…

苹果的数据怎么传输到电脑上?这五种方法轻松实现!

在日常使用苹果设备时&#xff0c;我们经常需要将重要的数据传输到电脑上进行备份或处理&#xff0c;那么苹果的数据怎么传输到电脑上呢&#xff1f;接下来&#xff0c;本文将为您提供多种传输的方法&#xff0c;帮助您将苹果设备上的数据轻松传输到电脑上。 方法一、使用iTun…

如何在雷电模拟器上安装Magisk并加载movecert模块抓https包(二)

接来下在PC端安装和配置Charles&#xff0c;方法同下面链接&#xff0c;不再赘述。在模拟器上安装magisk实现Charles抓https包&#xff08;二&#xff09;_小小爬虾的博客-CSDN博客 一、记录下本机IP和代理端口 二、在手机模拟器上设置代理192.168.31.71:8888&#xff0c;设置…

VScode商店无法访问

下面的方法也许对你没用&#xff0c;也许也有用&#xff0c;但是尝试一下不会有任何副作用。 步骤一&#xff1a; 步骤二&#xff1a;在Proxy代理设置中复制输入 http://127.0.0.1:8080 步骤三&#xff1a;关闭软件&#xff0c;再打开VScode&#xff0c;把http://127.0.0.1:8…

Typora安装教程

Typora 安装教程 安装 官网最新版 自行官网下载 社区版&#xff08;老版本&#xff0c;附带激活码&#xff09; 链接: https://pan.baidu.com/s/1t_3o3Xi7x09_8G1jpQYIvg?pwdmeyf 提取码: meyf 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 将百度云盘下…

单目标应用:火鹰优化算法(Fire Hawk Optimizer,FHO)求解微电网优化--提供MATLAB代码

一、火鹰优化算法FHO 火鹰优化算法&#xff08;Fire Hawk Optimizer&#xff0c;FHO&#xff09;由Mahdi Azizi等人于2022年提出&#xff0c;该算法性能高效&#xff0c;思路新颖。 单目标优化&#xff1a;火鹰优化算法&#xff08;Fire Hawk Optimizer&#xff0c;FHO&#…

【人工智能数学基础】几何解释——最小二乘法

先来一组对应关系&#xff1a; 一、使用拟合。 1.1代数计算 拟合后误差为&#xff0c;要找到一个a&#xff0c;使得 的和最小&#xff0c;计算 &#xff0c;用 f(a) 表示&#xff1a; 带入数据即可得到 易得f(a)最小时的a值。 1.2解超定方程组 用向量表示x和y&#xff1a…

自动化脚本编写实例-python

1. 打开浏览器&#xff0c;访问p.to 2. 登陆 登陆这动作传入的参数只有一个“用户密码” 需要执行的操作有两个&#xff1a;1. 向输入框输入密码 2. 点击确定 需要意的是在登陆的时候可能出现页面还没有加载出来&#xff0c;我们的程序就开始填写表单的情况。 为了防止异常…

机器学习-概述与贝叶斯算法

机器学习的一般步骤&#xff1a;数据搜集、数据清洗、特征工程、数学建模。数据划分&#xff1a;训练集、验证集、测试集。K折交叉验证&#xff1a;解决数据量不够大问题&#xff0c;解决参数调优问题。深度学习不用做特征工程&#xff0c;传统机器学习要。损失函数&#xff0c…

Paddle安装

Paddle安装参考 docs/tutorials/INSTALL_cn.md PaddlePaddle/PaddleDetection - Gitee.comhttps://gitee.com/paddlepaddle/PaddleDetection/blob/release/2.6/docs/tutorials/INSTALL_cn.md # 不指定版本安装paddle-gpu python -m pip install paddlepaddle-gpu# 测试安装 …

A股风格因子看板 (2023.10 第04期)

该因子看板跟踪A股风格因子&#xff0c;该因子主要解释沪深两市的市场收益、刻画市场风格趋势的系列风格因子&#xff0c;用以分析市场风格切换、组合风格暴露等。 今日为该因子跟踪第04期&#xff0c;指数组合数据截止日2023-09-30&#xff0c;要点如下 近1年A股风格因子检验统…

PySpark 概述

文章最前&#xff1a; 我是Octopus&#xff0c;这个名字来源于我的中文名--章鱼&#xff1b;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github &#xff1b;这博客是记录我学习的点点滴滴&#xff0c;如果您对 Python、Java、AI、算法有兴趣&#xff0c;可以关注我的…

Windows Nginx 服务器部署(保姆级)

大家好 我是寸铁 不知道怎么部署Windows Nginx 服务器看过来 手把手带你部署服务器 将你的本地网页部署到服务器上 话不多说&#xff0c;直接上操作&#xff01;&#xff01;&#xff01; Windows Nginx服务器部署 进入下载地址&#xff1a; http://nginx.org/en/download.h…

HQChart实战教程66-动态调整HQChart布局大小

HQChart实战教程66-动态调整HQChart布局大小 需求小程序h5AppHQChart插件源码地址 需求 在不销毁hqchart实例的情况下&#xff0c;动态调整K线图或分时图的大小&#xff0c; 如下图&#xff0c;把图1的K线图大小调整为图2的大小 图1 图2 小程序 调整画布大小&#xff0c;并…

基于VUE的图书借阅管理系统的设计与实现

目录 一、摘要 二、技术描述 三、部分截图 四、获取方式 一、摘要 随着我国经济的高速发展&#xff0c;人们对图书的需求也愈发旺盛&#xff0c;而传统图书管理模式存在以下弊端&#xff1a;信息存储和分类操作不够高效&#xff0c;导致查找书籍困难&#xff1b;借还书流程…

2019庐阳区(试卷及题解)

2019庐阳区 Accepted P1919 身高测量仪(height)843511 Accepted P1920 蚂蚁(ant)673383 Accepted P1921 布展(diff)943244 Accepted P1922 防盗(guard) 身高测量仪(height) 题目描述 给智能电子身高测量仪&#xff0c;写一个显示程序。 输入一个数字N&#xff0c…

Linux友人帐之网络配置与网络传输

一、相关概念 IP地址 IP地址&#xff08;Internet Protocol Address&#xff09;是用于唯一标识和定位计算机网络中设备&#xff08;如计算机、服务器、路由器等&#xff09;的数字标识。在互联网中&#xff0c;IP地址是用来进行网络通信和数据传输的基础。 IP地址由32位或128…

书客、柏曼、爱德华哪款比较值得入手?三款台灯多维度测评

随着现在孩子的近视趋势越来越严峻&#xff0c;有很多家长开始意识到自己的孩子也出现了揉眼睛、时不时眯眯眼的情况。而台灯作为守护孩子用眼环境的必备用品&#xff0c;很多家长想给孩子购置一款护眼灯&#xff0c;却看见市面琳琅满目的款式根本不知道怎么购买。 所以今天为了…