前言:
FIFO是数据采集系统中必不可少的环节,AD采回来的数据要送至ARM/DSP处理,或将采回来的数据写到本地,都需要解决读写速度匹配问题,解决这类问题,首选FIFO。
在我们的设计当中,使用的是ADI公司的AD7989,18bit,100KSPS,采用三线SPI数据传输模式。采用两级FIFO,第一级FIFO用于缓存AD采样点数据,第二级FIFO用于DMA数据传输。
一. FIFO的使用
在本设计中,将数据这样打包:一个package包含1024个字(4096Byte)其中1020个AD采样数据点(AD采样数据扩展成32bit),4个字的数据包信息:通道号(有两个通道)、块号(package编号)、触发信号位置、CRC校验码。
第一级FIFO(FIFO1)缓存AD采样点,时钟与AD时钟相同,都是50MHz,第二级FIFO(FIFO2)从第一级FIFO取数据,当取到1020个数据时,就往FIFO2中写4个字的数据包信息,第二级FIFO用于DMA将数据流送至内存DDR3的数据缓存。FIFO2采用异步时钟,因为触发信号(Trig)是一个脉冲,触发信号模块使用的时钟也是50MHz,因此写时钟仍然是50MHz,读时钟采用DMA时钟(200MHz)。FIFO都是Xilinx Vivado下自带的IP core。
FIFO1的写使能信号是ad模块的ad_data_rdy,当FIFO1中有数据时,读使能信号就有效(rd_en = !fifo_empty); FIFO2的写使能信号在FIFO1数出数据有效后一个时钟有效, 读使能是FIFO2的prog_empty来控制的。关于prog_empty信号,一开始的时候对Empty Threshold Assert Value和Empty Threshold Negate Value理解有误,后来查看了Xilinx FIFO ipCore手册pg057-fifo-generator.pdf的pg105-106得知:
Forbuilt-in FIFOs, the number of entries in the FIFO must be greater than thethreshold value + 1 before prog_empty is deasserted. For non built-inFIFOs(block RAM, distributed RAM, and so forth), if the number of entries inthe FIFO is greater than threshold value, prog_empty is deasserted. 本设计使用的是Block RAM,对于Block RAM FIFO而言,当FIFO中的数据个数大于Negate Value时,prog_empty=0,当FIFO中数据个数小于等于Assert Value时,prog_empty=1。本设计中,FIFO_RD_EN = prog_empty,下图是第二级FIFO读写数据时序图,wr_fifo2_count表示写入到FIFO中数据个数,read_pointer表示从FIFO中读出的数据个数,FIFO_ALMOST_EMPTY即prog_empty信号。
左边红线可看出,本设计中设置的Empty Threshold Negate Value=16,当FIFO中有17(>= Negate Value)个数据时,prog_empty=0。本设计中设置的Empty Threshold Assert Value=2,所以当FIFO中数据个数小于等于2时,prog_empty要变为1。对应到右边红线,在这个时钟边沿,FIFO中正好还有2个数据,因此prog_empty由0变为1,而FIFO_RD_EN = !prog_empty,此时仍有效,因此会继续从FIFO中读出一个数据。