当前位置: 首页 > news >正文

可传参配置的同步异步fifo

可传参配置的同步异步fifo相比普通fifo有许多优势:
1、代码复用性强
写一个模块就能满足 同步数据缓存 和 跨时钟域缓冲 的需求。避免写两份 FIFO 模块,降低维护成本。
不同场景下只要改 parameter ASYNC 就能复用。

2、设计灵活,可快速切换架构
设计早期可能不知道模块最终是不是跨时钟域。
用可配置 FIFO,可以在不改 RTL 代码的情况下,快速切换同步/异步模式。

3、减少错误,统一接口
同步/异步 FIFO 的 接口信号形式是相同的。
用参数配置后,接口保持一致,不会因为 FIFO 类型不同而修改上层代码。
有利于 模块化设计 和 接口标准化。

4、便于综合优化
综合工具在识别到同步 FIFO 时,可以直接推导为 单口 RAM + 逻辑。
在异步模式下,可以推导为 双口 RAM + 跨时钟同步逻辑。
一份代码 → 工具会根据参数推导出最优实现。

5、支持不同应用场景
同步 FIFO:适合数据缓存 / 流量调节,延迟小,逻辑简单。
异步 FIFO:适合跨时钟域数据传输,安全可靠,适合大规模数据搬运。
参数化模块 = 两种场景都能覆盖。

一、RAM块缓存

指定使用块RAM进行数据缓存;读写操作独立运行。

/*** Module: reg_ram** Description:*  例化块ram进行数据读写** Created: ** Author:*/`timescale 1ns / 1psmodule reg_ram#(parameter WIDTH = 32,   //数据位宽parameter SIZE = 3      //fifo深度
)
(input   clk_wr,input   wr_en,input   [SIZE - 1 : 0]  wr_addr,input   [WIDTH - 1 : 0] wr_data,input   clk_rd,input   rd_en,input   [SIZE - 1 : 0]  rd_addr,output  [WIDTH - 1 : 0] rd_data
);(* ram_style = "block" *) reg [WIDTH - 1 : 0] ram [0 : 2**SIZE-1];reg [WIDTH - 1 : 0] rd_data_d;// ram数据写always @(posedge clk_wr) beginif(wr_en) beginram[wr_addr] <= wr_data;endend// ram数据读always @(posedge clk_rd) beginif(rd_en) beginrd_data_d <= ram[rd_addr];endendassign rd_data = rd_data_d;endmodule

二、fifo调用顶层

/*** Module: fifo** Description:*  fifo wrapper** Created: ** Author:*/`timescale 1ns / 1psmodule fifo#(parameter ASYNC = 1,            //异步fifo开关parameter DATA_CNT_WR_EN = 1,   //写数据计数parameter DATA_CNT_RD_EN = 1,   //读数据计数parameter WIDTH = 32,           //数据位宽parameter DEPTH = 3              //fifo深度
)
(input  clk_wr,input  rstn_wr,input  wr_en,input  [WIDTH - 1 : 0] wr_data,output [DEPTH - 1 : 0] wr_cnt,output alfull,output full,output overflow,input  clk_rd,input  rstn_rd,input  rd_en,output [WIDTH - 1 : 0] rd_data,output [DEPTH - 1 : 0] rd_cnt,output alempty,output empty
);reg ram_wr_en, ram_wr_en;reg [DEPTH - 1 : 0] ram_rd_addr, ram_wr_addr;reg [WIDTH - 1 : 0] ram_wr_data, ram_rd_data;fifo_ctrl#(.ASYNC          (1  ), //异步fifo开关.DATA_CNT_WR_EN (1  ), //写数据计数.DATA_CNT_RD_EN (1  ), //读数据计数.WIDTH          (32 ), //数据位宽.DEPTH          (3  )  //fifo深度)fifo_ctrl_inst(.clk_wr             ( clk_wr        ),.rstn_wr            ( rstn_wr       ),    .wr_en              ( wr_en         ),.wr_data            ( wr_data       ),    .ram_wr_en          ( ram_wr_en     ),    .ram_wr_addr        ( ram_wr_addr   ),        .ram_wr_data        ( ram_wr_data   ),        .ram_data_wr_cnt    ( wr_cnt        ),            .alfull             ( alfull        ),.full               ( full          ),.overflow           ( overflow      ),    .clk_rd             ( clk_rd        ),.rstn_rd            ( rstn_rd       ),    .rd_en              ( rd_en         ),.rd_data            ( rd_data       ),    .ram_rd_en          ( ram_rd_en     ),    .ram_rd_addr        ( ram_rd_addr   ),        .ram_rd_data        ( ram_rd_data   ),        .ram_data_rd_cnt    ( rd_cnt        ),            .alempty            ( alempty       ),    .empty              ( empty         ));reg_ram#(.WIDTH  ( 32 ), //数据位宽.DEPTH  ( 3  )  //fifo深度)reg_ram_inst(.clk_wr     ( clk_wr        ),.wr_en      ( ram_wr_en     ),.wr_addr    ( ram_wr_addr   ),.wr_data    ( ram_wr_data   ),.clk_rd     ( clk_rd        ),.rd_en      ( ram_rd_en     ),.rd_addr    ( ram_rd_addr   ),.rd_data    ( ram_rd_data   ));endmodule

