【FIFO】Standard / FWFT FIFO设计实现(二)——异步时钟

news/2024/5/19 19:20:32 标签: fpga开发, SystemVerilog, AXI-Stream, fifo, Vivado

在这里插入图片描述

标准FIFO

   异步FIFO需要使用格雷码同步读写信号,可参考牛客异步FIFO例题,不同于牛客例题之处在于FIFO读空信号置位与FIFO最后一个有效数据输出在同一个周期,与Xilinx FIFO一致。核心代码如下:


    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_r = 'd0, wr_ptr_r = 'd0;
    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_gray_r = 'd0, wr_ptr_gray_r = 'd0;
    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_gray_cdc_r = 'd0, wr_ptr_gray_cdc_r = 'd0;
    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_gray_scdc_r = 'd0, wr_ptr_gray_scdc_r = 'd0;
    
    always_ff @(posedge m_clk) begin
        if (wr_en & ~wfull) begin
            wr_ptr_r <= wr_ptr_r + 1;
        end
    end 

    always_ff @(posedge s_clk) begin
        if (rd_en & ~rempty) begin
            rd_ptr_r <= rd_ptr_r + 1;
        end
    end

    always_ff @(posedge s_clk) begin 
        rd_ptr_gray_r[FIFO_DEPTH_WIDTH] <= rd_ptr_r[FIFO_DEPTH_WIDTH];
        for (integer i = 0; i < FIFO_DEPTH_WIDTH; i++) begin
            rd_ptr_gray_r[i] <= rd_ptr_r[i + 1] ^ rd_ptr_r[i];
        end
    end

    always_ff @(posedge m_clk) begin
        rd_ptr_gray_cdc_r <= rd_ptr_gray_scdc_r;
        rd_ptr_gray_scdc_r <= rd_ptr_gray_r;
    end

    always_ff @(posedge m_clk) begin
        wr_ptr_gray_r[FIFO_DEPTH_WIDTH] <= wr_ptr_r[FIFO_DEPTH_WIDTH];
        for (integer i = 0; i < FIFO_DEPTH_WIDTH; i++) begin
            wr_ptr_gray_r[i] <= wr_ptr_r[i + 1] ^ wr_ptr_r[i];
        end
    end

    always_ff @(posedge s_clk) begin
        wr_ptr_gray_cdc_r <= wr_ptr_gray_scdc_r;
        wr_ptr_gray_scdc_r <= wr_ptr_gray_r;
    end

    logic [FIFO_DEPTH_WIDTH : 0] rd_ptr_m_clk, wr_ptr_s_clk;
    
    assign wfull = (wr_ptr_r[FIFO_DEPTH_WIDTH] != rd_ptr_m_clk[FIFO_DEPTH_WIDTH]) && (wr_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0] == rd_ptr_m_clk[FIFO_DEPTH_WIDTH - 1 : 0]);
    assign rempty = rd_ptr_r == wr_ptr_s_clk;
    
    always_comb begin
        wr_ptr_s_clk[FIFO_DEPTH_WIDTH] = wr_ptr_gray_cdc_r[FIFO_DEPTH_WIDTH];
        for (integer i = FIFO_DEPTH_WIDTH - 1; i >= 0; i--) begin
            wr_ptr_s_clk[i] = wr_ptr_s_clk[i + 1] ^ wr_ptr_gray_cdc_r[i];
        end
    end

    always_comb begin
        rd_ptr_m_clk[FIFO_DEPTH_WIDTH] = rd_ptr_gray_cdc_r[FIFO_DEPTH_WIDTH];
        for (integer i = FIFO_DEPTH_WIDTH - 1; i >= 0; i--) begin
            rd_ptr_m_clk[i] = rd_ptr_m_clk[i + 1] ^ rd_ptr_gray_cdc_r[i];
        end
    end

    logic [TDATA_WIDTH - 1 : 0] ram[FIFO_DEPTH - 1 : 0];

    always_ff @(posedge m_clk) begin
        if (wr_en & ~wfull) begin
            ram[wr_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]] <= m_axis_tdata;
        end
    end

    always_ff @(posedge s_clk) begin
        if (rd_en & ~rempty) begin
            s_axis_tdata <= ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
        end
    end

图片

