zoukankan      html  css  js  c++  java
  • 数据缓存器FIFO IP核调取及应用

    写在前面的话

    在项目设计中我们通常需要在两个模块之间传输数据,如果两个模块的数据处理速率相同,那么自然没有任何问题,直接数据对接就可以。但是,如果两个模块的数据处理速度不同呢?数据接收模块和数据发送模块的速度不一致,必然会导致采集数据的遗漏或错误。那么,该如何解决这个问题呢?梦翼师兄的办法是在他们之间加一个数据缓存器,所有数据先经过缓存器缓存,然后再输入到数据接收模块。那么本节,梦翼师兄和大家一起学习用做数据缓存的存储IP核-FIFO的设计。

    项目需求

    创建两个模块一个作为数据发送模块,另一个作为数据接收模块。发送模块检测到FIFO为空则开始向FIFO中写入数据,直到FIFO写满为止。数据接收模块检测到FIFO为满则开始从FIFO中读出数据,直到FIFO读空为止。

    操作步骤 

    在右侧的IP核搜索区,输入fifo,然后双击【FI

    选择语言类型为Verilog并命名

    点击【OK】

    设置fifo的存储深度和每一个存储空间的比特位数,选择输入和读出不是同一个时钟,fifo就会出现读时钟和写时钟

    点击【NEXT】,选择端口如下

    点击【NEXT】

    选中my_fifo_inst.v文件,然后点击【Finish】退出即可。

    fifo的读端口信号

    fifo的写端口信号

    端口名称

    端口介绍

    端口名称

    端口介绍

    full

    读满信号(rdfull),当fifo被填充满,全部没有读出时,full为真值

    full

    写满信号(wrfull),当fifo被写满时full为真值

    empty

    读空信号(rdempty),当fifo所有的数据都被读出时,empty为真值

    empty

    写空信号(wrempty),当fifo没有任何数据被写入时,empty为真值

    注:读端口和写端口的输出会有几拍的时间差,这是由fifo内部的结构导致的。

     顶层架构设计

    FIFO是一个重要的数据缓冲器,我们设计出对应的控制模块对FIFO进行读写,根据我们在FIFO设置向导中了解到的信息,我们掌握了FIFO端口的含义,现设计架构图如下(为了方便大家理解在这里我们选择/数据的时钟是相同的) 

    模块功能介绍

    模块名

    功能描述

    Wr_fifo

    对fifo进行写入

    Rd_fifo

    对fifo进行读出

    My_fifo

    数据缓存器

    Fifo

    系统顶层模块,负责子模块级联

    端口和内部连线描述



    顶层模块端口介绍

    端口名

    端口说明

    Clk

    系统时钟输入

    Rst_n

    系统复位

    q

    数据输出

    系统内部连线介绍

    连线名

    连线说明

    wrreq

    写请求信号

    wrfull

    写满信号

    wrempty

    写空信号

    rdreq

    读请求信号

    rdfull

    读满信号

    rdempty

    读空信号

    data

    输入fifo的数据

    代码解释



    Wr_fifo模块代码

    /****************************************************          

     *   Engineer      :   梦翼师兄

     *   QQ             :   761664056

     *   The module function:fifo进行写入 *****************************************************/

    00 module wr_fifo (

    01 clk, //模块输入时钟

    02 rst_n, //模块复位

    03 wrfull,// 写满信号

    04 wrempty,//写空信号

    05 data,//fifo的输入数据

    06 wrreq//写请求信号

    07 );

    08 //模块输入

    09 input clk;//模块输入时钟

    10 input rst_n;//模块复位

    11 input wrfull;// 写满信号

    12 input wrempty;//写空信号

    13 //模块输出

    14 output reg [7:0] data;//fifo的输入数据

    15 output reg wrreq;//写请求信号

    16 //定义中间寄存器

    17 reg state; //状态寄存器

    18

    19 always @ (posedge clk or negedge rst_n)

    20 begin

    21 if (!rst_n)//复位时,将中间寄存器和输出清零

    22 begin

    23 data <= 0;

    24 wrreq <= 0;

    25 state <= 0;

    26 end

    27 else

    28 begin

    29 case (state)

    30 0 : begin

    31 if (wrempty)//写空时,写请求拉高,跳到下一个状态

    32 begin

    33 state <= 1;

    34 wrreq <= 1;

    35 data <= 0;

    36 end

    37 else

    38 state <= 0;

    39 end

    40

    41 1 : begin

    42 if (wrfull)//写满时,写请求拉低,跳回上一个状态

    43 begin

    44 state <= 0;

    45 data <= 0;

    46 wrreq <= 0;

    47 end

    48 else

    49 begin

    50 data <= data + 1; //没有写满的时候,写请求拉高,继续输入数据

    51 wrreq <= 1;

    52 end

    53 end

    54 endcase 

    55 end

    56 end

    57

    58 endmodule

    rd_fifo模块代码

    /****************************************************          

     *   Engineer      :   梦翼师兄

     *   QQ             :   761664056

     *   E_mail        :   zxopenwjf@126.com

     *   The module function:fifo进行读出 *****************************************************/

    00 module rd_fifo (

    01 clk,  //模块输入时钟

    02 rst_n, //模块复位

    03 rdfull,//读满信号

    04 rdempty,//读空信号

    05 rdreq//读请求

    06 );

    07 //模块输入

    08 input clk;//模块输入时钟

    09 input rst_n;//模块复位

    10 input rdfull;//读满信号

    11 input rdempty;//读空信号

    12 //模块输出

    13 output reg rdreq;//读请求

    14 //定义中间寄存器

    15 reg state;//状态寄存器

    16

    17 always @ (posedge clk or negedge rst_n)

    18 begin

    19 if (!rst_n)//复位时,将中间寄存器和输出清零

    20 begin

    21 rdreq <= 0;

    22 state <= 0;

    23 end

    24 else

    25 case (state)

    26 0 : begin

    27 if (rdfull)//读满时,读请求拉高,跳到下一个状态

    28 begin

    29 rdreq <= 1;

    30 state <= 1;

    31 end

    32 else

    33 state <= 0;

    34 end

    35

    36 1 : begin

    37 if (rdempty)//读空时,读请求拉低,跳回上一个状态

    38 begin

    39 rdreq <= 0;

    40 state <= 0;

    41 end

    42 else

    43 begin

    44 rdreq <= 1;//没有读空的时候,读请求拉高,继续读出数据

    45 state <= 1;

    46 end

    47 end

    48 endcase

    49

    50 end

    51

    52 endmodule

    顶层连接模块

    /****************************************************          

     *   Engineer      :   梦翼师兄

     *   QQ             :   761664056

     *   The module function:顶层连接模块 *****************************************************/

    00 module fifo (

    01 clk,  //系统输入时钟

    02 rst_n,  //系统复位

    03 q //输出数据

    04 );

    05  //系统输入

    06 input clk; //系统输入时钟

    07 input rst_n; //系统复位

    08 //系统输出

    09 output [7:0] q; //输出数据

    10 //定义中间连线

    11 wire wrfull; // 写满信号

    12 wire wrempty;//写空信号

    13 wire [7:0] data;//fifo的输入数据

    14 wire wrreq; //写请求信号

    15 wire rdfull;//读满信号

    16 wire rdempty;//读空信号

    17 wire rdreq;//读请求

    18 // 实例化wr_fifo模块

    19 wr_fifo  wr_fifo (

    20 .clk(clk),  //系统输入时钟

    21 .rst_n(rst_n), //系统复位

    22 .wrfull(wrfull), // 写满信号

    23 .wrempty(wrempty), //写空信号

    24 .data(data), //fifo的输入数据

    25 .wrreq(wrreq)//写请求信号

    26 );

    27 // 实例化rd_fifo模块

    28 rd_fifo rd_fifo (

    29 .clk(clk),  //系统输入时钟

    30 .rst_n(rst_n), //系统复位

    31 .rdfull(rdfull), //读满信号

    32 .rdempty(rdempty), //读空信号

    33 .rdreq(rdreq)//读请求

    34 );

    35 //实例化my_fifo

    36 my_fifo my_fifo_inst (

    37 .data ( data ),//fifo的输入数据

    38 .rdclk ( clk ),//读时钟

    39 .rdreq ( rdreq ),//读请求

    40 .wrclk ( clk ),//写时钟

    41 .wrreq ( wrreq ),//写请求

    42 .q ( q ),//输出数据

    43 .rdempty ( rdempty ),//读空信号

    44 .rdfull ( rdfull ),//读满信号

    45 .wrempty ( wrempty ),//写空信号

    46 .wrfull ( wrfull )//写满信号

    47 );

    48

    49 endmodule

    编写完可综合代码之后首先查看RTL视图如下

    RTL视图可以看出代码综合以后成的电路和我们所设计的系统框图一致说明顶层模块连接正确接下来编写测试代码如下

    /****************************************************          

     *   Engineer      :   梦翼师兄

     *   QQ             :   761664056

     *   The module function:fifo的仿真测试 *****************************************************/

    00  `timescale 1ns/1ps       //时间单位和精度定义

    01  module fifo_tb;

    02      //系统输入

    03      reg clk;        //系统输入时钟

    04      reg rst_n;  //系统复位

    05      //系统输出

    06      wire [7:0] q;       //输出数据

    07

    08      initial begin

    09          clk = 1;

    10          rst_n = 0;

    11          # 200.1

    12          rst_n = 1;

    13      end

    14      

    15      always # 10 clk = ~clk; //50MHz的时钟

    16      

    17      //实例化fifo

    18      fifo fifo (

    19                          .clk(clk),      //系统输入时钟

    20                          .rst_n(rst_n),  //系统复位

    21                          .q(q)           //输出数据

    22                      );

    23

    24  endmodule 

    仿真分析

    复位结束后,由于fifo中没有任何数据,所以写空信号为1,当写入一个数据之后,写空信号变成0,写满信号一直为0

    当输入数据到达256个的时候写满信号变高,并且经过几拍之后读满信号变成1(这是由fifo内部结构导致的),当读出一个数据之后,读满信号马上就拉低

    当读出的数据达到256后,读空信号变高,经过几拍之后写空信号变高(由fifo内部结构决定),之后开始重新写数据,开始循环。


     




     

  • 相关阅读:
    appium知识01-环境设置
    移动端测试基础知识02
    魔术方法和反射
    面向对象开发: 封装, 继承, 多态
    正则的用法
    内置方法, 第三方模块(math, random, pickle, json, time, os, shutil, zip, tarfile), 导入包
    推导式(列表, 集合, 字典), 生成器
    迭代器, 高阶函数(map, filter, reduce, sorted) , 递归函数
    函数globals和locals用法, LEGB原则, 闭包函数 , 匿名函数
    字符串, 列表, 元祖, 集合, 字典的相关操作和函数, 深浅copy
  • 原文地址:https://www.cnblogs.com/mengyi1989/p/11518290.html
Copyright © 2011-2022 走看看