IP核之FIFO

IP核之FIFO

FIFO简介

FIFO(First In First Out):即先进先出,FIFO一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存(如数据读写带宽不同步),或者高速异步数据的交互也即所谓的跨时钟域信号传递。FIFO只能顺序访问,而RAM则可以随机访问。

FIFO分类

同步FIFO:指读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作

异步FIFO:指读写时钟不一致,读写时钟是互相独立的

IP核端口

full:已满;almost_full:差一个数据满;Prog_full:自定义设置满阈值

FIFO读写时序图



实验任务

使用 Vivado 生成一个异步 FIFO,并实现以下功能:当FIFO为空时,向FIFO中写入数据,直至将FIFO写满后停止写操作;当FIFO为满时,从FIFO中读出数据,直到FIFO被读空后停止读操作。如:将FIFO设置的深度和宽度分别为256和8进行读写测试

系统框图


波形图

写模块时序

读模块时序

IP核配置


1.支持读写位宽一致

2.支持预读模式

3.使用Built-in FIFO原语

4.是否支持ECC校验

5.动态错误写入


fifo_wr写模块代码

复制代码
module fifo_wr(
    //mudule clock
    input                  wr_clk      ,  // 时钟信号
    input                  rst_n       ,  // 复位信号
    //FIFO interface       
    input                  wr_rst_busy ,  // 写复位忙信号
    input                  empty       ,  // FIFO空信号
    input                  almost_full ,  // FIFO将满信号
	output    reg          fifo_wr_en  ,  // FIFO写使能
    output    reg  [7:0]   fifo_wr_data   // 写入FIFO的数据
);

//reg define
reg        empty_d0;
reg        empty_d1;

//*****************************************************
//**                    main code
//*****************************************************

//因为empty信号是属于FIFO读时钟域的
//所以对empty打两拍同步到写时钟域下
always @(posedge wr_clk or negedge rst_n) begin
    if(!rst_n) begin
        empty_d0 <= 1'b0;
        empty_d1 <= 1'b0;
    end
    else begin
        empty_d0 <= empty;
        empty_d1 <= empty_d0;
    end
end

//对fifo_wr_en赋值,当FIFO为空时开始写入,写满后停止写
always @(posedge wr_clk or negedge rst_n) begin
    if(!rst_n) 
        fifo_wr_en <= 1'b0;
    else if(!wr_rst_busy) begin
        if(empty_d1)
            fifo_wr_en <= 1'b1;
        else if(almost_full)
            fifo_wr_en <= 1'b0;  
    end
    else
        fifo_wr_en <= 1'b0;
end  

