异步fifo在IC设计中
源代码在线查看: asynfifo.v
//----------------------------------------------------------- // // Design : asynFifo // Author : Allen Leng // // Description : FIFO for code rate adjust in E1 to STM-1(SDH) // the interface is as follows: // ------------- // WrClk -->| | // WrEn -->| | // Din ==>| | // | asynFifo | // Full Dout // | |--> Empty // Rst -->| | // ------------- // Notes: 1) // // // History : // Jul.26,2005 Allen Leng Created this file // //----------------------------------------------------------- module asynFifo(Rst, WrClk, WrEn, Din,Full, RdClk, RdEn, Dout,Empty ); parameter AW = 6, // Number of memory address bits DW = 8; // the data width input Rst; // global reset signal, high level input WrClk; // ----- write port input WrEn; // write enable input [DW-1:0] Din; output Full; // almost full for protected input RdClk; // ----- read port input RdEn; // read enable output [DW-1:0] Dout; output Empty; // almost empty for protected reg Full,Empty; wire [AW-1:0] wrAddr,rdAddr; // the address for wr/rd of Ram wire enWr; // write protect when full wire enRd; // read protect when empty assign enWr = (~Full && WrEn); assign enRd = (~Empty &&RdEn); // (2^AW)*DW RAM Ram #(AW,DW) U_RAM(.Clk(WrClk), .EnWr(enWr), .AddrWr(wrAddr), .Din(Din), .AddrRd(rdAddr), .Dout(Dout) ); // *************************** // write address generation // *************************** reg [AW:0] wrPtr, // the current wr pointer wrPtrGray; // the gray code of wr pointer wire [AW:0] wrPtrNxt,wrPtrGrayNxt; assign wrAddr = wrPtr[AW-1:0]; assign wrPtrNxt = wrPtr + enWr; assign wrPtrGrayNxt = (wrPtrNxt >> 1) ^ wrPtrNxt; // write pointer always @ (posedge Rst or posedge WrClk) if(Rst) begin wrPtr wrPtrGray end else {wrPtr,wrPtrGray} //wrPtr sync to rdClk domain (read side) reg [AW:0] wrPtrRd,wrPtrGrayRd,wrPtrTmp; // wrPtrGray sync to read side always @ (posedge Rst or posedge RdClk) if(Rst) begin wrPtrTmp wrPtrGrayRd end else begin wrPtrTmp wrPtrGrayRd end integer i; // gray to binary: wrPtrGrayRd to wrPtrRd always @(wrPtrGrayRd) for (i=0; i wrPtrRd[i] = ^(wrPtrGrayRd>>i); // *************************** // read address generation // *************************** reg [AW:0] rdPtr, // the current read pointer rdPtrGray; // rdPtr in gray code wire [AW:0] rdPtrNxt,rdPtrGrayNxt; assign rdAddr = rdPtr[AW-1:0]; assign rdPtrNxt = rdPtr + enRd; assign rdPtrGrayNxt = (rdPtrNxt >> 1) ^ rdPtrNxt; // the current read pointer,including gray code always @ (posedge Rst or posedge RdClk) if(Rst) {rdPtr,rdPtrGray} else {rdPtr,rdPtrGray} //rdPtr sync to wrClk domain reg [AW:0] rdPtrWr,rdPtrGrayWr,ptrTmp; // rdPtrGray sync to write side always @ (posedge Rst or posedge WrClk) if(Rst) begin ptrTmp rdPtrGrayWr end else begin ptrTmp rdPtrGrayWr end // gray to binary: rdPtrGrayWr to rdPtrWr always @(rdPtrGrayWr) for (i=0; i rdPtrWr[i] = ^(rdPtrGrayWr>>i); //wr almost full generation: different page, and wrPtr catch up with // rdPtr within 5 cycles. always @ (wrPtr or rdPtrWr) if ((wrPtr[AW] != rdPtrWr[AW]) && ((wrPtr[AW-1:0] + 3'b101) >= rdPtrWr[AW-1:0])) Full = 1'b1; // 5 ???? else Full = 1'b0; always @ (wrPtrRd or rdPtr) if(wrPtrRd == rdPtr) Empty = 1'b1; else Empty = 1'b0; endmodule