uncore: Add fifo

This commit is contained in:
Marcus Mellor 2024-02-28 16:03:26 -06:00
parent b05893647f
commit dec30b4d99
6 changed files with 180 additions and 0 deletions

43
src/uncore/fifo/fifo.sv Normal file
View File

@ -0,0 +1,43 @@
module fifo #(parameter DSIZE = 8,
parameter ASIZE = 4)
(rdata, wfull, rempty, wdata,
winc, wclk, wrst_n, rinc, rclk, rrst_n);
input logic [DSIZE-1:0] wdata;
input logic winc;
input logic wclk;
input logic wrst_n;
input logic rinc;
input logic rclk;
input logic rrst_n;
output logic [DSIZE-1:0] rdata;
output logic wfull;
output logic rempty;
logic [ASIZE-1:0] waddr, raddr;
logic [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 // fifo1

View File

@ -0,0 +1,24 @@
// DATASIZE = Memory data word width
// ADDRSIZE = Number of mem address bits
module fifomem #(parameter DATASIZE = 8,
parameter ADDRSIZE = 4)
(rdata, wdata, waddr, raddr, wclken, wfull, wclk);
input logic [DATASIZE-1:0] wdata;
input logic [ADDRSIZE-1:0] waddr;
input logic [ADDRSIZE-1:0] raddr;
input logic wclken;
input logic wfull;
input logic wclk;
output logic [DATASIZE-1:0] rdata;
// RTL Verilog memory model
localparam DEPTH = 1 << ADDRSIZE;
logic [DATASIZE-1:0] mem [0:DEPTH-1];
assign rdata = mem[raddr];
always @(posedge wclk)
if (wclken && !wfull) mem[waddr] <= wdata;
endmodule // fifomem

View File

@ -0,0 +1,37 @@
module rptr_empty #(parameter ADDRSIZE = 4)
(rempty, raddr, rptr, rq2_wptr, rinc, rclk, rrst_n);
input logic [ADDRSIZE:0] rq2_wptr;
input logic rinc;
input logic rclk;
input logic rrst_n;
output logic rempty;
output logic [ADDRSIZE-1:0] raddr;
output logic [ADDRSIZE :0] rptr;
logic [ADDRSIZE:0] rbin;
logic [ADDRSIZE:0] rgraynext;
logic [ADDRSIZE:0] rbinnext;
//-------------------
// GRAYSTYLE2 pointer
//-------------------
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) {rbin, rptr} <= 0;
else {rbin, rptr} <= {rbinnext, rgraynext};
// Memory read-address pointer (okay to use binary to address memory)
assign raddr = rbin[ADDRSIZE-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)
if (!rrst_n) rempty <= 1'b1;
else rempty <= rempty_val;
endmodule // rptr_empty

View File

@ -0,0 +1,16 @@
module sync_r2w #(parameter ADDRSIZE = 4)
(wq2_rptr, rptr, wclk, wrst_n);
input logic [ADDRSIZE:0] rptr;
input logic wclk;
input logic wrst_n;
output logic [ADDRSIZE:0] wq2_rptr;
logic [ADDRSIZE:0] wq1_rptr;
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
endmodule // sync_r2w

View File

@ -0,0 +1,16 @@
module sync_w2r #(parameter ADDRSIZE = 4)
(rq2_wptr, wptr, rclk, rrst_n);
input logic [ADDRSIZE:0] wptr;
input logic rclk;
input logic rrst_n;
output logic [ADDRSIZE:0] rq2_wptr;
logic [ADDRSIZE: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 // sync_w2r

View File

@ -0,0 +1,44 @@
module wptr_full #(parameter ADDRSIZE = 4)
(wfull, waddr, wptr, wq2_rptr, winc, wclk, wrst_n);
input logic [ADDRSIZE :0] wq2_rptr;
input logic winc;
input logic wclk;
input logic wrst_n;
output logic wfull;
output logic [ADDRSIZE-1:0] waddr;
output logic [ADDRSIZE:0] wptr;
logic [ADDRSIZE:0] wbin;
logic [ADDRSIZE:0] wgraynext;
logic [ADDRSIZE:0] wbinnext;
// GRAYSTYLE2 pointer
always @(posedge wclk or negedge wrst_n)
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[ADDRSIZE-1:0];
assign wbinnext = wbin + (winc & ~wfull);
assign wgraynext = (wbinnext>>1) ^ wbinnext;
//------------------------------------------------------------------
// Simplified version of the three necessary full-tests:
// assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) &&
// (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) &&
// (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0]));
//------------------------------------------------------------------
assign wfull_val = (wgraynext=={~wq2_rptr[ADDRSIZE:ADDRSIZE-1],
wq2_rptr[ADDRSIZE-2:0]});
always @(posedge wclk or negedge wrst_n)
if (!wrst_n)
wfull <= 1'b0;
else
wfull <= wfull_val;
endmodule // wptr_full