// ****************************************************************************************************************
// Copyright(c) 2012, Technology Endless - Creative Boundless , All right reserved
// Filename : asynfifo.v
// Author : lucien
// Email : intellectuallib@126.com
// Date : Apr 22th, 2012
// Version : 1.0
// Company :
// Description : asynchronous FIFO(first in first out)
// Modification History
// Date By Revision Change Description
// ---------------------------------------------------------------------------------------
// 2012/04/22 Lucien 1.0 Original
// ****************************************************************************************************************
`timescale 1ns/1ps
module asynfifo(
rst ,
wr_clk ,
wr_en ,
din ,
full ,
rd_clk ,
rd_en ,
dout ,
empty
);
input wire rst ;//reset signal
input wire wr_clk ;//clock of read clock field
input wire wr_en ;//write enable
input wire [7:0] din ;
output wire full ;
input wire rd_clk ;//clock of write clock field
input wire rd_en ;
output wire [7:0] dout ;
output wire empty ;
/**************************************************************************************************************/
/**************************************************************************************************************\
* define internal signals *
\**************************************************************************************************************/
reg [7:0] waddr; //write address in write clock field
reg [7:0] raddr; //read address in read clock field
wire [7:0] waddr_gray_wclk; //the gray code of write address in write clock field
wire [7:0] raddr_gray_rclk; //the gray code of read address in read clock field
reg [7:0] waddr_gray_rclk_0; //the dealyed gray codes of write address in read clock field
reg [7:0] waddr_gray_rclk_1;
reg [7:0] raddr_gray_wclk_0; //the dealyed gray codes of read address in write clock field
reg [7:0] raddr_gray_wclk_1;
wire [7:0] waddr_rclk; //write address in read clock field
wire [7:0] raddr_wclk; //read address in write clock field
reg [8:0] count_wclk; //the data counter in write clock field
reg [8:0] count_rclk; //the data counter in read clock field
function [7:0] binary_to_gray;
input [7:0] binary_code ;
begin
binary_to_gray[0]=binary_code[0]^binary_code[1];
binary_to_gray[1]=binary_code[1]^binary_code[2];
binary_to_gray[2]=binary_code[2]^binary_code[3];
binary_to_gray[3]=binary_code[3]^binary_code[4];
binary_to_gray[4]=binary_code[4]^binary_code[5];
binary_to_gray[5]=binary_code[5]^binary_code[6];
binary_to_gray[6]=binary_code[6]^binary_code[7];
binary_to_gray[7]=binary_code[7];
end
endfunction
function [7:0] gray_to_binary;
input [7:0] gray_code ;
begin
gray_to_binary[7]=waddr_gray_rclk_1[7];
gray_to_binary[6]=waddr_gray_rclk_1[6]^gray_to_binary[7];
gray_to_binary[5]=waddr_gray_rclk_1[5]^gray_to_binary[6];
gray_to_binary[4]=waddr_gray_rclk_1[4]^gray_to_binary[5];
gray_to_binary[3]=waddr_gray_rclk_1[3]^gray_to_binary[4];
gray_to_binary[2]=waddr_gray_rclk_1[2]^gray_to_binary[3];
gray_to_binary[1]=waddr_gray_rclk_1[1]^gray_to_binary[2];
gray_to_binary[0]=waddr_gray_rclk_1[0]^gray_to_binary[1];
end
endfunction
simple_dual_port_ram U_simple_dual_port_ram(
.clka (wr_clk ),
.wea (wr_en ),
.addra (waddr ),
.dina (din ),
.clkb (rd_clk ),
.addrb (raddr ),
.doutb (dout )
);
assign empty = (count_rclk[8:0] == 9'h0);
assign full = (count_rclk[8:0] == 9'h100);
assign waddr_gray_wclk = binary_to_gray(waddr);
assign raddr_gray_rclk = binary_to_gray(raddr);
assign waddr_rclk = gray_to_binary(waddr_gray_rclk_1);
assign raddr_wclk = gray_to_binary(raddr_gray_wclk_1);
always@(posedge wr_clk or posedge rst)
begin
if(rst == 1'b1)
waddr <= 8'h0;
else
if(wr_en==1'b1)
waddr <= waddr + 8'h1;
else
waddr <= waddr;
end
always@(posedge rd_clk or posedge rst)
begin
if(rst == 1'b1)
raddr <= 8'h0;
else
if(wr_en==1'b1)
raddr <= raddr + 8'h1;
else
raddr <= raddr;
end
always@(posedge wr_clk or posedge rst)
begin
if(rst == 1'b1)
begin
raddr_gray_wclk_0<=8'b0;
raddr_gray_wclk_1<=8'b0;
end
else
begin
raddr_gray_wclk_0<=raddr_gray_rclk;
raddr_gray_wclk_1<=raddr_gray_wclk_0;
end
end
always@(posedge rd_clk or posedge rst)
begin
if(rst == 1'b1)
begin
waddr_gray_rclk_0<=8'b0;
waddr_gray_rclk_1<=8'b0;
end
else
begin
waddr_gray_rclk_0<=waddr_gray_wclk;
waddr_gray_rclk_1<=waddr_gray_rclk_0;
end
end
always@(posedge wr_clk or posedge rst)
begin
if(rst == 1'b1)
count_wclk <= 9'h0;
else
if(waddr < raddr_wclk)
count_wclk <= waddr + 9'h100 - raddr_wclk;
else if((count_wclk > 9'h0) && (waddr == raddr_wclk))
count_wclk <= 9'h100;
else
count_wclk <= waddr - raddr_wclk;
end
always@(posedge rd_clk or posedge rst)
begin
if(rst == 1'b1)
count_rclk <= 9'h0;
else
if(waddr_rclk < raddr)
count_rclk <= waddr_rclk + 9'h100 - raddr;
else if((count_rclk > 9'h0) && (waddr_rclk == raddr))
count_rclk <= 9'h100;
else
count_rclk <= waddr_rclk - raddr;
end
endmodule
|