Verilog功能模块——读写位宽不同的异步FIFO

这篇具有很好参考价值的文章主要介绍了Verilog功能模块——读写位宽不同的异步FIFO。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

FIFO系列文章目录:

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

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

Verilog功能模块——读写位宽不同的异步FIFO-CSDN博客

Verilog功能模块——读写位宽不同的同步FIFO-CSDN博客

Verilog功能模块——标准FIFO转FWFT FIFO-CSDN博客


fifo读写位宽不一致,Verilog,Verilog,FIFO,异步FIFO,读写位宽不同,位宽变换,1024程序员节

前言

前面的博文已经讲了异步FIFO和同步FIFO,但并没有实现FIFO的读写位宽转换功能,此功能是FIFO的主要功能之一,应用十分广泛,因此,在前面两个模块的基础上,本文使用纯Verilog实现了读写位宽不同的FIFO,并仿真验证了设计的正确性。


一. 实现思路

fifo读写位宽不一致,Verilog,Verilog,FIFO,异步FIFO,读写位宽不同,位宽变换,1024程序员节

思路:

  1. 根据读写数据位宽的关系,分两种情况,当读位宽>写位宽时组合数据;当读位宽<写位宽时分解数据

  2. 同步FIFO作为缓冲,深度固定为2,异步FIFO作为主体,深度为设定深度

  3. 当读位宽≥写位宽时,读端口逻辑无需关心,同步FIFO时钟与异步FIFO写时钟为同一时钟,只要同步FIFO中有数据就立刻读出,组合之后写入异步FIFP,所以写端口的full信号只会在异步FIFO满之后再写入两个数据才置高,此时不必担心同步FIFO因为深度为2会很快写满

  4. 当读位宽<写位宽时,写端口逻辑无需关心,同步FIFO时钟域异步FIFO读时钟为同一时钟,只要异步FIFO中有数据就分解之后写入到同步FIFO,所以读端口的empty信号只会在异步FIFO空之后置高,此时不必担心同步FIFO因为深度为2会很快读空

注意:

  1. 因为模块主体仍是异步FIFO,所以异步FIFO的“假满”和“假空”问题仍然存在,不影响功能
  2. FIFO实际容量总是比设定容量大,差值为两个小位宽(读/写)数据,这不影响功能

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

fifo读写位宽不一致,Verilog,Verilog,FIFO,异步FIFO,读写位宽不同,位宽变换,1024程序员节

信号说明:

分类 信号名称 输入/输出 说明
参数 DIN_WIDTH 输入数据位宽
DOUT_WIDTH 输出数据位宽
WADDR_WIDTH 写地址位宽,FIFO深度=2**WADDR_WIDTH
FWFT_EN First word fall-through输出模式使能,高电平有效
MSB_FIFO 1(默认值)表示高位先进先出,0表示低位先进先出
例如输入4bit,输出8bit,则首先输入的认为是8bit的高4位,
接着输入的认为是8bit的低4位。
同理,如果输入8bit,输出4bit,则首先输出的会是8bit的高4位,
接着输出的是8bit的低4位。
Vivado FIFO只有高位先进先出
FIFO写端口 din input FIFO数据输入
full output FIFO满信号
wr_en input FIFO写使能
wr_clk input FIFO写时钟
wr_rst input FIFO写复位
almost_full output FIFO快满信号,FIFO剩余容量<=1时置高
FIFO读端口 dout output FIFO数据输出
empty output FIFO空信号
rd_en input FIFO读使能
rd_clk input FIFO读时钟
rd_rst input FIFO读复位
almost_empty output FIFO快空信号,FIFO内数据量<=1时置高

注意:

  1. 信号的命名与Vivado中的FIFO IP核完全一致

  2. 复位均为高电平复位,与Vivado中的FIFO IP核保持一致

  3. 复位为异步复位,写复位和读复位可以共用一个信号,也可以分开

  4. FIFO深度通过WADDR_WIDTH来设置,所以FIFO的深度必然是2的指数,如8、16、32等

  5. DIN_WIDTH与DOUT_WIDTH的倍数关系必须是2的n次方,如2倍、4倍、8倍,不能是3倍、6倍

  6. WADDR_WIDTH必须≥3,且RADDR_WIDTH = WADDR_WIDTH + log2(DIN_WIDTH / DOUT_WIDTH)也必须≥3

    一种极限情况,DIN_WIDTH = 4,DOUT_WIDTH=16,WADDR_WIDTH=5,RADDR_WIDTH =5+log2(4/16)=3

  7. MSB_FIFO用于设定高位/低位先进先出,它和一般讲的FIFO大端和小端模式不是一个概念

三. 部分代码展示