三、fifo的控制模块

将读写操作转换为对块ram的地址读写,同时将读写地址进行gary码转换进行空满计算等。

/*** Module: fifo_ctrl** Description:*  根据ASYNC常量值来控制async或sync fifo读写;*  提供剩余可写入空间的计算和剩余可读出数据的计算;** Created: ** Author:*/`timescale 1ns / 1psmodule fifo_ctrl#(parameter ASYNC = 1,            //异步fifo开关parameter DATA_CNT_WR_EN = 1,   //写数据计数parameter DATA_CNT_RD_EN = 1,   //读数据计数parameter WIDTH = 32,           //数据位宽parameter DEPTH = 3              //fifo深度
)
(input   clk_wr,input   rstn_wr,input   wr_en,input   [WIDTH - 1 : 0] wr_data,output  ram_wr_en,output  [DEPTH - 1 : 0] ram_wr_addr,output  [WIDTH - 1 : 0] ram_wr_data,output  [DEPTH - 1 : 0] ram_data_wr_cnt,output  alfull,output  full,output  overflow,input   clk_rd,input   rstn_rd,input   rd_en,input   [WIDTH - 1 : 0] rd_data,output  ram_rd_en,output  [DEPTH - 1 : 0] ram_rd_addr,output  [WIDTH - 1 : 0] ram_rd_data,output  [DEPTH - 1 : 0] ram_data_rd_cnt,output  alempty,output  empty
);reg [DEPTH - 1 : 0] fifo_wr_addr, fifo_wr_addr_inc1, fifo_wr_addr_inc2;reg [DEPTH - 1 : 0] fifo_wr_addr_gray, fifo_wr_addr_gray_d1, fifo_wr_addr_gray_d2;reg [DEPTH - 1 : 0] fifo_wr_addr_gray_inc1, fifo_wr_addr_gray_inc2;reg [DEPTH - 1 : 0] fifo_data_wr_cnt;reg [DEPTH - 1 : 0] fifo_rd_addr, fifo_rd_addr_inc1, fifo_rd_addr_inc2;reg [DEPTH - 1 : 0] fifo_rd_addr_gray, fifo_rd_addr_gray_d1, fifo_rd_addr_gray_d2;reg [DEPTH - 1 : 0] fifo_rd_addr_gray_inc1;reg [DEPTH - 1 : 0] fifo_data_rd_cnt;//写地址计算always @(posedge clk_wr) beginif(!rstn_wr) beginfifo_wr_addr <= 'h0;fifo_wr_addr_inc1 <= 'h0;fifo_wr_addr_inc2 <= 'h0;fifo_wr_addr_gray <= 'h0;overflow <= 0;endelse beginif(wr_en) beginif(!full) beginfifo_wr_addr <= fifo_wr_addr + 1;   //当前写入地址fifo_wr_addr_inc1 <= fifo_wr_addr + 2;fifo_wr_addr_inc2 <= fifo_wr_addr + 3;fifo_wr_addr_gray <= bin2gray(fifo_wr_addr + 1);    //当前写入地址的gray码endelse beginoverflow <= 1;endendif(!full) beginoverflow <= 0;endelse beginoverflow <= overflow;endendend// 读地址计算always @(posedge clk_rd) beginif(!rstn_rd) beginfifo_rd_addr <= 'h0;fifo_rd_addr_inc1 <= 'h0;fifo_rd_addr_inc2 <= 'h0;fifo_rd_addr_gray <= 'h0;endelse beginif(rd_en) beginif(!empty) beginfifo_rd_addr <= fifo_rd_addr + 1;   //当前读出地址fifo_rd_addr_inc1 <= fifo_rd_addr + 2;fifo_rd_addr_gray <= bin2gray(fifo_rd_addr + 1);    //当前读出地址的gray码endendendendgenerateif(ASYNC) begin : async_ctrl// 同步读地址always @(posedge clk_wr) beginif(!rstn_wr) beginfifo_rd_addr_gray_d1 <= 'h0;fifo_rd_addr_gray_d2 <= 'h0;endelse beginfifo_rd_addr_gray_d1 <= fifo_rd_addr_gray;fifo_rd_addr_gray_d2 <= fifo_rd_addr_gray_d1;endend// 同步写地址always @(posedge clk_rd) beginif(!rstn_wr) beginfifo_wr_addr_gray_d1 <= 'h0;fifo_wr_addr_gray_d2 <= 'h0;endelse beginfifo_wr_addr_gray_d1 <= fifo_wr_addr_gray;fifo_wr_addr_gray_d2 <= fifo_wr_addr_gray_d1;endendgenerate if(DATA_CNT_RD_EN) begin//写指针的格雷码减去读指针的格雷码即剩余可读出的数据数量assign fifo_data_rd_cnt = gray2bin(fifo_wr_addr_gray_d2) - gray2bin(fifo_rd_addr_gray);endelse beginassign fifo_data_rd_cnt = 0;endendgenerateendelse begin : sync_ctrlgenerate if(DATA_CNT_RD_EN) begin//写指针减去读指针即剩余可读出的数据数量assign fifo_data_rd_cnt = fifo_wr_addr - fifo_rd_addr;endelse beginassign fifo_data_rd_cnt = 0;endendgenerateendendgenerategenerate if(DATA_CNT_WR_EN) begin//总空间大小减去已使用的空间大小即剩余可写入的空间assign fifo_data_wr_cnt = 2**DEPTH - fifo_data_rd_cnt;endelse beginassign fifo_data_wr_cnt = 0;endendgenerate// I/O Connect //assign ram_wr_en = wr_en;assign ram_wr_data = wr_data;assign ram_wr_addr = fifo_wr_addr;assign ram_data_wr_cnt = fifo_data_wr_cnt;assign ram_rd_en = rd_en;assign ram_rd_data = rd_data;assign ram_rd_addr = fifo_rd_addr;assign ram_data_rd_cnt = fifo_data_rd_cnt;// 空满状态都可以用gray码计算// 满、将满通过wr地址判断assign alfull = (bin2gray(fifo_wr_addr_inc2) == fifo_rd_addr_gray_d2) ? 1 : 0;assign full = (bin2gray(fifo_wr_addr_inc1) == fifo_rd_addr_gray_d2) ? 1 : 0;// 空、将空通过rd地址判断assign alempty = (fifo_wr_addr_gray_d2 == bin2gray(fifo_rd_addr_inc1)) ? 1 : 0;assign empty = (fifo_wr_addr_gray_d2 == fifo_rd_addr_gray) ? 1 : 0;endmodule

四、仿真波形

同步fifo配置的仿真波形如下:
在这里插入图片描述

http://www.dtcms.com/a/341049.html

相关文章:

  • PyTorch 社区贡献 和 设计原则
  • Web 安全之延迟攻击(Delay Attack)详解
  • PyCharm2025无法启动Powershell.exe的解决办法
  • 发那科机器人程序调整功能
  • 好家园房产中介网后台管理完整(python+flask+mysql)
  • 【图论】拓扑排序
  • 48 C++ STL模板库17-容器9-关联容器-映射(map)多重映射(multimap)
  • Spring Boot如何配置Liveness和Readiness探针
  • 【Android】Activity 如何进行数据传输
  • java17学习笔记-switch总结
  • 使用 GraalVM Native Image 将 Spring Boot 应用编译为跨平台原生镜像:完整指南
  • linux 内核 - 内存管理单元(MMU)与地址翻译(一)
  • yolo_RK3588系列(三)
  • mac电脑软件左上角的关闭/最小化/最大化按钮菜单的宽度和高度是多少像素
  • ijkplayer Android 编译
  • strncpy 函数使用及其模拟实现
  • AI重塑软件测试:质量保障的下一站
  • 成本管控:餐饮利润的隐形守护者
  • Zemax光学设计输出3D
  • 4位量化:常规的线性层被替换成了4位线性层(48)
  • 酶 EC number 预测工具CLEAN的安装和使用
  • QT官方库头文件找不到(添加模块方法)
  • C++模板元编程:从SFINAE到Concepts的进化史
  • mac 搭建docker-compose,部署docker应用
  • AI on Mac, Your Way!全本地化智能代理,隐私与性能兼得
  • pcl求平面点云的边界凸包点
  • Frida Hook Android Activity生命周期全方法监控方案
  • 哈希:字母异位词分组
  • RHCA07-Linux跟踪工具及CPU调优
  • Linux I/O 多路复用实战:深入剖析 Select 与 Poll