// FIFO的verilog实现
module fifo1 (rdata, wfull, rempty, wdata,
winc, wclk, wrst_n, rinc, rclk, rrst_n);
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, wrptr2, rwptr2;
sync_r2w sync_r2w
(.wrptr2(wrptr2),
.rptr(rptr),
.wclk(wclk),
.wrst_n(wrst_n));
sync_w2r sync_w2r
(.rwptr2(rwptr2),
.wptr(wptr),
.rclk(rclk),
.rrst_n(rrst_n));
fifomem #(DSIZE, ASIZE) fifomem
(.rdata(rdata),
.wdata(wdata),
.waddr(waddr),
.raddr(raddr),
.wclken(winc),
.wclk(wclk));
rptr_empty #(ASIZE) rptr_empty
(.rempty(rempty),
.raddr(raddr),
.rptr(rptr),
.rwptr2(rwptr2),
.rinc(rinc),
.rclk(rclk),
.rrst_n(rrst_n));
wptr_full #(ASIZE) wptr_full
(.wfull(wfull),
.waddr(waddr),
.wptr(wptr),
.wrptr2(wrptr2),
.winc(winc),
.wclk(wclk),
.wrst_n(wrst_n));
endmodule
module fifomem (rdata, wdata, waddr, raddr, wclken, wclk);
parameter DATASIZE = 8; // Memory data word width
parameter ADDRSIZE = 4; // Number of memory address bits
output [DATASIZE-1:0] rdata;
input [DATASIZE-1:0] wdata;
input [ADDRSIZE-1:0] waddr, raddr;
input wclken, wclk;
`ifdef VENDORRAM
// instantiation of a vendor's dual-port RAM
VENDOR_RAM MEM (.dout(rdata), .din(wdata),
.waddr(waddr), .raddr(raddr),
.wclken(wclken), .clk(wclk));
`else
reg [DATASIZE-1:0] MEM [0:(1<<ADDRSIZE)-1];
assign rdata = MEM[raddr];
always @(posedge wclk)
if (wclken) MEM[waddr] <= wdata;
`endif
endmodule
module sync_r2w (wrptr2, rptr, wclk, wrst_n);
parameter ADDRSIZE = 4;
output [ADDRSIZE:0] wrptr2;
input [ADDRSIZE:0] rptr;
input wclk, wrst_n;
reg [ADDRSIZE:0] wrptr2, wrptr1;
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) {wrptr2,wrptr1} <= 0;
else {wrptr2,wrptr1} <= {wrptr1,rptr};
endmodule
module sync_w2r (rwptr2, wptr, rclk, rrst_n);
parameter ADDRSIZE = 4;
output [ADDRSIZE:0] rwptr2;
input [ADDRSIZE:0] wptr;
input rclk, rrst_n;
reg [ADDRSIZE:0] rwptr2, rwptr1;
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) {rwptr2,rwptr1} <= 0;
else {rwptr2,rwptr1} <= {rwptr1,wptr};
endmodule
module rptr_empty (rempty, raddr, rptr, rwptr2, rinc, rclk, rrst_n);
parameter ADDRSIZE = 4;
output rempty;
output [ADDRSIZE-1:0] raddr;
output [ADDRSIZE:0] rptr;
input [ADDRSIZE:0] rwptr2;
input rinc, rclk, rrst_n;
reg [ADDRSIZE:0] rptr, rbin, rgnext, rbnext;
reg rempty, raddrmsb;
//-------------------
// GRAYSTYLE1 pointer
//-------------------
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) begin
rptr <= 0;
raddrmsb <= 0;
end
else begin
rptr <= rgnext;
raddrmsb <= rgnext[ADDRSIZE]^rgnext[ADDRSIZE-1];
end
always @(rptr or rinc) begin: Gray_inc
integer i;
for (i=0; i<=ADDRSIZE; i=i+1)
rbin[i] = ^(rptr>>i);
if (!rempty) rbnext = rbin + rinc;
else rbnext = rbin;
rgnext = (rbnext>>1) ^ rbnext;
end
// Memory read-address pointer
assign raddr = {raddrmsb,rptr[ADDRSIZE-2:0]};
//---------------------------------------------------------------
// FIFO empty on reset or when the next rptr == synchronized wptr
//---------------------------------------------------------------
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) rempty <= 1'b1;
else rempty <= (rgnext == rwptr2);
endmodule
module wptr_full (wfull, waddr, wptr, wrptr2, winc, wclk, wrst_n);
parameter ADDRSIZE = 4;
output wfull;
output [ADDRSIZE-1:0] waddr;
output [ADDRSIZE:0] wptr;
input [ADDRSIZE:0] wrptr2;
input winc, wclk, wrst_n;
reg [ADDRSIZE:0] wptr, wbin, wgnext, wbnext;
reg wfull, waddrmsb;
// GRAYSTYLE1 pointer
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) begin
wptr <= 0;
waddrmsb <= 0;
end
else begin
wptr <= wgnext;
waddrmsb <= wgnext[ADDRSIZE]^wgnext[ADDRSIZE-1];
end
always @(wptr or winc) begin: Gray_inc
integer i;
for (i=0; i<=ADDRSIZE; i=i+1)
wbin[i] = ^(wptr>>i);
if (!wfull) wbnext = wbin + winc;
else wbnext = wbin;
wgnext = (wbnext>>1) ^ wbnext;
end
// Memory write-address pointer
assign waddr = {waddrmsb,wptr[ADDRSIZE-2:0]};
wire w_2ndmsb = wgnext[ADDRSIZE] ^ wgnext[ADDRSIZE-1];
wire wr_2ndmsb = wrptr2[ADDRSIZE] ^ wrptr2[ADDRSIZE-1];
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) wfull<=0;
else wfull<=((wgnext[ADDRSIZE] !=wrptr2[ADDRSIZE]) &&
(w_2ndmsb ==wr_2ndmsb ) &&
(wgnext[ADDRSIZE-2:0]==wrptr2[ADDRSIZE-2:0]));
endmodule