//~ 如果读位宽大于写位宽,则需要组合数据,组合成一个数据就写入到读取侧FIFO中
if (DOUT_WIDTH >= DIN_WIDTH) begin
  wire clk = wr_clk;
  wire rst = wr_rst;
  wire wdata_almost_full;

  syncFIFO # (
    .DATA_WIDTH (DIN_WIDTH),
    .ADDR_WIDTH (1        ),
    .FWFT_EN    (1   )
  ) syncFIFO_inst (
    .din          (din        ),
    .wr_en        (wr_en      ),
    .full         (full       ),
    .almost_full  (wdata_almost_full),
    .dout         (wdata      ),
    .rd_en        (wdata_rd_en),
    .empty        (wdata_empty),
    .almost_empty (           ),
    .clk          (clk        ),
    .rst          (rst        )
  );

  assign almost_full = (wdata_almost_full && rdata_full) || full;


  localparam RADDR_WIDTH = $clog2(2**WADDR_WIDTH * DIN_WIDTH / DOUT_WIDTH);

  asyncFIFO # (
    .DATA_WIDTH (DOUT_WIDTH ),
    .ADDR_WIDTH (RADDR_WIDTH),
    .FWFT_EN    (FWFT_EN    )
  ) asyncFIFO_inst (
    .din          (rdata       ),
    .wr_en        (rdata_wr_en ),
    .full         (rdata_full  ),
    .almost_full  (            ),
    .wr_clk       (clk         ),
    .wr_rst       (rst         ),
    .dout         (dout        ),
    .rd_en        (rd_en       ),
    .empty        (empty       ),
    .almost_empty (almost_empty),
    .rd_clk       (rd_clk      ),
    .rd_rst       (rd_rst      )
  );

  // 在读取侧FIFO未满,而写入侧FIFO非空时去读取写入侧FIFO
  assign wdata_rd_en = ~rdata_full && ~wdata_empty;

  reg [DOUT_WIDTH-1:0] rdata_r;

  if (MSB_FIFO == 1) begin
    always @(posedge clk or posedge rst) begin
      if (rst)
        rdata_r <= 'd0;
      else if (wdata_rd_en)
        rdata_r <= {rdata_r[DOUT_WIDTH-DIN_WIDTH-1:0], wdata}; // 先进的为高位
      else
        rdata_r <= rdata_r;
    end
    assign rdata = {rdata_r[DOUT_WIDTH-DIN_WIDTH-1:0], wdata}; // 先进的为高位
  end
  else begin
    always @(posedge clk or posedge rst) begin
      if (rst)
        rdata_r <= 'd0;
      else if (wdata_rd_en)
        rdata_r <= {wdata, rdata_r[DOUT_WIDTH-1 : DIN_WIDTH]}; // 先进的为低位
      else
        rdata_r <= rdata_r;
    end
    assign rdata = {wdata, rdata_r[DOUT_WIDTH-1 : DIN_WIDTH]}; // 先进的为低位
  end

  localparam WDATA_RD_EN_CNT_MAX = DOUT_WIDTH / DIN_WIDTH - 1;
  reg [$clog2(WDATA_RD_EN_CNT_MAX+1)-1 : 0] wdata_rd_en_cnt;
  always @(posedge clk or posedge rst) begin
    if (rst)
      wdata_rd_en_cnt <= 'd0;
    else if (wdata_rd_en)
      wdata_rd_en_cnt <= wdata_rd_en_cnt + 1'b1;
    else
      wdata_rd_en_cnt <= wdata_rd_en_cnt;
  end
  
  assign rdata_wr_en = wdata_rd_en && wdata_rd_en_cnt == WDATA_RD_EN_CNT_MAX;
end

四. 功能仿真

仿真与之前异步FIFO的情形基本相同,只是要将读写数据位宽设为不一样。

testbench与之前异步FIFO基本相同,文末也有工程分享,各位同学可自行查看。

写入4bit,写入深度64,读出16bit,FWFT FIFO仿真,波形如下:

fifo读写位宽不一致,Verilog,Verilog,FIFO,异步FIFO,读写位宽不同,位宽变换,1024程序员节

可以看到,写入4个4bit数据后,empty在延迟两个读时钟上升沿后拉低,同时数据变为16’h0123,在读出之后,数据变为16‘h4567,读端口逻辑正常。Vivado FIFO IP的empty信号拉低延迟较大,但也保证了在empty拉低时数据是有效的。

fifo读写位宽不一致,Verilog,Verilog,FIFO,异步FIFO,读写位宽不同,位宽变换,1024程序员节

从上图可以看到,full信号和almost_full信号能正常置高,然后再读取一个数据后延迟两个写时钟上升沿一起拉低,因为读数据读一次就相当于4个写数据,所以almost_full和full是一起拉低的,这也是正确的。Vivado FIFO IP的实际深度比设定的64要大,这也是此IP的full比模块full更晚置高的原因。

fifo读写位宽不一致,Verilog,Verilog,FIFO,异步FIFO,读写位宽不同,位宽变换,1024程序员节

可以看到模块的读数据与Vivado FIFO IP的读数据是一样的,在最后,模块FIFO读出16’h0123后,empty置高,Vivado IP因为深度更大,empty更晚置高,可见读端口的行为是正确的。

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

  1. 更改读写时钟的频率,上述仿真是写时钟频率大于读时钟频率
  2. FWFT_EN改为0,注意同步修改Vivado FIFO的配置
  3. 验证写数据位宽>读数据位宽的情况

五. 工程分享

Verilog功能模块——读写位宽不同的异步FIFO,Vivado 2021.2工程。

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

8303

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

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

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


fifo读写位宽不一致,Verilog,Verilog,FIFO,异步FIFO,读写位宽不同,位宽变换,1024程序员节

徐晓康的博客持续分享高质量硬件、FPGA与嵌入式知识,软件,工具等内容,欢迎大家关注。文章来源地址https://www.toymoban.com/news/detail-790988.html

到了这里,关于Verilog功能模块——读写位宽不同的异步FIFO的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot中各个模块的功能

    Entity:实体层,数据库在项目中对应的类。放置一个个实体,及其相应的set、get方法。 Entity层中的类大多数是数据方面的,例如数据库中有负责登陆的User表(ID、UserName,Password),在Entity层就需要用private定义与数据库中一样的字段(ID、UserName,Password)以及这些字段

    2024年02月13日
    浏览(53)
  • 前端022_广告模块_修改功能

    需求分析 当点击 编辑 按钮后,弹出编辑窗口,并查询出分类相关信息进行渲染。修改后点击 确定 提交修改后的数据。 请求URL: /article/advert/{id} 请求方式: get 描述:通过广告 ID 查询数据接口 mock.js 配置:

    2024年02月05日
    浏览(87)
  • 前端013_标签模块_新增功能

    点击 新增 按钮后,对话框形式弹出新增窗口 输入类别信息后,点击 确定 提交表单数据; 新增和修改功能共用一个组件,我们将它作为子组件引入到列表查询父组件中,下面先将组件定义出来。 弹出功能参考:https://element.eleme.cn/#/zh-CN/component/dialog#zi-ding-yi-nei-rong el-dialog标

    2024年02月04日
    浏览(41)
  • 前端020_广告模块_列表功能

    广告模块主要针对博客门户广告处统一的进行管理。 首先开发模块中的列表功能,包含数据列表、分页。 请求URL: /article/advert/search 请求方式: post 描述: 广告分页列表 mock.js 配置: 带分页功能,每页显示20条

    2024年02月05日
    浏览(93)
  • 若依cloud(RuoYi-Cloud)新增业务模块和功能模块增删改查演示

    前言 看了几篇文章感觉都不太满意,索性自己来写一篇。 一、后端 后端新建业务模块流程大致如下: 看一下目录结构, business 就是我们自己的业务模块: 1.0 新建业务模块 就是在 ruoyi-module模块 下新建一个 springboot 工程模块,大家既然都学到cloud了,我相信这一步也不用多

    2024年02月17日
    浏览(56)
  • mesa库的模块功能和关系详述

    技术:mesa、OpenGL、meson 目录 前言:meson 构建系统 一、静态库列表(.a文件) 二、动态库列表(.so文件) 三、模块关系         在详述mesa模块功能和关系前,先来说下如何分析mesa的模块和关系。 很简单,熟悉mesa的构建系统:meson 。meson 是一个生成 ninja 文件的构

    2024年02月14日
    浏览(57)
  • KUKA机器人后台逻辑功能模块sps

    KUKA机器人的后台逻辑功能体现在其sps.sub文件中,其中功能和其他品牌的机器人一致(详细的说明解释可参考小编另一篇文章 FANUC机器人后台逻辑功能 ),这边对软plc,后台逻辑功能的具体解释不做过多的赘述,下面进入讲解的主题。 在workvisual软件中我们可以看到后台文件

    2024年04月13日
    浏览(58)
  • Flink流批一体计算(4):Flink功能模块

    目录 Flink功能架构 Flink输入输出 Flink功能架构 Flink是分层架构的分布式计算引擎,每层的实现依赖下层提供的服务,同时提供抽象的接口和服务供上层使用。 Flink 架构可以分为4层,包括Deploy部署层、Core核心层、API层和Library层 部署层:主要涉及Flink的部署模式。Flink支持多种

    2024年02月10日
    浏览(50)
  • C++功能模块6:打开视频文件并获取视频属性

    直接上代码 附:查询其他视频属性用到的宏 0:CV_CAP_PROP_POS_MSEC 1:CV_CAP_PROP_POS_FRAMES 2:CV_CAP_PROP_POS_AVI_RATIO 3:CV_CAP_PROP_FRAME_WIDTH 4:CV_CAP_PROP_FRAME_HEIGHT 5:CV_CAP_PROP_FPS 6:CV_CAP_PROP_FOURCC 7:CV_CAP_PROP_FRAME_COUNT 8:CV_CAP_PROP_FORMAT 9:CV_CAP_PROP_MODE 10:CV_CAP_PROP_BRIGHTNESS 11:CV_CAP_PROP_CO

    2023年04月15日
    浏览(47)
  • 新年快乐—数睿通2.0数据中台全新功能模块发布

    离上次发文已经有接近三个月了,这三个月主要在开发数睿通的数据生产模块,同时优化了一下数据集成,目前已经基本开发完毕了,集成了 Flink,Hadoop,可以在线开发 FlinkSql 作业任务,同时支持 Sql 任务开发,使平台初步具备了拉数,造数的能力,正值新年,在这里给大家

    2024年02月02日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包