基于Vivado的FIFO-IP核-强化篇

FIFO-IP核的配置

下面操作是以异步FIFO为例,且读模式为首字先出模式FWFT。

配置界面1

1、模块命名

首先给FIFO模块起名,要做到见名知意。

2、接口类型

接口类型,选择不同的接口类型,那么FIFO的信号线是不同的,也就是说接口类型不同,信号线的功能也不一样,我们的读写操作所使用的信号线不同。我们默认选择Native本地接口。

3、FIFO类型

FIFO类型选取,有同步FIFO和异步FIFO。

Block RAM称为块RAM、嵌入式RAM,它是一个电路,专门用于存储数据的。其电路是在FPGA内部,一块BRAM大小为36Kbit,由两个小的RAM(18Kbit)组成。在FPGA内部资源里有很多BRM资源。它是按块使用的,比如我们位宽是64bit,深度为65536,那么就要消耗64*65535 / (36*1024) ≈ 113.8,需要114个BRAM。那如果消耗了113.1个,那么还是消耗114个BRAM。

总结:(1)FPGA越贵,BRAM资源越多

(2)BRAM的数量,需要根据我们选择芯片信号,去查看手册得知。

(3)每一个BRAM的容量大小为36Kbit,每一块BRAM是由两个小的RAM(18Kbit)组成。

(4)有时候使用存储类的IP核,可能消耗的是BRAM资源,主要看我们选择是BRAM还是DRAM。

(5)消耗BRAM计算公式:位宽*深度 bit / 36Kbit,若存在小数,则结果要+1。

Distributed RAM称为分布式RAM,它消耗的只能是FPGA内部的CLB(可配置逻辑块)中的SLILCM中的LUT(查找表)资源, 可在UG474手册中12页查到。SLILCM的资源要少于SLILCL,在FPGA中比较分散。

FIFO/ROM/RAM-IP核如何选择RAM类型:

BRAM:尽量选择这个,数据量大、较为重要的数据、时钟频率高。是因为它是一个电路专门用于存储数据,适用于时钟频率快的情况。

DRAM:数据量小、不太重要的数据、时钟频率低。是因为它消耗的只能是FPGA内部的CLB(可配置逻辑块)中的SLILCM中的LUT(查找表)资源,而SLILCM的资源在FPGA中比较分散,在读写数据时这个时延相对来说比较大,适用于时钟频率慢的情况。

Bulitin FIFO:在FPGA内部是一个专门的电路,适用于高速的数据缓存的情况。

这里选择异步FIFO的BRAM类型。

配置界面2

1、读模式选择

设置读模式,分别是标准FIFO和首字先出模式。

标准FIFO:读使能rden和读数据之间会有一拍的延迟,也就是1个时钟的潜伏期(1 Clock Latency)

首字先出模式(FWFT) :读使能rden和读数据之间无延迟,也就是0个潜伏期(0 Clock Latency)

2、数据端口的参数

然后再设置读写位宽,以及深度。

异步FIFO可以解决的问题:(1)数据位宽不匹配问题(跨位宽),FIFO作为数据缓存器(同步FIFO也可以),但是需要注意的是读位宽最大只能是写位宽的8倍。(2)跨时域问题

3、输出寄存器

读使能rden和读数据之间的Clock Latency有三种情况:

0拍:FWFT,用在读使能rden和读数据间的时序是对齐的。

1拍:Standard,正常情况下都使用这个。

2拍:Standard + Output Registers,当时钟频率>=200Mhz或者我们的工程所用资源超过了FPGA芯片内部资源的70%,推荐使用2拍延迟

4、复位引脚

FIFO的复位信号rst高电平有效,在复位时rst信号高电平持续时间需要长一些,而且复位结束以后还需要等一会时间。如下图所示:来自PG057手册P128。在这段时间内读写数据都是无效的,也就是说在复位操作这段时间内不可以读写数据。

配置界面3

prog_full和prog_empty可作为反馈机制引脚,控制往FIFO里写数据模块,FIFO快满时不能写,FIFO读空时快点写。

配置界面4

假设写数据位宽位8bit,读数据位宽16bit。

写用量信号wr_data_count:代表FIFO中有多少个8bit数据。

读用量信号rd_data_count:代表FIFO中有多少个16bit数据。

配置界面5

最后检查一下配置是否正确,然后点击OK,即完成FIFO-IP核的配置。

仿真代码

