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在线调试

上板测试

上板测试结果如下:


相关推荐
璞致电子2 小时前
基于 AD9361 (PZSDR‑P201Pro) 软件无线电实战综述:从板卡选型、硬件平台升级到 GNU Radio QPSK 完整收发链路
经验分享·嵌入式硬件·fpga开发·软件无线电·sdr·璞致电子
炎龙铠甲会合体4 小时前
从 SPEC 到上板:在 Zynq-7020 上用 RTL 手写一个 YOLO 卷积加速器(完整教程)
yolo·fpga开发·axi·芯片验证
FPGA小徐4 小时前
Vivado 按键消抖与复位模块代码修复详解:KEY_TOP、key、rst_gen 完整实战
fpga开发
炎龙铠甲会合体6 小时前
AXI2ICACHE— AXI4-Full 四路组相联指令 Cache 设计与 UVM 验证
fpga开发·面试·芯片验证
bingcheby6 小时前
FMQL15/20/45 (复旦微青龙系列 PSOC)新手使用说明
fpga开发
漫漫长远7 小时前
低功耗UPF介绍(一)
笔记·嵌入式硬件·学习·fpga开发
自小吃多18 小时前
【Verilog/FPGA】存储器(数组)
嵌入式硬件·fpga开发
szxinmai主板定制专家18 小时前
RK3588+FPGA异构架构|高速数据采集+边缘AI落地应用全解析
人工智能·嵌入式硬件·fpga开发·架构·zynq
明德扬1 天前
FPGA MIPI 多路视频聚合方案
fpga开发·mipi视频拼接·mipi多路拼接·mipi协议·mipi视频拼接方案·fpga mipi方案·mipi csi
XMAIPC_Robot1 天前
为什么大型储能需要边缘 AI 协调控制器?RK3588+FPGA 高速采集方案
人工智能·嵌入式硬件·fpga开发·arm+fpga·rk3588+fpga·协调控制器