• ALTERA FPGA IPCORE核之FIFO详细教程


    ALTERA FPGA IPCORE核之FIFO详细教程

    若要观看该博客配套的视频教程,可点击此链接

    一. FIFO简介

    FIFO: 是英文first in first out的缩写,即先进先出,指的是对数据的存储具有先进先出特性的缓存器。从字面意思上就可以大致看出和RAM和ROM的区别,即没有地址线,无法像RAM和ROM一样写入或读出指定地址的数据,而必须按顺序读出。
    根据读写操作是否使用同一个时钟,可以将FIFO分为两类:

    • 同步FIFO

      读写操作使用同一个时钟,一般用于数据缓存

    • 异步FIFO

      读写操作使用不同的时钟,一般用于跨时钟域处理,比如我们在做视频相关项目时,假如我们的摄像头的像素时钟是25MHZ,SDRAM的读写时钟是100MHZ,那我们要把采集到的视频数据写入SDRAM,那么就必须要用到异步FIFO,进行跨时钟域处理。还有一种应用场景,读写数据的位宽不一致时,比如写入的数据是16位,读出的数据需要8位,这时候使用异步FIFO,只需要分别选择写数据位宽和读数据位宽,非常方便,值得注意的是QuartusII中的同步FIFO,读数据位宽是无法进行更改,默认和写数据位宽一致。

    二. FIFO IPCORE生成步骤及参数介绍

    不同公司的FPGA,生成的FIFO大同小异,本篇我们以一个实例来对ALTERA的IPCORE来进行介绍。我们要生成一个写数据位宽8,读数据位宽16的异步FIFO,利用Modelsim仿真来观察FIFO的时序波形。

    2.1 首先打开QuartusII软件,新建一个工程,命令为async_fifo_test

    新建QuartusII工程的步骤就不一一说明,为了方便上板验证,选用我们开发板上的器件:EP4CE6F17C8

    2.2 FIFO IPCORE配置
    2.2.1 生成IPCORE,命名为async_fifo_w8r16_d1024
    我们在对IPCORE命名时,最好能体现出该IPCORE的一些主要特性,比如我们上面的命令,我们知道是一个异步FIFO,写数据位宽8,读数据位宽16,深度1024。说到这,就有必要说一下非对称读写位宽。读写数据的位宽可以不一致,但是必须满足比例关系:1:8,1:4,1:2,1:1,那么读写位宽不一致,数据的排序关系是怎么样的呢?我们分两种情况做一下说明:

    1. 写位宽大于读位宽,直截了当我做了一个简单的测试程序仿真出的波形如下:
      在这里插入图片描述

      通过仿真可以看出,写入16’h0102,先读出的是8’h02,接着读出的是8’h01,是不是和我们想的不一样,所以这个地方一定要注意噢

    2. 写位宽小于读位宽,直截了当我做了一个简单的测试程序仿真出的波形如下:
      在这里插入图片描述

      通过仿真可以看出,写入8’h01,8’h02两个数,读出的是16’h0201,是不是和我们想的不一样,所以这个地方一定要注意噢
      2.2.2 生成FIFO的步骤如下图所示:
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    当我们生成好后可以看到左边FIFO框图上显示了FIFO的输入输出接口,左下角是FIFO使用的FPGA内部资源。

    2.2.2 FIFO各接口定义如下:

    1. wrfull:选用写时钟域,写满是指写得快读得慢,FIFO里面的存储数据超过了FIFO的深度,如果这时候再继续写,数据就会溢出丢失,所以这时需要禁止再往FIFO 中写入数据,防止数据溢出丢失。高电平表示FIFO写入数据量达到 FIFO 设置的最大空间
    2. rdempty:选用读时钟域,高电平表示 FIFO 中已经没有数据了,此时应该通过该信号控制读请求信号(也称为读使能信号),禁止FIFO 继续再读出数据,否则读出的将是无效数据。
    3. rdusedw:为FIFO里面存存储的数据个数。在某些应用场景下,我们需要用到usedw时钟监测FIFO存储的数据个数,但是需要注意,同步FIFO的数据计数是准确的,因为读写时钟相同,不需要做跨时钟域处理;但是异步FIFO的计数就不准确了,只能粗略的进行判断,比如半空,半满等。
    4. wrreq:写使能,高电平有效
    5. wrclk:写时钟
    6. data:写数据,位宽8
    7. rdreq:读使能,高电平有效
    8. rdclk:读时钟
    9. aclr:异步复位信号,用于清空 FIFO
    10. almost full:几乎满标志信号,我们可以控制 FIFO 快要被写满的时候和 full 信号的作用一样。
    11. almost empty:几乎空标志信号,我们可以控制 FIFO 快要被读空的时候和 empty 信号的作用一样。
    12. Synchronous clear:同步复位信号,用于清空 FIFO。
    10~12的信号,本例程的FIFO没有生成,大家可根据具体需求选择是否生成这些信号。

    三. Verilog代码设计

    	`timescale 1ns / 100ps
        module async_fifo_test(
        	input	clk			,//50MHZ
        	input	rst_n		,
        	output	[15:0]	dout
        	);
        	reg	[ 7:0]	fifo_wdata	;
        	reg			fifo_wren	;
        	reg			fifo_rden	;
        	wire[15:0]	fifo_rdata	;
        	wire		fifo_wclk	;
        	wire		fifo_rclk	;
        	wire		locked		;
        	reg	[9:0]	wr_cnt		;
        	reg	[8:0]	rd_cnt		;
        	assign	dout=fifo_rdata	;
        	//注意需要在fifo_wclk时钟域下,因为fifo写使能和写数据都是在该计数器(wr_cnt)下生成
        	always@(posedge fifo_wclk or negedge locked)begin
        		if(!locked)
        			wr_cnt<=0;
        		else 
        			wr_cnt<=wr_cnt+1;
        	end
        	//注意需要在fifo_rclk时钟域下,因为fifo读使能是在该计数器(rd_cnt)下生成
        	always@(posedge fifo_rclk or negedge locked)begin
        		if(!locked)
        			rd_cnt<=0;
        		else 
        			rd_cnt<=rd_cnt+1;
        	end
        	//在fifo_wclk时钟域下生成FIFO写数据和写使能,位宽8位,写100个数据
        	always@(posedge fifo_wclk or negedge locked)begin
        		if(!locked)begin
        			fifo_wren<=0;
        			fifo_wdata<=0;
        		end else if(wr_cnt>0&&wr_cnt<=100)begin
        			fifo_wren<=1;
        			fifo_wdata<=fifo_wdata+1;
        		end else begin
        			fifo_wren<=0;
        		end
        	end
        	//在fifo_rclk时钟域下生成FIFO读使能,读数据的位宽是16位,所以读50个数据就将FIFo读空
        	always@(posedge fifo_rclk or negedge locked)begin
        		if(!locked)
        			fifo_rden<=0;
        		else if(rd_cnt>100&&rd_cnt<=150)
        			fifo_rden<=1;
        		else
        			fifo_rden<=0;
        	end
        	//利用PLL生成FIFO的读写时钟,写时钟25MHZ,读时钟50MHZ
        	pll Upll(
        	.areset		(~rst_n		),
        	.inclk0		(clk		),
        	.c0			(fifo_wclk	),
        	.c1			(fifo_rclk	),
        	.locked 	(locked		)
        	);
        	//例化FIFO IPCORE
        	async_fifo_w8r16_d1024 Uasync_fifo_w8r16_d1024(
        	.aclr		(~rst_n		),//复位,高电平复位
        	.data		(fifo_wdata	),//写数据
        	.rdclk		(fifo_rclk	),//读时钟
        	.rdreq		(fifo_rden	),//读使能
        	.wrclk		(fifo_wclk	),//写时钟
        	.wrreq		(fifo_wren	),//写使能
        	.q			(fifo_rdata	),//读数据
        	.rdempty	(),//读空标志
        	.rdusedw	(),//在读时钟域下,FIFO中当前存储的数据个数,数据位宽16位
        	.wrfull ()//写满标志
        	);
        endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    四. Verilog测试代码设计

        `timescale 1ns / 100ps
        module async_fifo_test_tb;
        	reg					clk			=1;
        	reg					rst_n		=0;
        initial
        	begin
        		#1000
        		rst_n=1;
        	end
        //生成激励时钟
        always #10 clk<=~clk;
        //例化被测试模块
        async_fifo_test Uasync_fifo_test(
        	.clk	(clk	),//50MHZ
        	.rst_n	(rst_n	),
        	.dout   (		)
        	);
        endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    五. 仿真波形分析

    在这里插入图片描述
    1.aclr :fifo复位信号,高电平复位
    2.wrclk :fifo写时钟
    3.wrreq :fifo写使能,高电平时表示写入数据。
    4.rdclk :fifO读时钟
    5.rdreq :fifo读使能,高电平表示读数据,由于我们选择是正常模式,所以在rdreq有效时,会延时一个时钟周期才会出有效数据。
    6.q:fifo读数据
    7.rdempty:空标志,高电平表示fifo为空,在仿真波形中可以看出在fifo复位时且未写入数据时,rdempty为高电平,当前fifo为空。
    8.rdusedw:FIFO里面存存储的数据个数,由于我们用的是异步fifO,这个数据并不能精确的反应fifo里面的数据个数,只能做一个参考。通过上面的仿真图也可以看出,rdusedw并没有精确的反应fifo中的数据个数。
    9.wrfull:满标志,当fifo中存储的数据个数超过fifo自身的深度时,便会溢出,wrful置高。
    通过上面的仿真图,我们可以看到wrfull一直为低,所以fifo数据未溢出,不会造成数据丢失。同时,fifo在进行读操作时,rdempty一直为低,说明在读数据时,fifo中一直有数据,不会读出无效数据。一般来说,只要fifo操作满足以上两个条件,便可进行正常的数据写入和读取。

    如果大家想要该工程的源码和仿真测试激励文件用来学习,可以直接联系工程师,谢谢大家的阅读!

  • 相关阅读:
    打工人一定要学会找资源~
    [附源码]计算机毕业设计基于SpringBoot的校园报修平台
    C++高级编程: 可调用对象
    钉钉平台“智”领宠物界,开启萌宠智能新时代!
    【微信小程序入门到精通】— 微信小程序开发工具的安装
    含文档+PPT+源码等]精品基于SSM的体育商城的设计与实现[包运行成功]程序设计源码计算机毕设
    springboot 点滴(1)springboot IOC
    阿里内部目前最完整“Spring全线笔记”,不止是全家桶,太完整了
    RCE远程命令执行web经典题型解答
    可以从以下几点着手选择期货开户公司
  • 原文地址:https://blog.csdn.net/Moon_3181961725/article/details/126681138