FWFT FIFO简单实现

   基于标准异步FIFO,引入FWFT机制。一种简单做法即将ram输出改为组合逻辑输出,这种方式实现的FWFT延时最低。

    always_comb begin
        // if (rd_en & ~rempty) begin
            s_axis_tdata = ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
        // end
    end

图片

FWFT FIFO优化

   然而,在FPGA中所有存储资源如(BRAM、URAM)均具有一个周期的读延时,在构造大容量fifo时,为了让综合工具将RAM综合为BRAM / URAM,更合适的做法为添加寄存器slice,这种方式会增加1个周期的延迟:

        initial rempty = 1'b1;
        
        assign wfull = sfifo_wfull;
        
        always @(posedge s_clk) begin
            if (~sfifo_rempty & (rempty | rd_en)) begin
                s_axis_tdata <= ram[rd_ptr_r[FIFO_DEPTH_WIDTH - 1 : 0]];
            end
        end
        
        assign sfifo_rd_en = (rempty | rd_en);
        
        always @(posedge s_clk) begin
            if (~sfifo_rempty) begin
                rempty <= 1'b0;
            end else if (rd_en) begin
                rempty <= 1'b1;
            end
        end     

图片

完整代码

完整工程代码可公众号回复ASYNC_FIFOs下载。


http://www.niftyadmin.cn/n/5462120.html

相关文章

一步步指导:在Chrome中安装Vue插件vue-devtools

一步步指导&#xff1a;在Chrome中安装Vue插件vue-devtools 1. 引言1.1. 关于Vue.js1.2. 为何使用vue-devtools 2. vue-devtools简介2.1. vue-devtools的功能2.2. 兼容性和需求 3. 如何在Chrome中安装vue-devtools3.1. 访问Chrome网上应用店3.2. 搜索并找到vue-devtools3.3. 安…

04---java面试八股文——spring-----注解-------10题

31、ComponentScan注解的作用 ComponentScan 注解用于指定 Spring 容器在启动时要扫描的基础包路径&#xff0c;以及要扫描的包路径下应该被自动注册为 Spring bean 的类。 具体来说&#xff0c;ComponentScan 注解的作用有以下几个方面&#xff1a; 组件扫描&#xff1a;Comp…

Vue系列-el挂载

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>el:挂载点</title> </head> <body&g…

Mybatis-特殊SQL的执行

1. 模糊查询 在MyBatis中进行模糊查询时&#xff0c;有以下三种常见的实现方式&#xff1a; 1.1. 错误示范 先来个准备操作&#xff0c;并做一个错误示例 根据姓名&#xff0c;模糊查询用户&#xff0c;(x小x) 更新数据表 SQLMapper.java package com.sakurapaid.mybatis3…

Chatgpt掘金之旅—有爱AI商业实战篇(二)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、前言&#xff1a; 成为一名商业作者是一个蕴含着无限可能的职业选择。在当下数字化的时代&#xff0c;作家们有着众多的平台可以展示和推广自己的作品。无论您是对写书、文…

每周编辑精选|免费使用 Sora 平替、在线运行 Python 基础教程、MCFEND 中国假新闻检测数据集上线

继 ChatGPT 后&#xff0c;OpenAI 又发布了爆炸级产品——Sora 文生视频模型&#xff0c;当其他模型还在努力突破几秒内的连贯性问题时&#xff0c;Sora 已经将视频时长拉到了 60s。不过&#xff0c;目前 Sora 模型仅对小部分研究人员和创意人士开放访问权限。 别担心&#xf…

ES学习日记(四)-------插件head安装和一些配套插件下载

前言 接上节,第三方插件选择了时间久,功能丰富,长得丑的head,head 插件在ES 5版本以前开箱即用非常简单&#xff0c;ES 5版本以后需要运行在node环境下&#xff0c;所以我们要先准备一下环境 一.安装Git yum -y install git 二.安装node 安装包位置node for linux下载 解压…

CAJViewer8.1下载地址及安装教程

CAJViewer是中国学术期刊&#xff08;CAJ&#xff09;全文数据库的专用阅读软件。CAJViewer是中国知识资源总库&#xff08;CNKI&#xff09;开发的一款软件&#xff0c;旨在方便用户在线阅读和下载CAJ数据库中的学术论文、期刊和会议论文等文献资源。 CAJViewer具有直观的界面…