异步FIFO程序

module FIFO(Wr_Clk,//write FIFO clock
   nWr,   //write FIFO signal
   Din,   //write FIFO data
   Rd_Clk,//read  FIFO clock
   nRd,   //read  FIFO signal
   Dout,  //read  FIFO data
 
   Full,  // 1 = FIFO full
   Empty);// 1 = FIFO empty

 input  Wr_Clk, nWr, Rd_Clk, nRd;
 input  [Bsize-1:0] Din;
 output [Bsize-1:0] Dout;
 output Full, Empty;

 reg Full, Empty;
 reg [Bsize-1:0] Buff [Dsize-1:0];
 reg [Asize:0] Wr_Addr_Bin, Rd_Addr_Bin;
 reg [Asize:0] Sync_Wr_Addr0_Gray, Sync_Wr_Addr1_Gray, Sync_Wr_Addr2_Gray;
 reg [Asize:0] Sync_Rd_Addr0_Gray, Sync_Rd_Addr1_Gray, Sync_Rd_Addr2_Gray;

 wire [Asize-1:0] FIFO_Entry_Addr, FIFO_Exit_Addr;
 wire [Asize:0] Wr_NextAddr_Bin, Rd_NextAddr_Bin;
 wire [Asize:0] Wr_NextAddr_Gray, Rd_NextAddr_Gray;
 wire Asyn_Full, Asyn_Empty;

 parameter
  Dsize = 256, Asize = 8,
  Bsize = 8;

 initial
 begin
  Full   = 0;
  Empty  = 1;

  Wr_Addr_Bin = 0;
  Rd_Addr_Bin = 0;

  Sync_Wr_Addr0_Gray = 0;
  Sync_Wr_Addr1_Gray = 0;
  Sync_Wr_Addr2_Gray = 0;
  Sync_Rd_Addr0_Gray = 0;
  Sync_Rd_Addr1_Gray = 0;
  Sync_Rd_Addr2_Gray = 0;
 end
FIFO数据的写入与输出//
 assign FIFO_Exit_Addr  = Rd_Addr_Bin[Asize-1:0];
 assign FIFO_Entry_Addr = Wr_Addr_Bin[Asize-1:0];

 assign Dout = Buff[FIFO_Exit_Addr];
 always @ (posedge Wr_Clk)
 begin
  if (~nWr & ~Full) Buff[FIFO_Entry_Addr] <= Din;
  else              Buff[FIFO_Entry_Addr] <= Buff[FIFO_Entry_Addr];
 end
///FIFO读写的地址生成器///
 assign Wr_NextAddr_Bin = (~nWr&~Full) ?Wr_Addr_Bin[Asize:0]+1:Wr_Addr_Bin[Asize:0];
 assign Rd_NextAddr_Bin = (~nRd&~Empty)?Rd_Addr_Bin[Asize:0]+1:Rd_Addr_Bin[Asize:0];

 assign Wr_NextAddr_Gray = (Wr_NextAddr_Bin >> 1) ^ Wr_NextAddr_Bin;
 assign Rd_NextAddr_Gray = (Rd_NextAddr_Bin >> 1) ^ Rd_NextAddr_Bin;

 always @ (posedge Wr_Clk)
 begin
  Wr_Addr_Bin        <= Wr_NextAddr_Bin;
  Sync_Wr_Addr0_Gray <= Wr_NextAddr_Gray;
 end

 always @ (posedge Rd_Clk)
 begin
  Rd_Addr_Bin        <= Rd_NextAddr_Bin;
  Sync_Rd_Addr0_Gray <= Rd_NextAddr_Gray;
 end
///采用双锁存器把异步信号同步起来/
 always @ (posedge Wr_Clk)
 begin
  Sync_Rd_Addr2_Gray <= Sync_Rd_Addr1_Gray;//读信号同步到写时钟
  Sync_Rd_Addr1_Gray <= Sync_Rd_Addr0_Gray;
 end

 always @ (posedge Rd_Clk)
 begin
  Sync_Wr_Addr2_Gray <= Sync_Wr_Addr1_Gray;//写信号同步到读时钟
  Sync_Wr_Addr1_Gray <= Sync_Wr_Addr0_Gray;
 end
/将产生的Full信号和Empty信号同步的各自的时钟域上//
 assign Asyn_Empty = (Rd_NextAddr_Gray==Sync_Wr_Addr2_Gray);
 assign Asyn_Full  = (Wr_NextAddr_Gray=={~Sync_Rd_Addr2_Gray[Asize:Asize-1],
                                          Sync_Rd_Addr2_Gray[Asize-2:0]});

 always @ (posedge Wr_Clk)
 begin
  Full <= Asyn_Full;
 end

 always @ (posedge Rd_Clk)
 begin
  Empty <= Asyn_Empty;
 end
//
endmodule

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值