复制代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/05/17 09:16:36
// Design Name: 
// Module Name: FWFT_FIFO_TB
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module FWFT_FIFO_TB(

    );
	
	
	reg fifo_clk;
	reg [15:0] fifo_wrdata;
	reg fifo_wren;
	reg fifo_rden;
	
	
	
	reg rst_n;
	initial begin 
	
		fifo_clk = 1'b0;
		rst_n = 1'b0;
		#300.1
		rst_n = 1'b1;
	
	end 
	
	always #10 fifo_clk = ~fifo_clk;
	
	
	reg [15:0]work_cnt;
	
	always @ (posedge fifo_clk or negedge rst_n)
	begin 
		if(~rst_n)
			begin 
				work_cnt <= 16'd0;
			end 
		else if(work_cnt == 16'd1000)
			begin 
				work_cnt <= work_cnt;
			end 
		else 
			begin 
				work_cnt <= work_cnt + 1'b1;
			end 
	end 
	
	
	always @ (posedge fifo_clk or negedge rst_n)
	begin 
		if(~rst_n)
			begin 
				fifo_wrdata <= 16'd0;
				fifo_wren <= 1'b0;
			end 
		else if((work_cnt >= 100) && (work_cnt <= 199))//写了100个随机数据
			begin 
				fifo_wrdata <= {$random} %3000;
				fifo_wren <= 1'b1;
			end 
		else 
			begin 
				fifo_wren <= 1'b0;
				fifo_wrdata <= 16'd0;
			end 
	end 
	
	
	always @ (posedge fifo_clk or negedge rst_n)
	begin 
		if(~rst_n)
			begin 
				fifo_rden <= 1'b0;
			end 
		else if((work_cnt >= 200) && (work_cnt <= 299))
			begin 
				fifo_rden <= 1'b1;
			end 
		else 
			begin 
				fifo_rden <= 1'b0;
			end 
	end 
	
	
	
	wire fifo_full;
	wire fifo_empty;
	wire [15:0]fifo_dataout;
	wire [10:0] fifo_data_count;//表示FIFO内部已经存在的数据量
    wire [10:0] wr_data_count;
	
	
	
	
	
	//异步FIFO测试
	FWFT_FIFO FWFT_FIFO (
	  .wr_clk(fifo_clk),                // input wire wr_clk
	  .rd_clk(fifo_clk),                // input wire rd_clk
	  .din(fifo_wrdata),                      // input wire [15 : 0] din
	  .wr_en(fifo_wren),                  // input wire wr_en
	  .rd_en(fifo_rden),                  // input wire rd_en
	  .dout(fifo_dataout),                    // output wire [15 : 0] dout
	  .full(fifo_full),                    // output wire full
	  .empty(fifo_empty),                  // output wire empty
	  .rd_data_count(fifo_data_count),  // output wire [10 : 0] rd_data_count
	  .wr_data_count(wr_data_count)  // output wire [10 : 0] wr_data_count
	);
	
	
	
	
	
	
	
	
	
endmodule

仿真验证

由于使用的首字先出模式,会在写数据时,将第一个数据放在读数据端口上,以此来实现的0拍的延迟。所以才会导致上面这种情况。但是不影响后续读数据时序。

相关推荐
FPGA小迷弟15 小时前
AXI4-Stream协议详解与Vivado自定义IP核封装实战
网络协议·tcp/ip·fpga开发·fpga·硬件开发
zlinear数据采集卡1 天前
数据采集卡从入门到精通(10):采样率与分辨率的核心关系——反比律、架构分布与过采样
arm开发·嵌入式硬件·算法·fpga开发·架构·开源
zlinear数据采集卡1 天前
数据采集卡从入门到精通(9):分辨率与精度——16位卡不等于1/65536的精度
开发语言·数据库·fpga开发·开源·c#
Hello-FPGA2 天前
AI 如何自动通过 PDF 原理图生成管脚映射
人工智能·fpga开发·pdf
zlinear数据采集卡2 天前
数据采集卡从入门到精通(7):流水线型ADC——级级接力,高速与高精的平衡术
开发语言·arm开发·嵌入式硬件·fpga开发·c#
鬼手点金2 天前
FPGA常用型号参考
fpga开发·verilog·vivado·xilinx·vhdl·altera·lattice
Kong_19943 天前
芯片开发学习笔记·二十九——大模型基础知识与 KV Cache 详解
fpga开发·芯片开发
m0_46644103詹湛3 天前
FPGA 定点数、小数与负数的加减乘除原理
fpga开发
zlinear数据采集卡3 天前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
zlinear数据采集卡3 天前
D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#