异步fifo
这个是基于RAM的异步FIFO代码,个人认为代码结构简单易懂,非常适合于考试中填写。与同步fifo相比增加了读写控制信号的跨时钟域的同步。此外,判空与判满的也稍有不同。
module fifo #( parameter DSIZE = 8, ASIZE = 4 ) ( input [DSIZE-1:0] wdata, input winc, wclk, wrst_n, input rinc, rclk, rrst_n, output [DSIZE-1:0] rdata, output reg wfull, output reg 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<<ASIZE)-1]; wire [ASIZE-1:0] waddr, raddr; wire [ASIZE:0] rgraynext, rbinnext,wgraynext,wbinnext; wire rempty_val,wfull_val; //-----------------双口RAM存储器-------------------- assign rdata=mem[raddr]; always @(posedge wclk) if (winc && !wfull) mem[waddr] <= wdata; //-------------同步rptr 指针------------------------- always @(posedge wclk or negedge wrst_n) if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0; else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr}; //-------------同步wptr指针--------------------------- always @(posedge rclk or negedge rrst_n) if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0; else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr}; //-------------rempty产生与raddr产生------------------- always @(posedge rclk or negedge rrst_n) // GRAYSTYLE2 pointer begin if (!rrst_n) {rbin, rptr} <= 0; else {rbin, rptr} <= {rbinnext, rgraynext}; end // Memory read-address pointer (okay to use binary to address memory) assign raddr = rbin[ASIZE-1:0]; assign rbinnext = rbin + (rinc & ~rempty); assign rgraynext = (rbinnext>>1) ^ rbinnext; // FIFO empty when the next rptr == synchronized wptr or on reset assign rempty_val = (rgraynext == rq2_wptr); always @(posedge rclk or negedge rrst_n) begin if (!rrst_n) rempty <= 1'b1; else rempty <= rempty_val; end //---------------wfull产生与waddr产生------------------------------ always @(posedge wclk or negedge wrst_n) // GRAYSTYLE2 pointer if (!wrst_n) {wbin, wptr} <= 0; else {wbin, wptr} <= {wbinnext, wgraynext}; // Memory write-address pointer (okay to use binary to address memory) assign waddr = wbin[ASIZE-1:0]; assign wbinnext = wbin + (winc & ~wfull); assign wgraynext = (wbinnext>>1) ^ wbinnext; assign wfull_val = (wgraynext=={~wq2_rptr[ASIZE:ASIZE-1], wq2_rptr[ASIZE-2:0]}); //:ASIZE-1] always @(posedge wclk or negedge wrst_n) if (!wrst_n) wfull <= 1'b0; else wfull <= wfull_val; endmodule
参考文章:Clifford E. Cummings http://www.sunburst-design.com/papers/
http://www.cnblogs.com/qiweiwang/archive/2011/04/09/2010591.html
http://www.cnblogs.com/qiweiwang/archive/2011/04/09/2010591.html
路漫漫其修远兮,吾将上下而求索