📄 asyncfifoxpx.v
字号:
//written by xpx in 2008-11-27, modified from the asyncfifo from limiao.
module ASYNCFIFO
#(parameter
DSIZE = 32,//width=16,指明读写数据的宽度
ASIZE = 2 //depth=4//指明地址总线的宽度,是fifo单元数的幂函数
)( //input signals
input wrst_n, //write resett
input wclk, //write clock
output wenable, //fifo full flag
input wta, //write enable,有效时表明输入端口数据有效
input [DSIZE-1:0] wdata, //write data
input rrst_n, //read reset
input rclk, //read clock
output renable, //fifo empty flag
input rreq, //read enable,有效时要求读取下一个数据
output [DSIZE-1:0] rdata //read data
);
parameter depth=2**ASIZE;
//internal variables
reg [ASIZE:0] wptr,rptr;
wire [ASIZE-1:0] waddr,raddr;
reg [ASIZE:0] wbin,rbin;
reg [ASIZE:0] wbin_next,rbin_next;
reg [ASIZE:0] wgnext,rgnext;
//---------write------------------------------------------
wire wring=wta&&wenable;
always @ (posedge wclk or negedge wrst_n)
if (!wrst_n)wptr<=0;
else wptr<=wptr+wring;//use binary code to keep data
reg[ASIZE:0]wptrg;
always@(posedge wclk)wptrg<={1'b0,wptr[ASIZE:1]}/*(wptr>>1)*/^wptr;//change binary to gray to transport
//----------read-------------------------------------------
wire rding=renable&&rreq;
wire[ASIZE-1:0]rptrram=rptr[ASIZE-1:0]+rding;
always @ (posedge rclk or negedge rrst_n)
if (!rrst_n)
rptr <= 0;
else
rptr <=rptr+rding;
reg[ASIZE:0]rptrg;
always@(posedge rclk)rptrg<={1'B0,rptr[ASIZE:1]}/*(rptr>>1)*/^rptr;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//本例中换成sysnplify生成的双端口ram,此处的ram必须换成确保可以使用的双端口ram才行。
fifowrclkram #(DSIZE,ASIZE)ram
(
.PortAClk (wclk)//used to write
,.PortAAddr (wptr[ASIZE-1:0])//waddr
,.PortADataIn (wdata)
,.PortAWriteEnable(wta)
,.PortBClk (rclk)//used to read
,.PortBAddr (rptrram)//rbin_next)//raddr)
,.PortBDataOut (rdata)//注意:读数据是经过寄存的,所以要延时1拍。
);
//-------------compare-------------------------------------
reg[ASIZE:0] wrptr2,rwptr2;//2位数据同步
reg[ASIZE:0]rtow;
always @ (posedge wclk or negedge wrst_n)
if(!wrst_n)
{wrptr2,rtow} <= 0;
else
{wrptr2,rtow} <= {rtow,rptrg};
reg[ASIZE:0]wtor;
always @ (posedge rclk or negedge rrst_n)
if(!rrst_n)
{rwptr2,wtor} <= 0;
else
{rwptr2,wtor} <= {wtor,wptrg};
wire [ASIZE:0] cmprptr,cmpwptr;
assign cmprptr = wrptr2 ^ {1'b0,wrptr2[ASIZE:1]};//[2:1]};//gray_to_bin,wclk下的rptr 2进制
assign cmpwptr = rwptr2 ^ {1'b0,rwptr2[ASIZE:1]};//2:1]};//gray_to_bin,rclk下的wptr 2进制
wire [ASIZE:0] wdata_count,rdata_count;
assign wdata_count = {cmprptr[ASIZE]^wptr[ASIZE],wptr[ASIZE-1:0]} - {1'b0,cmprptr[ASIZE-1:0]}; //wclk下求解count
assign rdata_count = {rptr[ASIZE]^cmpwptr[ASIZE],cmpwptr[ASIZE-1:0]} - {1'b0,rptr[ASIZE-1:0]};//rclk下求解count
//上面的异或是为了生成四个象限,由于只有4个单元,指针只需2位就可表示,而最高位[2]
//实际上就是指示翻转次数
assign wenable = (wdata_count != depth);//3'd4);
assign renable = (rdata_count != 3'd0);
endmodule
//always @ (posedge wclk or negedge wrst_n)
// if (!wrst_n)
// wptr <= 0;
// else
// wptr <= wgnext; //采用格雷码计数,保存数据
//always @ (*)
//begin
// for(i=0;i<ASIZE+1;i=i+1)//将用格雷码表示的wptr转换为2进制数
// wbin[i] = ^(wptr>>i);
//
// if(wenable)//将wptr的2进制形式加wta(wta)
// wbin_next = wbin+ wta;
// else
// wbin_next = wbin;
//
// wgnext = (wbin_next>>1) ^ wbin_next; //重新转换为格雷码
//end
//assign waddr = wbin[ASIZE-1:0]; //ram的写地址仍采用2进制形式
//always @ (posedge rclk or negedge rrst_n)
// if (~rrst_n)
// rptr <= 0;
// else
// rptr <= rgnext;
//
//always @ (*)
//begin
// for(k=0;k<ASIZE+1;k=k+1)
// rbin[k] = ^(rptr>>k);
//
// if(renable)
// rbin_next = rbin + rreq;
// else
// rbin_next = rbin;
//
// rgnext = (rbin_next>>1) ^ rbin_next;
//end
//assign raddr = rbin[ASIZE-1:0];
//-------------ram-----------------------------------------
// ram_16x4 ram_16x4
// (
// .QA (rdata),
// .AA (raddr),
// .CLKA(rclk),
// .CENA(rreq),
// .AB (waddr),
// .DB (wdata),
// .CLKB(wclk),
// .CENB(wta)
// );
//=============================================================实例化ram
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//错误,这个例子不能使用,此处的ram必须换成确保可以使用的双端口ram才行。
//reg[DSIZE-1:0]fifo[depth-1:0];
//
//always @ (posedge wclk)
//begin
// if(wta)
// fifo[waddr] <= wdata;
//end
//
//assign rdata=fifo[raddr];
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//本例中换成sysnplify生成的双端口ram
//fifowrclkram #(DSIZE,ASIZE)ram
//(
// .PortAClk (wclk)//used to write
// ,.PortAAddr (wptr)//waddr
// ,.PortADataIn (wdata)
// ,.PortAWriteEnable(wta)
// ,.PortBClk (rclk)//used to read
// ,.PortBAddr (rptrram)//rbin_next)//raddr)
// ,.PortBDataOut (rdata)//注意:读数据是经过寄存的,所以要延时1拍。
//);
//-------------compare-------------------------------------
// wire [ASIZE:0] wrptr2,rwptr2;//2位数据同步
//reg[ASIZE:0] wrptr2,rwptr2;//2位数据同步
//read-domain to write-domain synchronizer
// sync_multi_bit #(ASIZE+1) sync_rptr
// (
// .i_data(rptr),
// .o_rst_n(wrst_n),
// .o_clk(wclk),
// .o_data(wrptr2)
// );
//reg[ASIZE:0]rtow;
//always @ (posedge wclk or negedge wrst_n)
// if(!wrst_n)
// {wrptr2,rtow} <= 0;
// else
// {wrptr2,rtow} <= {rtow,rptrg};
//write-domain to read-domain synchronizer
// sync_multi_bit #(ASIZE+1) sync_wptr
// (
// .i_data(wptr),
// .o_rst_n(rrst_n),
// .o_clk(rclk),
// .o_data(rwptr2)
// );
//always @ (posedge rclk or negedge rrst_n)
// if(~rrst_n)
// {rwptr2,wtor} <= 0;
// else
// {rwptr2,wtor} <= {wtor,wptr};
//reg[ASIZE:0]wtor;
//always @ (posedge rclk or negedge rrst_n)
// if(!rrst_n)
// {rwptr2,wtor} <= 0;
// else
// {rwptr2,wtor} <= {wtor,wptrg};
//
//wire [ASIZE:0] cmprptr,cmpwptr;
//assign cmprptr = wrptr2 ^ {1'b0,wrptr2[ASIZE:1]};//[2:1]};//gray_to_bin,wclk下的rptr 2进制
//assign cmpwptr = rwptr2 ^ {1'b0,rwptr2[ASIZE:1]};//2:1]};//gray_to_bin,rclk下的wptr 2进制
//
//wire [ASIZE:0] wdata_count,rdata_count;
// assign wdata_count = {cmprptr[2]^wbin[2],wbin[1:0]} - {1'b0,cmprptr[1:0]}; //wclk下求解count
// assign rdata_count = {rbin[2]^cmpwptr[2],cmpwptr[1:0]} - {1'b0,rbin[1:0]};//rclk下求解count
//assign wdata_count = {cmprptr[ASIZE]^wptr[ASIZE],wptr[ASIZE-1:0]} - {1'b0,cmprptr[ASIZE-1:0]}; //wclk下求解count
//assign rdata_count = {rptr[ASIZE]^cmpwptr[ASIZE],cmpwptr[ASIZE-1:0]} - {1'b0,rptr[ASIZE-1:0]};//rclk下求解count
//上面的异或是为了生成四个象限,由于只有4个单元,指针只需2位就可表示,而最高位[2]
//实际上就是指示翻转次数
// assign wfull = (wdata_count == 3'd4);
// assign rempty = (rdata_count == 3'd0);
//assign wenable = (wdata_count != depth);//3'd4);
//assign renable = (rdata_count != 3'd0);
//
//
//endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -