wire[ASIZE-1:
0]waddr,raddr;
wire[ASIZE:
0]rgraynext,rbinnext,wgraynext,wbinnext;
wirerempty_val,wfull_val;
//-----------------双口RAM存储器--------------------
assignrdata=mem[raddr];
always@(posedgewclk)
if(winc&&!
wfull)mem[waddr]<=wdata;
//-------------同步rptr指针-------------------------
always@(posedgewclkornegedgewrst_n)
if(!
wrst_n){wq2_rptr,wq1_rptr}<=0;
else{wq2_rptr,wq1_rptr}<={wq1_rptr,rptr};
//-------------同步wptr指针---------------------------
always@(posedgerclkornegedgerrst_n)
if(!
rrst_n){rq2_wptr,rq1_wptr}<=0;
else{rq2_wptr,rq1_wptr}<={rq1_wptr,wptr};
//-------------rempty产生与raddr产生-------------------
always@(posedgerclkornegedgerrst_n)//GRAYSTYLE2pointer
begin
if(!
rrst_n){rbin,rptr}<=0;
else{rbin,rptr}<={rbinnext,rgraynext};
end
//Memoryread-addresspointer(okaytousebinarytoaddressmemory)
assignraddr=rbin[ASIZE-1:
0];
assignrbinnext=rbin+(rinc&~rempty);
assignrgraynext=(rbinnext>>1)^rbinnext;
//FIFOemptywhenthenextrptr==synchronizedwptroronreset
assignrempty_val=(rgraynext==rq2_wptr);
always@(posedgerclkornegedgerrst_n)
begin
if(!
rrst_n)rempty<=1'b1;
elserempty<=rempty_val;
end
//---------------wfull产生与waddr产生------------------------------
always@(posedgewclkornegedgewrst_n)//GRAYSTYLE2pointer
if(!
wrst_n){wbin,wptr}<=0;
else{wbin,wptr}<={wbinnext,wgraynext};
//Memorywrite-addresspointer(okaytousebinarytoaddressmemory)
assignwaddr=wbin[ASIZE-1:
0];
assignwbinnext=wbin+(winc&~wfull);
assignwgraynext=(wbinnext>>1)^wbinnext;
assignwfull_val=(wgraynext=={~wq2_rptr[ASIZE:
ASIZE-1],wq2_rptr[ASIZE-2:
0]});//:
ASIZE-1]
always@(posedgewclkornegedgewrst_n)
if(!
wrst_n)wfull<=1'b0;
elsewfull<=wfull_val;
endmodule
异步FIFO的Verilog代码之一
这个是基于RAM的异步FIFO代码,个人认为代码结构简单易懂,非常适合于考试中填写。
记得10月份参加威盛的笔试的时候,就考过异步FIFO的实现。
想当初要是早点复习,可能就可以通过威盛的笔试了。
与之前的用RAM实现的同步FIFO的程序相比,异步更为复杂。
增加了读写控制信号的跨时钟域的同步。
此外,判空与判满的也稍有不同。
modulefifo1(rdata,wfull,rempty,wdata,winc,wclk,wrst_n,rinc,rclk,rrst_n);
parameterDSIZE=8;parameterASIZE=4;
output[DSIZE-1:
0]rdata;
outputwfull;
outputrempty;
input[DSIZE-1:
0]wdata;
inputwinc,wclk,wrst_n;
inputrinc,rclk,rrst_n;
regwfull,rempty;
reg[ASIZE:
0]wptr,rptr,wq2_rptr,rq2_wptr,wq1_rptr,rq1_wptr;
reg[ASIZE:
0]rbin,wbin;
reg[DSIZE-1:
0]mem[0:
(1<wire[ASIZE-1:
0]waddr,raddr;
wire[ASIZE:
0]rgraynext,rbinnext,wgraynext,wbinnext;
wirerempty_val,wfull_val;
//-----------------双口RAM存储器--------------------
assignrdata=mem[raddr];
always@(posedgewclk)
if(winc&&!
wfull)mem[waddr]<=wdata;
//-------------同步rptr指针-------------------------
always@(posedgewclkornegedgewrst_n)
if(!
wrst_n){wq2_rptr,wq1_rptr}<=0;
else{wq2_rptr,wq1_rptr}<={wq1_rptr,rptr};
//-------------同步wptr指针---------------------------
always@(posedgerclkornegedgerrst_n)
if(!
rrst_n){rq2_wptr,rq1_wptr}<=0;
else{rq2_wptr,rq1_wptr}<={rq1_wptr,wptr};
//-------------rempty产生与raddr产生-------------------
always@(posedgerclkornegedgerrst_n)//GRAYSTYLE2pointer
begin
if(!
rrst_n){rbin,rptr}<=0;
else{rbin,rptr}<={rbinnext,rgraynext};
end
//Memoryread-addresspointer(okaytousebinarytoaddressmemory)
assignraddr=rbin[ASIZE-1:
0];
assignrbinnext=rbin+(rinc&~rempty);
assignrgraynext=(rbinnext>>1)^rbinnext;
//FIFOemptywhenthenextrptr==synchronizedwptroronreset
assignrempty_val=(rgraynext==rq2_wptr);
always@(posedgerclkornegedgerrst_n)
begin
if(!
rrst_n)rempty<=1'b1;
elserempty<=rempty_val;
end
//---------------wfull产生与waddr产生------------------------------
always@(posedgewclkornegedgewrst_n)//GRAYSTYLE2pointer
if(!
wrst_n){wbin,wptr}<=0;
else{wbin,wptr}<={wbinnext,wgraynext};
//Memorywrite-addresspointer(okaytousebinarytoaddressmemory)
assignwaddr=wbin[ASIZE-1:
0];
assignwbinnext=wbin+(winc&~wfull);
assignwgraynext=(wbinnext>>1)^wbinnext;
assignwfull_val=(wgraynext=={~wq2_rptr[ASIZE:
ASIZE-1],wq2_rptr[ASIZE-2:
0]});//:
ASIZE-1]
always@(posedgewclkornegedgewrst_n)
if(!
wrst_n)wfull<=1'b0;
elsewfull<=wfull_val;
endmodule
异步FIFO的Verilog实现
2010-03-2223:
28
//----------------------STYLE#1--------------------------
modulefifo1(rdata,wfull,rempty,wdata,winc,wclk,wrst_n,rinc,rclk,rrst_n);
parameterDSIZE=8;
parameterASIZE=4;
output[DSIZE-1:
0]rdata;
outputwfull;
outputrempty;
input[DSIZE-1:
0]wdata;
inputwinc,wclk,wrst_n;
inputrinc,rclk,rrst_n;
regwfull,rempty;
reg[ASIZE:
0]wptr,rptr,wq2_rptr,rq2_wptr,wq1_rptr,rq1_wptr;
reg[ASIZE:
0]rbin,wbin;
reg[DSIZE-1:
0]mem[0:
(1<wire[ASIZE-1:
0]waddr,raddr;
wire[ASIZE:
0]rgraynext,rbinnext,wgraynext,wbinnext;
wirerempty_val,wfull_val;
//-----------------双口RAM存储器--------------------
assignrdata=mem[raddr];
always@(posedgewclk)
if(winc&&!
wfull)mem[waddr]<=wdata;
//-------------同步rptr指针-------------------------
always@(posedgewclkornegedgewrst_n)
if(!
wrst_n){wq2_rptr,wq1_rptr}<=0;
else{wq2_rptr,wq1_rptr}<={wq1_rptr,rptr};
//-------------同步wptr指针---------------------------
always@(posedgerclkornegedgerrst_n)
if(!
rrst_n){rq2_wptr,rq1_wptr}<=0;
else{rq2_wptr,rq1_wptr}<={rq1_wptr,wptr};
//-------------rempty产生与raddr产生-------------------
//-------------------
//GRAYSTYLE2pointer
//-------------------
always@(posedgerclkornegedgerrst_n)
begin
if(!
rrst_n){rbin,rptr}<=0;
else{rbin,rptr}<={rbinnext,rgraynext};
end
//Memoryread-addresspointer(okaytousebinarytoaddressmemory)
assignraddr=rbin[ASIZE-1:
0];
assignrbinnext=rbin+(rinc&~rempty);
assignrgraynext=(rbinnext>>1)^rbinnext;
//---------------------------------------------------------------
//FIFOemptywhenthenextrptr==synchronizedwptroronreset
//---------------------------------------------------------------
assignrempty_val=(rgraynext==rq2_wptr);
always@(posedgerclkornegedgerrst_n)
begin
if(!
rrst_n)rempty<=1'b1;
elserempty<=rempty_val;
end
//---------------wfull产生与waddr产生------------------------------
//GRAYSTYLE2pointer
always@(posedgewclkornegedgewrst_n)
if(!
wrst_n){wbin,wptr}<=0;
else{wbin,wptr}<={wbinnext,wgraynext};
//Memorywrite-addresspointer(okaytousebinarytoaddressmemory)
assignwaddr=wbin[ASIZE-1:
0];
assignwbinnext=wbin+(winc&~wfull);
assignwgraynext=(wbinnext>>1)^wbinnext;
//------------------------------------------------------------------
//Simplifiedversionofthethreenecessaryfull-tests:
//assignwfull_val=((wgnext[ADDRSIZE]!
=wq2_rptr[ADDRSIZE])&&
//(wgnext[ADDRSIZE-1]!
=wq2_rptr[ADDRSIZE-1])&&
//(wgnext[ADDRSIZE-2:
0]==wq2_rptr[ADDRSIZE-2:
0]));
//------------------------------------------------------------------
assignwfull_val=(wgraynext=={~wq2_rptr[ASIZE:
ASIZE-1],
wq2_rptr[ASIZE-2:
0]});
always@(posedgewclkornegedgewrst_n)
if(!
wrst_n)wfull<=1'b0;
elsewfull<=wfull_val;
endmodule
//---------------------STYLE#2-------------------------
modulefifo2(rdata,wfull,rempty,wdata,
winc,wclk,wrst_n,rinc,rclk,rrst_n);
parameterDSIZE=8;
parameterASIZE=4;
output[DSIZE-1:
0]rdata;
outputwfull;
outputrempty;
input[DSIZE-1:
0]wdata;
inputwinc,wclk,wrst_n;
inputrinc,rclk,rrst_n;
wire[ASIZE-1:
0]wptr,rptr;
wire[ASIZE-1:
0]waddr,raddr;
async_cmp#(ASIZE)async_cmp(.aempty_n(aempty_n),
.afull_n(afull_n),
.wptr(wptr),.rptr(rptr),
.wrst_n(wrst_n));
fifomem2#(DSIZE,ASIZE)fifomem2(.rdata(rdata),
.wdata(wdata),
.waddr(wptr),
.raddr(rptr),
.wclken(winc),
.wclk(wclk));
rptr_empty2#(ASIZE)rptr_empty2(.rempty(rempty),
.rptr(rptr),
.aempty_n(aempty_n),
.rinc(rinc),
.rclk(rclk),
.rrst_n(rrst_n));
wptr_full2#(ASIZE)wptr_full2(.wfull(wfull),
.wptr(wptr),
.afull_n(afull_n),
.winc(winc),
.wclk(wclk),
.wrst_n(wrst_n));
endmodule
modulefifomem2(rdata,wdata,waddr,raddr,wclken,wclk);
parameterDATASIZE=8;//Memorydatawordwidth
parameterADDRSIZE=4;//Numberofmemoryaddressbits
parameterDEPTH=1<output[DATASIZE-1:
0]rdata;
input[DATASIZE-1:
0]wdata;
input[ADDRSIZE-1:
0]waddr,raddr;
inputwclken,wclk;
`ifdefVENDORRAM
//instantiationofavendor'sdual-portRAM
VENDOR_RAMMEM(.dout(rdata),.din(wdata),
.waddr(waddr),.raddr(raddr),
.wclken(wclken),.clk(wclk));
`else
reg[DATASIZE-1:
0]MEM[0:
DEPTH-1];
assignrdata=MEM[raddr];
always@(posedgewclk)
if(wclken)MEM[waddr]<=wdata;
`endif
endmodule
moduleasync_cmp(aempty_n,afull_n,wptr,rptr,wrst_n);
parameterADDRSIZE=4;
parameterN=ADDRSIZE-1;
outputaempty_n,afull_n;
input[N:
0]wptr,rptr;
inputwrst_n;
regdirection;
wirehigh=1'b1;
wiredirset_n=~((wptr[N]^rptr[N-1])&~(wptr[N-1]^rptr[N]));
wiredirclr_n=~((~(wptr[N]^rptr[N-1])&(wptr[N-1]^rptr[N]))|
~wrst_n);
always@(posedgehighornegedgedirset_nornegedgedirclr_n)
if(!
dirclr_n)direction<=1'b0;
elseif(!
dirset_n)direction<=1'b1;
elsedirection<=high;
//always@(negedgedirset_nornegedgedirclr_n)
//if(!
dirclr_n)direction<=1'b0;
//elsedirection<=1'b1;
assi