FIFO溢出:所谓溢出,指达到FIFO最大存储数之后或者是有可能存不下下一条数据或者包文时,需要根据需要对存入不了的部分进行处理,可以丢弃,也可以通过乒乓操作保存,此处主要讲丢弃。
案例一:
包文长度在50~200之间,FIFO最大存1000个长度的包文,要求FIFO不溢出,可以丢弃溢出部分的包文,可以多丢,但是一定要保证包文的完整性。
分析:因为要保证包文的完整性,所以只能在写侧进行丢弃,因为溢出后无法写入数据,读侧并不知道是否存入的数据溢出
最大存1000,而包文长度在50~200之间,也就是说,若存入的数据大于800后,若是检测到SOP信号,则丢弃该包文。按包文的最大长度进行丢弃,因为你无法判断来的包文到底是多大,超过1000 - 200 = 800 的SOP请求存入信号一律将包文丢弃在,这样才能保证包文是完整和正确的。
大于等于800检测到SOP进行丢弃判定,在检测到该丢弃包文的EOP信号时丢弃状态结束,此时再根据FIFO中剩余空间大小进行后续判定
//flag_drop == 1 : 开始丢弃信号
//flag_drop == 0 : 停止丢弃信号
assign drop_start = din_vld && din_sop && wrusedw >= 800 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
flag_drop <= 0;
end
else if(drop_start)begin
flag_drop <= 1'b1;
end
else if(din_vld && din_eop)begin
flag_drop <= 1'b0;
end
end
//数据FIFO写使能和写数据
assign wr_en = din_vld && (drop_start == 0 && flag_drop == 0);
assign wdata = (din_sop,din_eop,din);
//读使能
assign rd_en = empty == 0 && rdy ;//rdy是上个模块准备好信号
//dout
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout <= 0;
end
else begin
dout <= q[7:0];
end
end
//dout_sop
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_sop <= 0;
end
else begin
dout_sop <= q[9] && rd_en;
end
end
//dout_eop
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_eop <= 0;
end
else begin
dout_eop <= q[8] && rd_en;
end
end
//dout_vld
always @(posedge clk or negedge rst_n)begin
if(rst_n)begin
dout_vld <= 0;
end
else begin
dout_vld <= rd_en;
end
end
案例二:
当输入的包文第20个数据等于特定值时,该数据被读出,且读出的包文要完整。
首先设计一个计数器,计数到20即可,在20这一时刻判断数据是否等于特定值,若是特定值,则将信息FIFO的写使能拉高。
此处特定的值为16’h55,当然这个特定值可以根据需求更改
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 0;
end
else begin
cnt <= cnt + 1;
end
end
end
assign add_cnt = din_vld && flag == 0;
assign end_cnt = add_cnt && cnt == 20 - 1;
//flag == 1 时,不再计数
//flag == 0 时,一个包文完整的发送完成,即意味着可以进行下一个包文的计数
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
flag <= 0;
end
else if(end_cnt && din_eop == 0)begin
flag <= 1;
end
else if(din_vld && din_eop)begin
flag <= 0;
end
end
//数据FIFO的写使能和写数据
assign wr_en = din_vld ;
assign wdata = {din_sop,din_eop,din};
//信息FIFO
assign msg_wr_en = end_cnt && din == 16'h55;
assign msg_wdata = end_cnt;
//数据FIFO的读使能
assign rd_en = msg_empty == 0 && empty == 0;
//信息FIFO的读使能
//信息FIFO总是在最后一刻清掉总线上的数据
assign msg_rd_en = dout_eop_tmp ;
assign dout_eop_tmp = rd_en && q[16];
//dout_vld
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_vld <= 0;
end
else begin
dout_vld <= rd_en && msg_q;
end
end
//dout_sop
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_sop <= 0;
end
else begin
dout_sop <= rd_en && q[17];
end
end
//dout_eop
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_eop <= 0;
end
else begin
dout_eop <= rd_en && q[16];
end
end
//dout
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout <= 0;
end
else begin
dout <= q[15:0];
end
end
案例三:传入完整的包文后,若有ERR信号,则丢弃该包文
//数据FIFO 写使能,写数据
assign wr_en = din_vld ;
assign wdata = {din_sop,din_eop,din};
//信息FIFO 写使能,写数据
assign msg_wr_en = din_vld && din_eop;
assign msg_wdata = din_err==0;
//数据FIFO 读使能
assign rd_en = empty == 0 && msg_empty == 0;
//信息FIFO 读使能
assign msg_rd_en = dout_eop_tmp ;
assign dout_eop_tmp = rd_en && q[16];
//dout_sop
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_sop <= 0;
end
else begin
dout_sop <= rd_en && q[17];
end
end
//dout_eop
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_eop <= 0;
end
else begin
dout_eop <= dout_eop_tmp;
end
end
//dout_vld
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_vld <= 0;
end
else begin
dout_vld <= rd_en && msg_q;
end
end