引荐博文:
xilinx FIFO的使用及各信号的讨论
Xilinx ISE FIFO读写操作仿真学习
这两篇博文都很好,一共介绍了两种比较全面的fifo数据接口测量方案。
下面进行博主自己的fifo_ip测试。
fifo_ip fifotest (
.rst (rst), // input rst
.wr_clk (wr_clk), // input wr_clk
.rd_clk (rd_clk), // input rd_clk
.din (din), // input [7 : 0] din
.wr_en (wr_en), // input wr_en
.rd_en (rd_en), // input rd_en
.dout (dout), // output [7 : 0] dout
.full (full), // output full
.almost_full (almost_full), // output almost_full
.wr_ack (wr_ack), // output wr_ack
.overflow (overflow), // output overflow
.empty (empty), // output empty
.almost_empty (almost_empty), // output almost_empty
.valid (valid), // output valid
.underflow (underflow), // output underflow
.rd_data_count (rd_data_count), // output [7 : 0] rd_data_count
.wr_data_count (wr_data_count), // output [7 : 0] wr_data_count
.prog_full (prog_full), // output prog_full
.prog_empty (prog_empty) // output prog_empty
);
module ip_test_fifo(
input clk,
input rst_n
);
wire rst ;
wire [7 : 0] din ;
// wire wr_en ;
wire rd_en ;
wire [7 : 0] dout ;
wire full ;
wire almost_full ;
wire wr_ack ;
wire overflow ;
wire empty ;
wire almost_empty ;
wire valid ;
wire underflow ;
wire [7 : 0] rd_data_count ;
wire [7 : 0] wr_data_count ;
wire prog_full ;
wire prog_empty ;
reg [8:0] din_cnt;
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
din_cnt <= 'd0;
else
if(din_cnt == 'd511)
din_cnt <= 'd0;
else
din_cnt <= din_cnt + 1'b1;
end
assign wr_en = ((din_cnt >= 9'd10) && (din_cnt <= 9'd100));
assign rd_en = ((din_cnt >= 9'd110) && (din_cnt <= 9'd200));
assign din = (wr_en) ? din_cnt : 'd0;
assign rst = ~rst_n ;
fifo_ip fifotest (
.rst (rst), // input rst
.wr_clk (clk), // input wr_clk
.rd_clk (clk), // input rd_clk
.din (din), // input [7 : 0] din
.wr_en (wr_en), // input wr_en
.rd_en (rd_en), // input rd_en
.dout (dout), // output [7 : 0] dout
.full (full), // output full
.almost_full (almost_full), // output almost_full
.wr_ack (wr_ack), // output wr_ack
.overflow (overflow), // output overflow
.empty (empty), // output empty
.almost_empty (almost_empty), // output almost_empty
.valid (valid), // output valid
.underflow (underflow), // output underflow
.rd_data_count (rd_data_count), // output [7 : 0] rd_data_count
.wr_data_count (wr_data_count), // output [7 : 0] wr_data_count
.prog_full (prog_full), // output prog_full
.prog_empty (prog_empty) // output prog_empty
);
endmodule
可以看出
1,wr_ack 是用来标记上一个时钟是否成功写入数据的。
2,wr_data_count是在wr_ack拉高之后开始计数,计数为成功写入加一,进行减一是在数据读数的时候,但有时钟延时
3,rd_data_count是计数可以读数的数据个数,同样会优势种
4,数据的写入实在wr_en拉高的同时写入的,没有时钟延时
5,re_en使能信号来临时数据不会立刻出来,会延时一个时钟周期
6,valid信号是标志读有效的,当有数据出时,valid信号拉高
7,空满信号
7,A,空信号:(图三)可以看出,信号是与写数据计数有关
7,B,满信号:这里没有写满,写一个测试案例进行测试
8,其他信号可以不用去处理(需要进行测试的时候补充)或者见测试二
图一
图二
图三
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
din_cnt <= 'd0;
else
if(din_cnt == 'd511)
din_cnt <= 'd0;
else
din_cnt <= din_cnt + 1'b1;
end
assign wr_en = ((din_cnt >= 9'd0) && (din_cnt <= 9'd260));
assign rd_en = ((din_cnt >= 9'd261) && (din_cnt <= 'd511));
// assign din = (wr_en) ? din_cnt : 'd0;
// din = 0;
reg [7 : 0] din = 'd0;
assign rst = ~rst_n ;
always @ (posedge clk)
begin
din = ~din;
end
9,rst信号:这里的复位信号是高电平有效,这也就是为什么有
assign rst = ~rst_n ;
这样一段代码的原因了。
10,读使能信号的有效必须在复位结束后的一两个时钟周期在给,否则写入数据是不能写入的。两种检验方式,第一,通过后面读出的数据,第二,根据wr_ack信号
11,满信号拉高的时候,就已经不能写入数据了(图五,根据wr_ack可知)
12,溢出信号:在数据满信号拉高,数据继续写入,溢出信号拉高
图四
图五