diff --git a/src/uncore/fifo/fifo.sv b/src/uncore/fifo/fifo.sv new file mode 100644 index 000000000..b6f3fcdc3 --- /dev/null +++ b/src/uncore/fifo/fifo.sv @@ -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 + + + + diff --git a/src/uncore/fifo/fifomem.sv b/src/uncore/fifo/fifomem.sv new file mode 100644 index 000000000..3e3665c0d --- /dev/null +++ b/src/uncore/fifo/fifomem.sv @@ -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 diff --git a/src/uncore/fifo/rptr_empty.sv b/src/uncore/fifo/rptr_empty.sv new file mode 100644 index 000000000..68ec5cb6e --- /dev/null +++ b/src/uncore/fifo/rptr_empty.sv @@ -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 diff --git a/src/uncore/fifo/sync_r2w.sv b/src/uncore/fifo/sync_r2w.sv new file mode 100644 index 000000000..97ac299a7 --- /dev/null +++ b/src/uncore/fifo/sync_r2w.sv @@ -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 diff --git a/src/uncore/fifo/sync_w2r.sv b/src/uncore/fifo/sync_w2r.sv new file mode 100644 index 000000000..f186968be --- /dev/null +++ b/src/uncore/fifo/sync_w2r.sv @@ -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 diff --git a/src/uncore/fifo/wptr_full.sv b/src/uncore/fifo/wptr_full.sv new file mode 100644 index 000000000..a6f4fdf9f --- /dev/null +++ b/src/uncore/fifo/wptr_full.sv @@ -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 + +