FPGA|CPLD|ASIC论坛
直播中

yangtuzi2016

8年用户 84经验值
擅长:可编程逻辑
私信 关注
[资料]

FPGA实现异步FIFO(笔记:代码和框图都来自simulation and synthesis techniques for asynchronous FIFO design这篇文章)

框图如下:
顶层模块:
module fifo1 #(parameter DSIZE=8,
                          parameter ASIZE=4)
(output [DSIZE-1:0] rdata,,
output                     wfull,
output                     rempty,
input   [DSIZE-1:0]  wdata,
input                        winc,wclk,wrst_n,
input                        rinc,rclk,rrst_n);

wire [ASIZE-1:0] waddr,raddr;
wire [ASIZE:0] wptr,rptr,wq2_rptr,rq2_wptr;

sync_r2w sync_r2w(.wq2_rptr(wq2_rptr), .rptr(rptr),
                                .wclk(wclk),.wrst_n(wrst_n));
sync_w2r sync_w2r(.rq2_wptr(rq2_wptr), .wptr(wptr),
                                .rclk(rclk),.rrst_n(rrst_n));
fifomem #(DSIZE,ASIZE) fifomem
                              (.rdata(rdata), .wdata(wdata),
                               .waddr(waddr), .raddr(raddr),
                               .wclken(winc), .wfull(wfull),
                               .wclk(wclk));
rptr_empty #(ASIZE) rptr_empty
                              (.rempty(rempty),
                               .raddr(raddr),
                               .rptr(rptr), .rq2_wptr(rq2_wptr),
                               .rinc(rinc), .rclk(rclk),
                               .rrst_n(rrst_n));
wptr_full #(ASIZE) wptr_full
                              (.wfull(wfull), .waddr(waddr),
                               .wptr(wptr), .wq2_rptr(wq2_rptr),
                               .winc(winc), .wclk(wclk),
                               .wrst_n(wrst_n));
endmodule

module fifomem #(parameter DSIZE = 8,
                                 parameter ASIZE = 4)
(output [DSIZE-1:0] rdata,
input [DSIZE-1:0] wdata,
input [ASIZE-1:0] waddr,raddr,
input                     wclken,wfull,wclk);
localparam DEPTH = 1< reg [DSIZE-1:0] mem [0:DEPTH-1];
assign rdata = mem[raddr];
always @(posedge wclk)
if(wclken && !wfull) mem[waddr] <= wdata;
endmodule


module sync_r2w #(parameter ASIZE = 4)
(output reg [ASIZE:0] wq2_rptr,
input          [ASIZE:0] rptr,
input                          wclk,wrst_n);
reg [ASIZE:0] wq1_rptr;
always @(posedge wclk or negedge wrst_n)
if(!wrt_n) {wq2_rptr,wq1_rptr} <= 0;
else         {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
endmodule


module sync_w2r #(parameter ASIZE = 4)
(output reg [ASIZE:0] rq2_wptr,
input          [ASIZE:0] wptr,
input                          rclk,rrst_n);
reg [ASIZE:0] rq1_wptr;
always @(posedge rclk or negedge rrst_n)
if(!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
else         {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
endmodule


module rptr_empty #(parameter ASIZE = 4)
(output reg rempty,
output [ASIZE-1:0] raddr,
output reg [ASZIE :0] rptr,
input [ASIZE :0] rq2_wptr,
input                  rinc,rclk,rrst_n);
reg [ASZIE:0] rbin;
wire[ASIZE:0] rgraynext,rbinnext;
always @(posedge rclk or negedge rrst_n)
if(!rrst_n) {rbin,rptr} <= 0;
else         {rbin,rptr} <={rbinnext,rgraynext};
assign raddr = rbin[ASZIE-1:0];
assign rbinnext = rbin + (rinc & ~rempty);
assign rgraynext = (rbinnext>>1) ^ rbinnext;


assign remty_val = (rgarynext == rq2_wptr);
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) rempty <= 1'b1;
else          rempty <= rempty_val;
endmodule


module wptr_full #(parameter ASIZE = 4)
(output reg wfull,
output [ASIZE-1:0] waddr,
output reg [ASIZE:0] wptr,
input [ASIZE:0] wq2_rptr,
input    winc,wclk,wrst_n);
reg [ASIZE:0] wbin;
wire [ASIZE:0] wgraynext,wbinnext;
always @(posedge wclk or negedge wrst_n)
if(!wrst_n) {wbin,wptr} <= 0;
else           {wbin,wptr}  <= {wbinnext,wgraynext};


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]});
always @(posedge wclk or negedge wrst_n)
if(!wrst_n) wfull <= 1'b0;
else           wfull <= wfull_val;
endmodule
  • 1.jpg

更多回帖

发帖
×
20
完善资料,
赚取积分