框图如下:
顶层模块:
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