在网上看到关于Altera的SCFIFO核的介绍中,都提到了它可以支持同时读写的功能,但未看到具体的仿真情况。Altera官方的ug中,也未看到关于此的明确描述(也可能是我读文档不仔细)。因此,对该问题进行modelsim仿真,将仿真情况记录于此,大家一起探讨。
首先生成一个256B的SCFIFO核,其主要参数如下:
defparam scfifo_component.add_ram_output_register = "ON", scfifo_component.almost_empty_value = 64, scfifo_component.almost_full_value = 128, scfifo_component.intended_device_family = "Cyclone III", scfifo_component.lpm_numwords = 256, scfifo_component.lpm_showahead = "OFF", scfifo_component.lpm_type = "scfifo", scfifo_component.lpm_width = 8, scfifo_component.lpm_widthu = 8, scfifo_component.overflow_checking = "ON", scfifo_component.underflow_checking = "ON", scfifo_component.use_eab = "ON";
生成的模块外形如下图所示。
编写测试代码如下
`timescale 1ns / 1ns module fifo_buf_tb; reg hclk; reg [7:0] data; reg rdreq; reg sclr=0; reg wrreq; wire almost_empty; wire almost_full; wire empty; wire full; wire [7:0] q; wire [7:0] usedw; FIFO_BUF DUT ( .clock ( hclk ), .data ( data ), .rdreq ( rdreq ), .sclr ( sclr ), .wrreq ( wrreq ), .almost_empty ( almost_empty ), .almost_full ( almost_full ), .empty ( empty ), .full ( full ), .q ( q ), .usedw ( usedw ) ); //20MHz高钟 initial begin hclk = 1'b1 ; forever #25 hclk = !hclk ; end //每1us更新一次data,每次更新自加1 initial begin data=1; forever #1000 data=data+1; end //给出一个高钟周期的wrreq信号 initial begin wrreq=0; forever begin #(0) wrreq=1; #50 wrreq=0; #(1000-50) ; end end //FIFO写入64字节后,进行读取试验 initial begin rdreq=0; forever begin #0 rdreq=(usedw>64?1:0); #50 rdreq=0; #(1000-50) ; end end //Start Time = 0 ns, End Time = 1ms initial #1000000 $stop; endmodule
modelsim仿真结果如下图所示。
由此可以看出,当输入数据的跳变和wrreq、rdreq同时发生时,SCFIFO中的数据无法正常读取,但非常奇怪的是,降低wrreq和rdreq的操作频率后,即时三者的跳变沿仍然是同步的,读取却是正常了。
相关代码调整如下
//给出一个高钟周期的wrreq信号 initial begin wrreq=0; forever begin #(1000) wrreq=1; //wrreq的操作频率降低一半 #50 wrreq=0; #(1000-50) ; end end //FIFO写入64字节后,进行读取试验 initial begin rdreq=0; forever begin #1000 rdreq=(usedw>64?1:0); rdreq的操作频率降低一半 #50 rdreq=0; #(1000-50) ; end end
仿真结果如下图。
可见此时SCFIFO的同时读写就正常了,但原因百思不得其解。
继续探讨SCFIFO不能正常同时读写的场景,一开始以为是wrreq与data同时跳变引起的,修改测试代码,使wrreq分别提前、错后一个高钟周期,仿真结果如下图所示。
由此可以看出,wrreq提前还是错后对仿真结果没有影响,都不能正常读取SCFIFO中的数据。
调整测试方式,固定wrreq与data同时跳变,调整rdreq的产生时间,仿真结果如下图所示。
由此可以看出,只要rdreq不与输入的data同时跳变,SCFIFO中的数据就可以正常读出。
继续针对读写频次的问题进行单变量测试,只降低读频次,仿真结果如下图(读触发条件改为usedw>96)。
此时SCFIFO的同时读写是正常的。
降低写频次进行仿真,结果如下图所示。
此时SCFIFO中的数据不能正常读出。
加密读频次,仿真结果如下图所示。
此时SCFIFO的读取扔不正常,推测是由于rdreq与输入data同频同相,导致SCFIFO输出出现异常,其它的rdreq信号也无法正常工作。
由上面的试验可以得出结论:当rdreq信号的周期和跳变沿与输入data完全一致时,SCFIFO中的数据无法正常读出。
虽然有了这个结论,但问题的机理仍不清楚,不知道与SCFIFO核的实现机制有无关系。在altera的文档中也未看到相关描述。因此,结论的正确性不能得到充分保证,期望各路大神进行指导。