异步fifo的verilog代码

来源:互联网 发布:用java输出正方形 编辑:程序博客网 时间:2024/06/14 09:17
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 = FIFOempty

 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 0
原创粉丝点击