FPGA中FIFO的应用(一)——同步FIFO设计


⭐️作者简介:小瑞同学,主要学习FPGA、信号处理、通信等。
🍎个人主页:小瑞同学的博客主页
🌻个人信条:越努力,越幸运!
⏰日期:2023.12.1
📖文章内容概述:介绍了同步FIFO的概念和工作原理,并使用Verilog代码模拟实现了同步FIFO,最后对其进行仿真。


连载系列:FPGA中FIFO的应用
完整工程已上传至CSDN下载链接


1.同步FIFO简介

1.1 概述

📄FIFO,即First In First Out,是一种常用的存储结构。正如其名,先进入FIFO的数据会先输出。FIFO通常可分为同步FIFO和异步FIFO两类,本篇文章我们先来介绍同步FIFO。

📄同步FIFO是指其读写受同一时钟控制,一般用于数据的缓冲、传输速率匹配等。

FIFO的优点:没有读写地址线,顺序读入数据,顺序读出数据,使用起来简单方便。
FIFO的缺点:不能像RAM或ROM那样读取或写入某个指定的地址。

1.2 主要参数

参数意义
时钟读写采用同一时钟
FIFO的宽度FIFO一次读写的数据位宽
FIFO的深度FIFO中存储的数据个数
空标志FIFO已空时发出空信号,以阻止读操作继续读取无效数据
满标志FIFO已满时发出满信号,以阻止写操作继续向FIFO中写数据而导致FIFO溢出

2.工作原理

📄同步FIFO实现起来相对简单,关键在于如何产生空满标志信号。

2.1 工作时序

  • 在写使能有效且FIFO非满时,对FIFO进行写;写地址由自增产生,将数据写入该地址 ,初始为0。
  • 在读使能有效且FIFO非空时,对FIFO进行读;读地址由自增产生,将数据从该地址读出,初始为0。

在这里插入图片描述

2.2 空满判断

📄FIFO空满判断主要有计数器法高位扩展法两种,这里我们先介绍计数器法,下篇文章介绍高位扩展法。

计数器法就是在程序中添加一个计数器data_cnt

  • 当写使能有效且FIFO非满时data_cnt+1;
  • 当读使能有效且FIFO非空时data_cnt-1;
  • data_cnt==0时,FIFO读空,产生空标志;
  • data_cnt==FIFO深度时,FIFO写满,产生满标志。

3.verilog代码

了解同步FIFO的工作原理后,代码思路就有了,程序如下:

`timescale 1ns / 1ps

module fifo_syn
#(parameter FIFO_WIDTH=8,
  parameter FIFO_DEPTH=16)

(
    input                        clk    ,
    input                        rstn   ,
    input                        wr_en  ,
    input                        rd_en  ,
    input       [FIFO_WIDTH-1:0] din    ,
    output                       empty  ,
    output                       full   ,
    output reg  [FIFO_WIDTH-1:0] dout
    );

reg [$clog2(FIFO_DEPTH)-1:0] wr_addr;
reg [$clog2(FIFO_DEPTH)-1:0] rd_addr;
reg [$clog2(FIFO_DEPTH):0] data_cnt;//由于FIFO赋值和地址自增相差1周期,需多计数1周期

reg [FIFO_WIDTH-1:0] fifo [0:FIFO_DEPTH-1];

assign empty=(data_cnt==0) ? 1'b1 : 1'b0;
assign full=(data_cnt==FIFO_DEPTH) ? 1'b1: 1'b0;
//写FIFO
always@(posedge clk or negedge rstn)begin
    if(!rstn)begin
        wr_addr<='b0;       
    end
    else if(wr_en&&!full)begin
        wr_addr<=wr_addr+1'b1;
        fifo[wr_addr]<=din;        
    end
    else begin
        wr_addr<=wr_addr;
    end
end

//读FIFO
always@(posedge clk or negedge rstn)begin
    if(!rstn)begin
        rd_addr<='b0;
        dout<='b0;
    end
    else if(rd_en&&!empty)begin
        rd_addr<=rd_addr+1'b1;
        dout<=fifo[rd_addr];        
    end
    else begin
        rd_addr<=rd_addr;
    end
end
//数据状态变化
always@(posedge clk or negedge rstn)begin
    if(!rstn)begin
        data_cnt<='b0;
    end
    else begin
        case({wr_en,rd_en})
            2'b10:
            if(data_cnt!=FIFO_DEPTH)//空满时计数器不变
                data_cnt<=data_cnt+1'b1;
            2'b01:
            if(data_cnt!=0)
                data_cnt<=data_cnt-1'b1;
            default:
                data_cnt<=data_cnt; 
        endcase
    end
end
endmodule

4.仿真分析

4.1 参考testbench文件

📄仿真中主要是产生读写使能信号和要写入的数据。为方便起见,这里我们编写几个简单的任务来产生读写使能信号,为保证数据稳定,在时钟的下降沿赋值。

{$random}%(2^FIFO_WIDTH)表示产生范围为0—2 ^ FIFO_WIDTH-1的随机数。
有关$random更详细的用法,可参考这篇文章: $random的用法详解

`timescale 1ns / 1ps

module tb();

parameter FIFO_WIDTH=8;
reg clk;
reg rstn;
reg wr_en;
reg rd_en;
reg [FIFO_WIDTH-1:0] din;
wire empty;
wire full;
wire [FIFO_WIDTH-1:0] dout;

initial begin
    clk=1'b0;
    rstn=1'b0;
    wr_en=1'b0;
    rd_en=1'b0;
    din='b0;
    #15;
    rstn=1'b1;
    repeat(20)begin
        wr_only;
    end
    repeat(20)begin
        rd_only;
    end
    repeat(5)begin
        wr_only;
    end
    repeat(5)begin
        wr_rd;
    end
end

always #10 clk=~clk;
//只写的任务
task wr_only;
begin
    @(negedge clk)begin
        wr_en=1'b1;
        rd_en=1'b0;
        din={$random}%(2^FIFO_WIDTH);//生成0~2^FIFO_WIDTH-1的随机数
    end
end
endtask
//只读的任务
task rd_only;
begin
    @(negedge clk)begin
        rd_en=1'b1;
        wr_en=1'b0;
    end
end
endtask
//读写的任务
task wr_rd;
begin
    @(negedge clk)begin
        rd_en=1'b1;
        wr_en=1'b1;
        din={$random}%(2^FIFO_WIDTH);
   end 
end
endtask
fifo_syn fifo_syn_u
(
    . clk    (clk),
    . rstn   (rstn),
    . wr_en  (wr_en),
    . rd_en  (rd_en),
    . din    (din),
    . empty  (empty),
    . full   (full),
    . dout   (dout)
    );
endmodule

4.2 仿真结果

写FIFO:
在这里插入图片描述
读FIFO:
在这里插入图片描述
同时读写:
在这里插入图片描述


❤️如果觉得文章对你有所帮助的话,别忘了点个收藏哦~
❤️更多优质内容可浏览本人主页👇,期待再次与你相遇!
🎉🎉🎉🎉🎉🎉小瑞同学的博客主页🎉🎉🎉🎉🎉🎉

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hi小瑞同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值