head 1.1; access; symbols; locks; strict; comment @# @; 1.1 date 2008.02.03.17.45.12; author lekernel; state Exp; branches; next ; commitid 244a47a5fd9b4567; desc @@ 1.1 log @Initial import @ text @//========================================== // Function : Asynchronous FIFO (w/ 2 asynchronous clocks). // Coder : Alex Claros F. // Date : 15/May/2005. // Notes : This implementation is based on the article // 'Asynchronous FIFO in Virtex-II FPGAs' // writen by Peter Alfke. This TechXclusive // article can be downloaded from the // Xilinx website. It has some minor modifications. //========================================= `timescale 1ns / 1ps module async_fifo #(parameter DATA_WIDTH = 8, ADDRESS_WIDTH = 4, FIFO_DEPTH = (1 << ADDRESS_WIDTH)) //Reading port (output wire [DATA_WIDTH-1:0] Data_out, output reg Empty_out, input wire ReadEn_in, input wire RClk, //Writing port. input wire [DATA_WIDTH-1:0] Data_in, output reg Full_out, input wire WriteEn_in, input wire WClk, input wire Clear_in); /////Internal connections & variables////// reg [DATA_WIDTH-1:0] Mem [FIFO_DEPTH-1:0]; wire [ADDRESS_WIDTH-1:0] pNextWordToWrite, pNextWordToRead; wire EqualAddresses; wire NextWriteAddressEn, NextReadAddressEn; wire Set_Status, Rst_Status; reg Status; wire PresetFull, PresetEmpty; //////////////Code/////////////// //Data ports logic: //(Uses a dual-port RAM). //'Data_out' logic: assign Data_out = Mem[pNextWordToRead]; // always @@ (posedge RClk) // if (!PresetEmpty) // Data_out <= Mem[pNextWordToRead]; // if (ReadEn_in & !Empty_out) //'Data_in' logic: always @@ (posedge WClk) if (WriteEn_in & !Full_out) Mem[pNextWordToWrite] <= Data_in; //Fifo addresses support logic: //'Next Addresses' enable logic: assign NextWriteAddressEn = WriteEn_in & ~Full_out; assign NextReadAddressEn = ReadEn_in & ~Empty_out; //Addreses (Gray counters) logic: GrayCounter #( .COUNTER_WIDTH( ADDRESS_WIDTH ) ) GrayCounter_pWr ( .GrayCount_out(pNextWordToWrite), .Enable_in(NextWriteAddressEn), .Clear_in(Clear_in), .Clk(WClk) ); GrayCounter #( .COUNTER_WIDTH( ADDRESS_WIDTH ) ) GrayCounter_pRd ( .GrayCount_out(pNextWordToRead), .Enable_in(NextReadAddressEn), .Clear_in(Clear_in), .Clk(RClk) ); //'EqualAddresses' logic: assign EqualAddresses = (pNextWordToWrite == pNextWordToRead); //'Quadrant selectors' logic: assign Set_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ~^ pNextWordToRead[ADDRESS_WIDTH-1]) & (pNextWordToWrite[ADDRESS_WIDTH-1] ^ pNextWordToRead[ADDRESS_WIDTH-2]); assign Rst_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ^ pNextWordToRead[ADDRESS_WIDTH-1]) & (pNextWordToWrite[ADDRESS_WIDTH-1] ~^ pNextWordToRead[ADDRESS_WIDTH-2]); //'Status' latch logic: always @@ (Set_Status, Rst_Status, Clear_in) //D Latch w/ Asynchronous Clear & Preset. if (Rst_Status | Clear_in) Status = 0; //Going 'Empty'. else if (Set_Status) Status = 1; //Going 'Full'. //'Full_out' logic for the writing port: assign PresetFull = Status & EqualAddresses; //'Full' Fifo. always @@ (posedge WClk, posedge PresetFull) //D Flip-Flop w/ Asynchronous Preset. if (PresetFull) Full_out <= 1; else Full_out <= 0; //'Empty_out' logic for the reading port: assign PresetEmpty = ~Status & EqualAddresses; //'Empty' Fifo. always @@ (posedge RClk, posedge PresetEmpty) //D Flip-Flop w/ Asynchronous Preset. if (PresetEmpty) Empty_out <= 1; else Empty_out <= 0; endmodule @