FPGA上板项目(四)——FIFO测试

目录


实验内容

  • 理解 FIFO 原理
  • 调用 FIFO IP 核完成数据读写

实验原理

  • FIFO:First In First Out,先入先出式数据缓冲器,用来实现数据先入先出的读写方式。可分类为同步 FIFO 和异步 FIFO,读写时钟相同即为同步 FIFO,读写时钟不同即为异步 FIFO。
  • FIFO 框图:
  • FIFO 端口定义与说明:
写端口 说明 读端口 说明
wr_clk 写时钟 rd_clk 读时钟
wr_en 写使能 rd_en 读使能
din 写入的数据 dout 读出的数据
full 满信号 empty 空信号
almost_full 将满信号 almost_empty 将空信号
prog_full 可配置满信号 prog_empty 可配置空信号

full:当 FIFO 已满时,满信号输出高电平,此时的写入操作失效。

almost_full:当 FIFO 差一个数据即满时,将满信号输出高电平,此时只可再进行一次写入操作。

prog_full:用户可自定义阈值,若 FIFO 存储的数据量超过阈值,可配置满信号输出高电平。

FIFO IP 核

  • 添加 FIFO Generator IP 核:IP Catalog -> FIFO Generator
  • Basic 界面
    • Fifo Implementation:用来设置同步/异步,以及使用的资源,常用为 Independent Clocks Block RAM
    • Synchronization Stages:跨时钟域逻辑的同步器级数,保持默认即可。数值 2 代表,empty 信号会在 FIFO 成功写入数据后的 2 个读时钟周期后拉低。
  • Native Ports 界面
    • Read Mode:Standard FIFO 标准模式,输出数据延迟读使能一拍,First Word Fall Through 预读模式,输出数据与读使能同步。
    • Data Port Parameters:调整数据位宽和深度
    • ECC:数据校验时开启,这里默认不开启
    • Output Registers:输出寄存器,可以改善 FIFO 时序,但输出会延迟一拍
    • Initialization:设置复位信号,Enable Reset Synchronization 启用同步复位
    • Enable Safety Circuit:启用安全电路,复位信号至少要保持八个时钟周期(以慢时钟为准)的有效,且在复位后至少要经过六十个时钟周期(以慢时钟为准)后,才能对 FIFO 进行写数据操作。
    • 其余保持默认,最后会统计出输出延迟 Read Latency
  • Status Flags 界面:可配置标志位信号,有需求时启用
  • Data Counts 界面:可配置读写数据计数,有需求时启用

时序绘制

  • 实验按照异步 FIFO 进行设计,使用 100MHz 时钟信号作为写时钟,50MHz 时钟信号作为读时钟。
  • 复位后,由于安全电路的存在,慢时钟(读时钟)计数六十拍后才可启动 FIFO,启动后将标志位 state 信号拉高。
  • 启动后,若 FIFO 未满,即 full 信号为低电平时,则拉高 wr_en,开始写数据;启动后,若 FIFO 不空,即 empty 信号为低电平,则拉高 rd_en,开始读数据。

HDL 代码

