Асинхронный FIFO

//-----------------------------------------------------
// Имя модуля : aFifo
// Имя файла : aFifo.v
// Функц. назначение : Асинхронный (однотактовый) FIFO
// Программист : www.portal-ed.ru/
//-----------------------------------------------------
module aFifo
#(parameter DATA_WIDTH = 8,
ADDRESS_WIDTH = 4,
FIFO_DEPTH = (1 << ADDRESS_WIDTH))
//Чтение порта
(output reg [DATA_WIDTH-1:0] Data_out,
output reg Empty_out,
input wire ReadEn_in,
input wire RClk,
//Запись в порт
input wire [DATA_WIDTH-1:0] Data_in,
output reg Full_out,
input wire WriteEn_in,
input wire WClk,
input wire Clear_in);
/////Внутренние связи и переменные//////
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;
//////////////Начало кода///////////////
//Логические порты данных:
//(Использование двойной RAM).
//'Data_out:
always @ (posedge RClk)
   if (ReadEn_in & !Empty_out)
   Data_out <= Mem[pNextWordToRead];
//'Data_in’:
always @ (posedge WClk)
   if (WriteEn_in & !Full_out)
      Mem[pNextWordToWrite] <= Data_in;
//Логическая поддержка Fifo:
//'Next Addresses' логическое разрешение:
assign NextWriteAddressEn = WriteEn_in & ~Full_out;
assign NextReadAddressEn = ReadEn_in & ~Empty_out;
//Addreses (Счетчик Грэя):
GrayCounter GrayCounter_pWr
(.GrayCount_out(pNextWordToWrite),
.Enable_in(NextWriteAddressEn),
.Clear_in(Clear_in),
.Clk(WClk)
);
GrayCounter GrayCounter_pRd
(.GrayCount_out(pNextWordToRead),
.Enable_in(NextReadAddressEn),
.Clear_in(Clear_in),
.Clk(RClk)
);
//'EqualAddresses':
assign EqualAddresses = (pNextWordToWrite == pNextWordToRead);
//'Quadrant selectors’:
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' защелка:
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' запись в порт:
assign PresetFull = Status & EqualAddresses; //'Полный' Fifo.
always @ (posedge WClk, posedge PresetFull) //D-триггер с
// асинхронной предустановкой
if (PresetFull)
    Full_out <= 1;
    else
    Full_out <= 0;
//'Empty_out' чтение из порта:
assign PresetEmpty = ~Status & EqualAddresses; //'Пустой' Fifo.
always @ (posedge RClk, posedge PresetEmpty) // D-триггер с
// асинхронной предустановкой
if (PresetEmpty)
    Empty_out <= 1;
    else
         Empty_out <= 0;
endmodule