微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 异步fifo的verilog代码问题

异步fifo的verilog代码问题

时间:10-02 整理:3721RD 点击:
一下是我写的异步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



    这个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



   威武,深入浅出啊。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top