module Yb_FIFO
#(
parameter width=16,
parameter depth=16
)
(
input rst_n,
input wr_clk,
input wd_en,
input [width-1:0] data_in,
input rd_clk,
input rd_en,
output [width-1:0] data_out,
output full,
output empty
);
reg [width-1:0] mem [depth-1:0];
reg[4:0] waddr;
reg[4:0] waddr_gray;//二进制地址转换为格雷码
reg[4:0] waddr_w2r1;//写地址(格雷码)同步到读时钟域的打拍寄存
reg[4:0] waddr_w2r2;
reg[4:0] raddr;
reg[4:0] raddr_gray;
reg[4:0] raddr_r2w1;
reg[4:0] raddr_r2w2;
reg[width-1:0] data_temp;
//写指针
always@(posedge wr_clk or negedge rst_n)
begin
if(!rst_n)
waddr <= 5'b0000;
else if(!full)
waddr <= waddr+1;
else
waddr <= waddr;
end
//写指针转换为格雷码
assign waddr_gray = (waddr>>1)^waddr;
//写指针(格雷码)同步到读时钟域
always@(posedge rd_clk or negedge rst_n)
begin
if(!rst_n)
{waddr_w2r2,waddr_w2r1} <= {2{5'b00000}};
else
{waddr_w2r2,waddr_w2r1} <= {waddr_w2r1,waddr_gray};
end
//读指针
always@(posedge rd_clk or negedge rst_n)
begin
if(!rst_n)
raddr <= 5'b00000;
else(!empty)
raddr <= raddr+1;
else
raddr <= raddr;
end
//读指针转化为格雷码
assign raddr_gray = (raddr>>1)^raddr;
//读指针(格雷码)同步到写时钟域
always@(posedge wr_clk or negedge rst_n)
begin
if(!rst_n)
{raddr_r2w2,raddr_r2w1} <= {2{5'b00000}};
else
{raddr_r2w2,raddr_r2w1} <= {raddr_r2w1,raddr_gray};
end
//写数据
always@(posedge wr_clk )
begin
if(wd_en==1)
mem[waddr] <= data_in;
else
mem[waddr] <= mem[waddr];
end
//读数据
assign data_out = data_temp;
always@(posedge rd_clk or negedge rst_n)
begin
if(!rst_n)
data_temp <= mem{width{1'b0}};
else(rd_en==1)
data_temp <= mem[raddr];
else
data_temp <=data_temp;
end
//空信号判断
assign empty = (waddr_w2r2 == raddr_gray)?1'b1:1'b0;
//满信号判断
assign full = ({~(raddr_r2w2[4:3]),raddr_r2w2[2:0]}==waddr_gray[4:0])?1'b1:1'b0;
异步FIFOVerilog代码
于 2022-06-29 10:53:50 首次发布