//对fifo_wr_data赋值,0~254
always @(posedge wr_clk or negedge rst_n) begin
    if(!rst_n) 
        fifo_wr_data <= 8'b0;
    else if(fifo_wr_en && fifo_wr_data < 8'd254)
        fifo_wr_data <= fifo_wr_data + 8'b1;
    else
        fifo_wr_data <= 8'b0;
end

endmodule

fifo_rd写模块代码

复制代码
module fifo_rd(
    //system clock
    input               rd_clk      , //时钟信号
    input               rst_n       , //复位信号
    //FIFO interface
    input               rd_rst_busy , //读复位忙信号
    input        [7:0]  fifo_rd_data, //从FIFO读出的数据
    input               full        , //FIFO满信号
    input               almost_empty, //FIFO将空信号
    output  reg         fifo_rd_en    //FIFO读使能
);

//reg define
reg       full_d0;
reg       full_d1;

//*****************************************************
//**                    main code
//*****************************************************

//因为full信号是属于FIFO写时钟域的
//所以对full打两拍同步到读时钟域下
always @(posedge rd_clk or negedge rst_n) begin
    if(!rst_n) begin
        full_d0 <= 1'b0;
        full_d1 <= 1'b0;
    end
    else begin
        full_d0 <= full;
        full_d1 <= full_d0;
    end
end    
    
//对fifo_rd_en进行赋值,FIFO写满之后开始读,读空之后停止读
always @(posedge rd_clk or negedge rst_n) begin
    if(!rst_n) 
        fifo_rd_en <= 1'b0;
    else if(!rd_rst_busy) begin
        if(full_d1)
           fifo_rd_en <= 1'b1;
        else if(almost_empty)
           fifo_rd_en <= 1'b0; 
    end
    else
        fifo_rd_en <= 1'b0;
end

endmodule

顶层模块代码,例化fifo_rw,fifo_rd模块和IP核

复制代码
module ip_fifo(
    input    sys_clk ,  // 系统时钟信号
    input    sys_rst_n  // 系统复位信号
);

//wire define
wire         clk_50m       ;  // 50M时钟
wire         clk_100m      ;  // 100M时钟
wire         locked        ;  // 时钟锁定信号
wire         rst_n         ;  // 复位,低有效
wire         wr_rst_busy   ;  // 写复位忙信号
wire         rd_rst_busy   ;  // 读复位忙信号
wire         fifo_wr_en    ;  // FIFO写使能信号
wire         fifo_rd_en    ;  // FIFO读使能信号
wire  [7:0]  fifo_wr_data  ;  // 写入到FIFO的数据
wire  [7:0]  fifo_rd_data  ;  // 从FIFO读出的数据
wire         almost_full   ;  // FIFO将满信号
wire         almost_empty  ;  // FIFO将空信号
wire         full          ;  // FIFO满信号
wire         empty         ;  // FIFO空信号
wire  [7:0]  wr_data_count ;  // FIFO写时钟域的数据计数
wire  [7:0]  rd_data_count ;  // FIFO读时钟域的数据计数

//*****************************************************
//**                    main code
//*****************************************************

//通过系统复位信号和时钟锁定信号来产生一个新的复位信号
assign   rst_n = sys_rst_n & locked;

//例化PLL IP核
clk_wiz_0 clk_wiz_0 (
    // Clock out ports
    .clk_out1(clk_50m ),  // output clk_out1
    .clk_out2(clk_100m),  // output clk_out2
    // Status and control signals
    .locked  (locked  ),  // output locked
    // Clock in ports
    .clk_in1 (sys_clk )   // input clk_in1
);     
  
//例化FIFO IP核
fifo_generator_0  fifo_generator_0 (
    .rst           (~rst_n       ),  // input wire rst
    .wr_clk        (clk_50m      ),  // input wire wr_clk
    .rd_clk        (clk_100m     ),  // input wire rd_clk
    .wr_en         (fifo_wr_en   ),  // input wire wr_en
    .rd_en         (fifo_rd_en   ),  // input wire rd_en
    .din           (fifo_wr_data ),  // input wire [7 : 0] din
    .dout          (fifo_rd_data ),  // output wire [7 : 0] dout
    .almost_full   (almost_full  ),  // output wire almost_full
    .almost_empty  (almost_empty ),  // output wire almost_empty
    .full          (full         ),  // output wire full
    .empty         (empty        ),  // output wire empty
    .wr_data_count (wr_data_count),  // output wire [7 : 0] wr_data_count   
    .rd_data_count (rd_data_count),  // output wire [7 : 0] rd_data_count
    .wr_rst_busy   (wr_rst_busy  ),  // output wire wr_rst_busy
    .rd_rst_busy   (rd_rst_busy  )   // output wire rd_rst_busy
);

//例化写FIFO模块
fifo_wr  u_fifo_wr (
    .wr_clk        (clk_50m     ), // 写时钟
    .rst_n         (rst_n       ), // 复位信号
    .wr_rst_busy   (wr_rst_busy ), // 写复位忙信号
    .fifo_wr_en    (fifo_wr_en  ), // fifo写请求
    .fifo_wr_data  (fifo_wr_data), // 写入FIFO的数据
    .empty         (empty       ), // fifo空信号
    .almost_full   (almost_full )  // fifo将满信号
);

//例化读FIFO模块
fifo_rd  u_fifo_rd (
    .rd_clk       (clk_100m    ),  // 读时钟
    .rst_n        (rst_n       ),  // 复位信号
    .rd_rst_busy  (rd_rst_busy ),  // 读复位忙信号
    .fifo_rd_en   (fifo_rd_en  ),  // fifo读请求
    .fifo_rd_data (fifo_rd_data),  // 从FIFO输出的数据
    .almost_empty (almost_empty),  // fifo将空信号
    .full         (full        )   // fifo满信号
);

//写时钟域下ila
ila_0 u_ila_wr (
    .clk       (clk_50m      ), // input wire clk

    .probe0    (fifo_wr_en   ), // input wire [0:0]  probe0  
    .probe1    (fifo_wr_data ), // input wire [7:0]  probe1 
    .probe2    (almost_full  ), // input wire [0:0]  probe2 
    .probe3    (full         ), // input wire [0:0]  probe3 
    .probe4    (wr_data_count)  // input wire [7:0]  probe4
);

//读时钟域下ila
ila_1 u_ila_rd (
    .clk       (clk_100m     ), // input wire clk

    .probe0    (fifo_rd_en   ), // input wire [0:0]  probe0  
    .probe1    (fifo_rd_data ), // input wire [7:0]  probe1 
    .probe2    (almost_empty ), // input wire [0:0]  probe2 
    .probe3    (empty        ), // input wire [0:0]  probe3 
    .probe4    (rd_data_count)  // input wire [7:0]  probe4
);

endmodule 

FPGA激励文件(Testbench)编写,其用于验证FPGA设计功能正确性的测试脚本,通过模拟输入信号并检查输出响应,确保设计符合预期。

复制代码
`timescale 1ns / 1ps        //仿真单位/仿真精度

module tb_ip_fifo();

//parameter define
parameter  CLK_PERIOD = 20; //时钟周期 20ns

//reg define
reg     sys_clk;
reg     sys_rst_n;

//信号初始化
initial begin
    sys_clk = 1'b0;
    sys_rst_n = 1'b0;
    #200
    sys_rst_n = 1'b1;
    //模拟按下复位
    #10000 ;
    sys_rst_n = 0; 
    #160    ; 
    sys_rst_n = 1;
end

//产生时钟
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;

ip_fifo  u_ip_fifo (
     .sys_clk      (sys_clk  ), 
     .sys_rst_n    (sys_rst_n)
 );

endmodule
相关推荐
坏孩子的诺亚方舟1 天前
FPGA系统架构设计实践10_时钟网络
fpga·xilinx·时钟网络
XINVRY-FPGA2 天前
XC2C256-7VQG100I Xilinx CoolRunner-II CPLD FPGA
单片机·嵌入式硬件·fpga开发·硬件工程·dsp开发·fpga
XINVRY-FPGA3 天前
EP1C6T144I7N Altera Cyclone FPGA
嵌入式硬件·fpga开发·硬件工程·dsp开发·fpga
欢鸽儿5 天前
Vitis】Linux 下彻底清除启动界面 Recent Workspaces 历史路径
linux·嵌入式硬件·fpga
HIZYUAN5 天前
AI时代,如何利用FPGA在无人机视觉等方面进行快速应用
stm32·单片机·fpga开发·视觉检测·无人机·fpga·光端机
XINVRY-FPGA6 天前
EP4CE30F23I7N Altera Cyclone IV E SRAM FPGA
嵌入式硬件·fpga开发·云计算·硬件工程·信息与通信·信号处理·fpga
XINVRY-FPGA7 天前
XC3S1000-4FGG320I Xilinx AMD Spartan-3 SRAM-based FPGA
嵌入式硬件·机器学习·计算机视觉·fpga开发·硬件工程·dsp开发·fpga
Troke8 天前
Xilinx FIFO IP中两种读模式的简单分析
fpga开发·fifo
stay_cloud9 天前
HDMI字符显示 —— 基于Genesys2
fpga·hdmi·genesys2