异步fifo的verilog代码问题
//该模块儿是存放帧数据的fifo,512Byte,16位输入,32位输出
//存放8个帧,每个帧大小为64Byte,其中帧头24Byte,帧数据40Byte
module data_din_fifo(fifo_dout,//fifo数据输出
fifo_ren,//fifo读使能
rclk,//fifo读时钟
fifo_empty,//空
fifo_din,//fifo 数据输入
fifo_wen,//fifo写使能
wclk,//fifo写时钟
fifo_full,//满
reset
);
parameter
WIDTH_DOUT=32,
WIDTH_DIN=16,
ADDR_WIDTH=8,
DEPTH_FIFO=256;
output reg [WIDTH_DOUT-1:0]fifo_dout;
output reg fifo_empty,fifo_full;
input [WIDTH_DIN-1:0] fifo_din;
input fifo_ren,
rclk,
fifo_wen,
wclk,
reset;
reg [WIDTH_DIN-1:0] dual_port_ram[DEPTH_FIFO-1:0];//双口ram,位宽16,深度256
reg [ADDR_WIDTH-1:0] wptr,rptr;//写,读指针
reg [ADDR_WIDTH-1:0] sync_wptr,sync_rptr,//同步后的读写指针
sync_wptr_tmp,sync_rptr_tmp;//临时读写指针
reg full_flag,//满空方向标志,1趋于满,0趋于空
empty_flag;//1空 ,0满
wire [ADDR_WIDTH-1:0] sync_rptr_binary,sync_wptr_binary;
assign sync_rptr_binary=gray_to_binary(sync_rptr);
assign sync_wptr_binary=gray_to_binary(sync_wptr);
//////////////双口ram存取数据///////////////
always@(posedge wclk)
if((fifo_full==0)&&(fifo_wen==1))
dual_port_ram[wptr]<=fifo_din;
else
dual_port_ram[wptr]<=dual_port_ram[wptr];
always@(posedge rclk)
if((fifo_empty==0)&&(fifo_ren==1))
fifo_dout<={dual_port_ram[rptr],dual_port_ram[rptr+1'b1]};
else
fifo_dout<=fifo_dout;
/////////////读指针计数///////////////////
always@(posedge rclk or negedge reset)
if(!reset)
rptr<=0;
else
if((fifo_empty==0)&&(fifo_ren==1))
rptr<=rptr+1'b1+1'b1;
else
rptr<=rptr;
///////////写指针计数///////////////////
always@(posedge wclk or negedge reset)
if(!reset)
wptr<=0;
else
if((fifo_full==0)&&(fifo_wen==1))
wptr<=wptr+1'b1;
else
wptr<=wptr;
//////////写指针同步到读时钟////////////////
always@(posedge rclk or negedge reset)
if(!reset)
begin
sync_rptr<=0;
sync_rptr_tmp<=0;
end
else
begin
sync_rptr_tmp<=binary_to_gray(wptr);
sync_rptr<=sync_rptr_tmp;
end
//////////读指针同步到写时钟//////////
always@(posedge wclk or negedge reset)
if(!reset)
begin
sync_wptr<=0;
sync_wptr_tmp<=0;
end
else
begin
sync_wptr_tmp<=binary_to_gray(rptr);
sync_wptr<=sync_wptr_tmp;
end
//////////空标志////////////
always@(posedge rclk or negedge reset)
if(!reset)
fifo_empty<=1;
else
if((rptr==sync_wptr_binary)&&(empty_flag==1))
fifo_empty<=1;
else
fifo_empty<=0;
/////////满标志///////////
always@(posedge wclk or negedge reset)
if(!reset)
fifo_full<=0;
else
if((wptr==sync_rptr_binary)&&(full_flag==1))
fifo_full<=1;
else
fifo_full<=0;
////////空方向标志//////
always@(posedge rclk or negedge reset)
if(!reset)
empty_flag<=1;
else
if(rptr>sync_wptr_binary)
if(rptr-sync_wptr_binary>=192)//大于75%
empty_flag<=1;
else
empty_flag<=0;
else
if(sync_wptr_binary-rptr<64)
empty_flag<=1;
else
empty_flag<=0;
//////满方向标志///////////
always@(posedge wclk or negedge reset)
if(!reset)
full_flag<=0;
else
if(wptr>sync_rptr_binary)
if(wptr-sync_rptr_binary>192)
full_flag<=1;
else
full_flag<=0;
else
if(sync_rptr_binary-wptr<64)
full_flag<=1;
else
full_flag<=0;
function [7:0] binary_to_gray;
input [7:0] binary_din;
integer i;
begin
binary_to_gray[7]=binary_din[7];
for(i=0;i<7;i=i+1)
binary_to_gray=binary_din^binary_din[i+1];
end
endfunction
function [7:0] gray_to_binary;
input [7:0]gray_din;
integer j;
begin
gray_to_binary[7]=gray_din[7];
for(j=6;j>=0;j=j-1)
gray_to_binary[j]=gray_to_binary[j+1]^gray_din[j];
end
endfunction
endmodule
这个FIFO是基于LUT搭的,又不是基于RAM的,容量越大,当然耗费的LE越多了。另外,我简单的算了一下,你的FIFO,就光存储体就
256深度*16宽度=4096个寄存器了,的确不小啊。
我需要存这么多的数据,我所用到的帧长最大是2000多字节,我还是把帧减小到64字节了的,我想做一个通用的IP,不局限与某个FPGA,以后可能该代码作为SOC的一部分,有什么方法可以解决的吗?我不想使用FPGA内部的FIFO。异步fifo一般设计大小是多大?谢谢指教
异步FIFO深度要经过计算的,考虑pop和push的速率差距。不能overrun和underrun就可以了。不能用FPGA内部自带的FIFO,就只能用LE搭了。一般的来说,异步FIFO就只做时钟域信号的跨越。你这里还做了一些其他的逻辑,比如数据的组合。建议如果是设计通用FIFO,那么这部分拿出去,不要放FIFO里面,如果可能的话异步FIFO深度尽量小,需要存储器的话,可以在异步FIFO后面再挂一个同步FIFO来解决。异步FIFO不要用作存储单元,只用于做数据时钟域的跨越。
写通用FIFO,不意味着里面的RAM也要用FF来搭。
可以用FPGA的RAM,外围电路自己搭就好了;需要移植到ASIC的时候,就改用ASIC的RAM就可以了。
所以RAM应该用一个shell包起来,通过parameter或者define来改变是用FPGA的核还是ASIC的核。
谢谢 懂了
这位仁兄说的挺好的!
大赞一个
为什么读指针计数那的程序里面没有如果rptr=8'hff时的情况,if(rptr==8'hff) rptr<=0,这样才对吧
你这个异步fifo程序是好的吗?
小小的建议:
1:所有的FIFO深度和地址在端口定义的时候参数化处理。就比较通用;
2:存储部分的数据容量上了两千最好能够用BLOCK_RAM进行存储(RAM不够除外);
3:FIFO的满FULL信号一般不会直接用,最好直接做个几乎满的信号(水线可配置的);
4:读数据几拍出数据也能够参数化处理。
一点不成熟的想法!
正在学习,谢谢
你这个异步fifo程序是好的吗?
进来看看的
根据需要,计算fifo的深度。
写写练习还可以。实际都是ip的。
这到没关系。加满后会自动到8‘h00
威武,深入浅出啊。
