查看: 923|回复: 0

[评测分享] 【PGL22G开发板】+IP核之FIFO

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-19 21:11
  • 签到天数: 66 天

    连续签到: 1 天

    [LV.6]常住居民II

    发表于 2023-5-7 19:04:19 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 feifeiz 于 2023-5-7 19:20 编辑

    一、前言

    在上一篇文章中学习了串口发送与接收,通过上位机下发数据给开发板,然后通过开发板又将数据返回,同时在串口接收模块中通过特定的协议点亮LED。本片文章继续学习如何在开发板上实现FIFO。
    二、FIFO简介

    FIFO 的英文全称是First In First Out,即先进先出。一般指的是对数据的存储具有先进先出特性的一个缓存器。常见的应用场景,在典型的串口设计中,串口的发送缓冲区只有一个字节,串口发送一次就需要CPU执行一次,当串口发送的数据比较多的时候,就会频繁的使用CPU,从而导致CPU的执行效率低下,通过使用FIFO的方法,使FIFO先工作完成后CPU才介入。在FPGA的FIFO常被用于数据的缓存,或者高速异步数据的交互也即所谓的跨时钟域信号传递。它与 FPGA 内部的 RAM 和 ROM 的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像 RAM 和 ROM 那样可以由地址线决定读取或写入某个指定的地址。

    同时根据FIFO的时钟域,将FIFO分成了同步FIFO和异步FIFO,他们的区别在于读写时是否使用的是同一个时钟,同步FIFO主要用于同步时钟下的数据缓存,异步FIFO主要应用于跨时域的数据型号传递,入单片机与FPGA通信过程中,使用的不是同一个时钟,通过异步FIFO的方式实现数据信号的传递,还有可能是不同位宽之间的数据传递。
    三、实验目标
    通过新建FIFO IP核,根据FIFO的状态进行读写数据,当FIFO为空时,向FIFO中写入数据,写满为止,完成FIFO的写入后,将写入的数据读取的出来。
    四、程序设计
    总体设计,共四个模块,FIFO写入模块,FIFO读模块,顶层设计模块以及FIF IP核,总体实现框图如下.
    1.png
    在顶层模块设计中,例化FIFO IP核,FIFO写模块,FIFO读模块
    module ip_fifo(
    input sys_clk , // 时钟信号
    input sys_rst_n // 复位信号
    );

    //wire define
    wire fifo_wr_en /* synthesis syn_keep=1 */;// FIFO写使能信号
    wire fifo_rd_en /* synthesis syn_keep=1 */;// FIFO读使能信号
    wire [7:0] fifo_din /* synthesis syn_keep=1 */;// 写入到FIFO的数据
    wire [7:0] fifo_dout /* synthesis syn_keep=1 */;// 从FIFO读出的数据
    wire almost_full /* synthesis syn_keep=1 */;// FIFO将满信号
    wire almost_empty /* synthesis syn_keep=1 */;// FIFO将空信号
    wire fifo_full /* synthesis syn_keep=1 */;// FIFO满信号
    wire fifo_empty /* synthesis syn_keep=1 */;// FIFO空信号
    wire [7:0] fifo_wr_data_count /* synthesis syn_keep=1 */;// FIFO写时钟域的数据计数
    wire [7:0] fifo_rd_data_count /* synthesis syn_keep=1 */;// FIFO读时钟域的数据计数

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

    reg almost_empty_d0 ; //almost_empty 延迟一拍
    reg almost_empty_d1 ; //almost_empty 延迟两拍
    reg almost_empty_syn ; //almost_empty 延迟三拍
    reg almost_full_d0 ; //almost_full 延迟一拍
    reg almost_full_d1 ; //almost_full 延迟两拍
    reg almost_full_syn ; //almost_full 延迟三拍

    //因为 almost_empty 信号是属于FIFO读时钟域的
    //所以要将其同步到写时钟域中
    always@( posedge sys_clk ) begin
    if( !sys_rst_n ) begin
    almost_empty_d0 <= 1'b0 ;
    almost_empty_syn <= 1'b0 ;
    almost_empty_d1 <= 1'b0 ;
    end
    else begin
    almost_empty_d0 <= almost_empty ;
    almost_empty_d1 <= almost_empty_d0 ;
    almost_empty_syn <= almost_empty_d1 ;
    end
    end

    //因为 almost_full 信号是属于FIFO读时钟域的
    //所以要将其同步到写时钟域中
    always@( posedge sys_clk ) begin
    if( !sys_rst_n ) begin
    almost_full_d0 <= 1'b0 ;
    almost_full_syn <= 1'b0 ;
    almost_full_d1 <= 1'b0 ;
    end
    else begin
    almost_full_d0 <= almost_full ;
    almost_full_d1 <= almost_full_d0 ;
    almost_full_syn <= almost_full_d1 ;
    end
    end

    fifo_generator_0 u_fifo_generator_0 (
    .wr_clk (sys_clk ), // input
    .wr_rst (~sys_rst_n ), // input
    .wr_en (fifo_wr_en ), // input
    .wr_data (fifo_din ), // input [7:0]
    .wr_full (fifo_full ), // output
    .wr_water_level (fifo_wr_data_count), // output [8:0]
    .almost_full (almost_full ), // output
    .rd_clk (sys_clk ), // input
    .rd_rst (~sys_rst_n ), // input
    .rd_en (fifo_rd_en ), // input
    .rd_data (fifo_dout ), // output [7:0]
    .rd_empty (fifo_empty ), // output
    .rd_water_level (fifo_rd_data_count), // output [8:0]
    .almost_empty (almost_empty ) // output
    );

    //例化写FIFO模块
    fifo_wr u_fifo_wr(
    .clk ( sys_clk ), // 写时钟
    .rst_n ( sys_rst_n ), // 复位信号

    .fifo_wr_en ( fifo_wr_en ), // fifo写请求
    .fifo_wr_data ( fifo_din ), // 写入FIFO的数据
    .almost_empty ( almost_empty_syn ), // fifo空信号
    .almost_full ( almost_full_syn ) // fifo满信号
    );

    //例化读FIFO模块
    fifo_rd u_fifo_rd(
    .clk ( sys_clk ), // 读时钟
    .rst_n ( sys_rst_n ), // 复位信号
    .fifo_rd_en ( fifo_rd_en ), // fifo读请求
    .fifo_dout ( fifo_dout ), // 从FIFO输出的数据
    .almost_empty ( almost_empty_syn ), // fifo空信号
    .almost_full ( almost_full_syn ) // fifo满信号
    );

    Endmodule
    写模块,fifo_wr 模块是通过一个不断进行状态循环的小状态机,如果检测到 FIFO 为空,则先延时 10拍。如果写满,则回到状态 0,即等待 FIFO 被读空,以进行下一轮的写操作。
    module fifo_wr(
    //mudule clock
    input clk , // 时钟信号
    input rst_n , // 复位信号
    //FIFO interface
    input almost_empty, // FIFO将空信号
    input almost_full , // FIFO将满信号
    output reg fifo_wr_en , // FIFO写使能
    output reg [7:0] fifo_wr_data // 写入FIFO的数据
    );

    //reg define
    reg [1:0] state ; //动作状态
    reg [3:0] dly_cnt ; //延迟计数器
    //*****************************************************
    //** main code
    //*****************************************************
    //向FIFO中写入数据
    always @(posedge clk ) begin
    if(!rst_n) begin
    fifo_wr_en <= 1'b0;
    fifo_wr_data <= 8'd0;
    state <= 2'd0;
    dly_cnt <= 4'd0;
    end
    else begin
    case(state)
    2'd0: begin
    if(almost_empty) begin //如果检测到FIFO将被读空
    state <= 2'd1; //就进入延时状态
    end
    else
    state <= state;
    end
    2'd1: begin
    if(dly_cnt == 10) begin //延时10拍
    //原因是FIFO IP核内部状态信号的更新存在延时

    //延迟10拍以等待状态信号更新完毕

    dly_cnt <= 4'd0;
    state <= 2'd2; //开始写操作
    fifo_wr_en <= 1'b1; //打开写使能
    end
    else begin
    dly_cnt <= dly_cnt + 4'd1;
    end
    end
    2'd2: begin
    if(almost_full) begin //等待FIFO将被写满
    fifo_wr_en <= 1'b0; //关闭写使能
    fifo_wr_data <= 8'd0;
    state <= 2'd0; //回到第一个状态
    end
    else begin //如果FIFO没有被写满
    fifo_wr_en <= 1'b1; //则持续打开写使能
    fifo_wr_data <= fifo_wr_data + 1'd1; //且写数据值持续累加
    end
    end
    default : state <= 2'd0;
    endcase
    end
    end

    endmodule
    五、实验现象
    编译工程,生成.sbit文件
    2.png
    连接开发板
    3.png
    下载
    4.png
    进行仿真验证,右击仿真文件,运行仿真,前提需要先装好Modelsim软件
    5.png
    进入仿真页面,并添加需要观测的量
    6.png
    仿真波形如下,当写满 255个数据后,fifo_full 满信号就会拉高。经过延时之后,fifo_rd_en 写使能信 号拉高,经过一拍之后就开始将 fifo 中的数据送到 fifo_dout 端口上。
    7.png
    好好修改一下网页编辑器吧,每次上传都挺难受。



    file:///C:/Users/dell/AppData/Local/Temp/msohtmlclip1/01/clip_image014.jpg




    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-5-10 16:52 , Processed in 0.113444 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.