在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 7988|回复: 17

[原创] 异步fifo的verilog代码问题

[复制链接]
发表于 2011-5-13 19:38:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
一下是我写的异步fifo,不知怎么回事,用quartus综合后占用了9000多个LE,而且fifo的容量设的越大,占用的LE会更多,不明白原因 !!!望指教,急等!!!!!





//该模块儿是存放帧数据的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
发表于 2011-5-13 20:36:00 | 显示全部楼层
回复 1# 天天PDF


    这个FIFO是基于LUT搭的,又不是基于RAM的,容量越大,当然耗费的LE越多了。另外,我简单的算了一下,你的FIFO,就光存储体就
    256深度*16宽度=4096个寄存器了,的确不小啊。
 楼主| 发表于 2011-5-14 12:37:13 | 显示全部楼层
回复 2# acgoal


    我需要存这么多的数据,我所用到的帧长最大是2000多字节,我还是把帧减小到64字节了的,我想做一个通用的IP,不局限与某个FPGA,以后可能该代码作为SOC的一部分,有什么方法可以解决的吗?我不想使用FPGA内部的FIFO。异步fifo一般设计大小是多大?谢谢指教
发表于 2011-5-14 19:19:59 | 显示全部楼层
回复 4# 天天PDF


    异步FIFO深度要经过计算的,考虑pop和push的速率差距。不能overrun和underrun就可以了。不能用FPGA内部自带的FIFO,就只能用LE搭了。一般的来说,异步FIFO就只做时钟域信号的跨越。你这里还做了一些其他的逻辑,比如数据的组合。建议如果是设计通用FIFO,那么这部分拿出去,不要放FIFO里面,如果可能的话异步FIFO深度尽量小,需要存储器的话,可以在异步FIFO后面再挂一个同步FIFO来解决。异步FIFO不要用作存储单元,只用于做数据时钟域的跨越。
发表于 2011-5-14 19:26:37 | 显示全部楼层
写通用FIFO,不意味着里面的RAM也要用FF来搭。
可以用FPGA的RAM,外围电路自己搭就好了;需要移植到ASIC的时候,就改用ASIC的RAM就可以了。
所以RAM应该用一个shell包起来,通过parameter或者define来改变是用FPGA的核还是ASIC的核。
k.jpg
 楼主| 发表于 2011-5-14 22:58:25 | 显示全部楼层
回复 4# 天天PDF


    谢谢 懂了
发表于 2011-5-15 13:34:28 | 显示全部楼层
回复 5# acgoal


    这位仁兄说的挺好的!
发表于 2014-6-16 19:34:19 | 显示全部楼层
大赞一个
发表于 2014-6-18 19:29:07 | 显示全部楼层
为什么读指针计数那的程序里面没有如果rptr=8'hff时的情况,if(rptr==8'hff) rptr<=0,这样才对吧
发表于 2014-6-18 19:29:48 | 显示全部楼层
你这个异步fifo程序是好的吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-20 18:59 , Processed in 0.030189 second(s), 10 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表