c 复制代码
`timescale 1ns / 1ps
module FIFO(
    input wire sys_clk_p,
    input wire sys_clk_n,
    input wire rst_n
);
        
/**********************************************
*********** 例化PLL
**********************************************/
    wire sys_clk_100M;
    wire sys_clk_50M;
    wire locked;
    clk_wiz_0 inst_clk(
        // Clock out ports
        .clk_out1(sys_clk_100M),     // output clk_out1
        .clk_out2(sys_clk_50M),     // output clk_out2
        // Status and control signals
        .reset(1'b0), // input reset
        .locked(locked),       // output locked
       // Clock in ports
        .clk_in1_p(sys_clk_p),    // input clk_in1_p
        .clk_in1_n(sys_clk_n)    // input clk_in1_n
    );
    
/**********************************************
*********** 例化FIFO
**********************************************/
    reg [15:0] din;
    wire wr_en;
    wire rd_en;
    wire [15:0] dout;
    wire full;
    wire empty;
    wire wr_rst_busy;
    wire rd_rst_busy;
    fifo_0 inst_fifo (
      .rst(!rst_n),                  // input wire rst
      .wr_clk(sys_clk_100M),            // input wire wr_clk
      .rd_clk(sys_clk_50M),            // input wire rd_clk
      .din(din),                  // input wire [15 : 0] din
      .wr_en(wr_en),              // input wire wr_en
      .rd_en(rd_en),              // input wire rd_en
      .dout(dout),                // output wire [15 : 0] dout
      .full(full),                // output wire full
      .empty(empty),              // output wire empty
      .wr_rst_busy(wr_rst_busy),  // output wire wr_rst_busy
      .rd_rst_busy(rd_rst_busy)  // output wire rd_rst_busy
    );
      
/**********************************************
*********** 信号赋值
**********************************************/  
    // 赋值启动标志位,state为高时代表可以开始FIFO读写
    reg state;
    reg [7:0] start_cnt;
    always@(posedge sys_clk_50M) begin
        if(!rst_n) begin
            start_cnt <= 8'b0;
        end
        else if(state) begin
            start_cnt <= 8'b0;
        end
        else begin
            start_cnt <= start_cnt + 8'b1;
        end
    end
    always@(posedge sys_clk_50M) begin
        if(!rst_n) begin
            state <= 1'b0;
        end
        else if(start_cnt == 8'd60) begin
            state <= 1'b1;
        end
    end

    // 组合逻辑赋值wr_en,当state为1时,wr_en的取值与full信号相反
    assign wr_en = (state == 1'b1) ? ~full : 1'b0;
    
    // 赋值din
    always@(posedge sys_clk_100M) begin
        if(!rst_n) begin
            din <= 16'b0;
        end
        else if(wr_en) begin
            din <= din + 16'b1;
        end
    end
    
    // 组合逻辑赋值rd_en,当state为1时,rd_en的取值与empty信号相反
    assign rd_en = (state == 1'b1) ? ~empty : 1'b0;
    
/**********************************************
*********** 例化ILA
**********************************************/ 
    ila_0 inst_ila (
        .clk(sys_clk_100M), // input wire clk
        .probe0(state), // input wire [0:0]  probe0  
        .probe1(wr_en), // input wire [0:0]  probe1 
        .probe2(din), // input wire [15:0]  probe2 
        .probe3(rd_en), // input wire [0:0]  probe3 
        .probe4(dout) // input wire [15:0]  probe4
    );

endmodule

仿真

testbench 代码:

c 复制代码
`timescale 1ns / 1ps
module tb_FIFO();
    
/**********************************************
*********** 实例化模块
**********************************************/
    reg sys_clk_p;
    wire sys_clk_n;
    reg rst_n;
    FIFO tb_FIFO(
        .sys_clk_p(sys_clk_p),
        .sys_clk_n(sys_clk_n),
        .rst_n(rst_n)
    );
    
/**********************************************
*********** 初始化 clk、rst
**********************************************/
    // 初始化 clk
    assign sys_clk_n = ~sys_clk_p;
    initial begin
        sys_clk_p = 1;
        forever #2.5 sys_clk_p = ~sys_clk_p;   
    end
    
    // 初始化 rst
    initial begin
        rst_n = 0;
        #302.5;
        rst_n = 1;
    end
endmodule

仿真时序图:

  • 当 start_cnt 计数到 60 后,state 标志位置一,开始启动 FIFO
  • 当 wr_en 置高,FIFO 开始写入数据,当 rd_en 置高,FIFO 开始读出数据,输出的数据延迟 rd_en 一拍
  • 当 FIFO 存满时,full 信号被拉高,等待数据被读取后, full 信号被拉低,即可再次写入数据

综合实现

添加管脚和时序约束后,run synthesis 以及 run implementation,具体步骤可参考:FPGA上板项目(一)------点灯熟悉完整开发流程、ILA在线调试

上板测试

上板测试结果如下:


相关推荐
nanxl130 分钟前
FPGA-DDS信号发生器
fpga开发·verilog·vivado
黄埔数据分析2 小时前
RecoNIC 入门:SmartNIC 上支持 RDMA 的计算卸载-FPGA-智能网卡-AMD-Xilinx
fpga开发
nanxl14 小时前
FPGA-数字时钟
fpga开发·verilog·vivado
尤老师FPGA18 小时前
LVDS系列9:Xilinx 7系可编程输入延迟(二)
单片机·嵌入式硬件·fpga开发
内有小猪卖21 小时前
时序约束 记录
fpga开发
Cao1234567893211 天前
FPGA时钟设计
fpga开发
JNTeresa1 天前
锁存器知识点详解
fpga开发
Cao1234567893211 天前
FPGA基础之基础语法
fpga开发
一大Cpp1 天前
通过Quartus II实现Nios II编程
fpga开发
7yewh1 天前
Verilog 语法 (二)
fpga开发