同步FIFO

本文介绍了同步FIFO的工作原理,包括时序和空满判断,以及使用Verilog语言编写的代码实例。通过仿真分析了不同操作模式下的行为。适合FPGA学习者理解FIFO在设计中的应用。
摘要由CSDN通过智能技术生成

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


一、概述

FIFO

📄FIFO(First In First Out)是一种先进先出的数据缓存器,先进入FIFO的数据会先输出。FIFO通常可分为同步FIFO和异步FIFO两类。

FIFO 设计的关键:产生可靠的 FIFO 读写指针和生成 FIFO“空”/“满”状态标志。

FIFO 本质上是由 (伪双口)RAM 加读写控制逻辑构成的。
在这里插入图片描述

FIFO的优点:没有读写地址线,顺序写入、读出数据,数据地址由内部读写指针自动+1完成,使用起来简单方便。
FIFO的缺点:不能像RAM或ROM那样读取或写入某个指定的地址。

同步FIFO

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

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

二、工作原理

2.1 工作时序

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

在这里插入图片描述

2.2 空满判断

📄FIFO空满判断主要有计数器法高位扩展法两种,这里先说明计数器法。

计数器法:添加一个计数器data_cnt指示FIFO中数据的个数:

  • 当写使能有效且FIFO非满时data_cnt+1;
  • 当读使能有效且FIFO非空时data_cnt-1;
  • 当读写使能同时有效时data_cnt不变;
  • data_cnt==0时,FIFO读空,产生空标志;
  • data_cnt==FIFO深度时,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

四、仿真

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

`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

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

  • 25
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
FPGA 同步 FIFO 是一种用于在 FPGA 设备中实现数据缓冲和数据转移的组件。它由一个读取指针和一个写入指针组成,可以实现读写操作的同步和互斥。 使用 FPGA 同步 FIFO 的一个常见场景是在不同频率的数据传输之间进行数据缓冲和同步。当输入以不同频率产生数据时,为了保证数据的可靠传输和处理,可以使用同步 FIFO 来缓冲输入数据,并在输出端以相同或不同的频率读取数据。 FPGA 同步 FIFO 的实现可以采用 FPGA 内部的存储单元,如 Block RAM 或 Distributed RAM。写入操作将数据写入 FIFO 的写入指针所指向的位置,并将写入指针前移。读取操作将数据从 FIFO 的读取指针所指向的位置读取出来,并将读取指针前移。读写指针的移动是同步的,以保证数据的正确性和完整性。 FPGA 同步 FIFO 的大小通常取决于数据传输的需求和 FPGA 设备的资源限制。可以根据数据产生和处理的速度来确定 FIFO 的大小,并且需要根据需要调整读写指针的顺序和移动策略,以满足数据的传输需求。 尽管 FPGA 同步 FIFO 在数据传输中起到了重要的作用,但同时也会增加设计的复杂性和资源消耗。在使用 FPGA 同步 FIFO 时,需要注意处理数据的同步和互斥问题,以及避免出现数据丢失、溢出等异常情况。 总之,FPGA 同步 FIFO 是一种用于实现数据缓冲和转移的组件,在不同频率的数据传输中发挥了关键作用。它可以通过读写指针的同步移动来保证数据的可靠性和完整性,并且可根据需求和硬件资源进行灵活调整。但同时也需要注意处理同步和互斥问题,以确保数据的正确传输。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hi小瑞同学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值