lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | // |
| 5 | // Generic synchronous fifo for use in a variety of devices. |
| 6 | |
Greg Chadwick | cf42308 | 2020-02-05 16:52:23 +0000 | [diff] [blame] | 7 | `include "prim_assert.sv" |
| 8 | |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 9 | module prim_fifo_sync #( |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 10 | parameter int unsigned Width = 16, |
| 11 | parameter bit Pass = 1'b1, // if == 1 allow requests to pass through empty FIFO |
| 12 | parameter int unsigned Depth = 4, |
Scott Johnson | b7c9e3b | 2020-01-03 14:46:50 -0800 | [diff] [blame] | 13 | // derived parameter |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 14 | localparam int unsigned DepthWNorm = $clog2(Depth+1), |
Scott Johnson | b7c9e3b | 2020-01-03 14:46:50 -0800 | [diff] [blame] | 15 | localparam int unsigned DepthW = (DepthWNorm == 0) ? 1 : DepthWNorm |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 16 | ) ( |
| 17 | input clk_i, |
| 18 | input rst_ni, |
Michael Schaffner | 44242c4 | 2019-10-29 09:14:22 -0700 | [diff] [blame] | 19 | // synchronous clear / flush port |
| 20 | input clr_i, |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 21 | // write port |
| 22 | input wvalid, |
| 23 | output wready, |
| 24 | input [Width-1:0] wdata, |
| 25 | // read port |
| 26 | output rvalid, |
| 27 | input rready, |
| 28 | output [Width-1:0] rdata, |
| 29 | // occupancy |
| 30 | output [DepthW-1:0] depth |
| 31 | ); |
| 32 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 33 | // FIFO is in complete passthrough mode |
| 34 | if (Depth == 0) begin : gen_passthru_fifo |
| 35 | `ASSERT_INIT(paramCheckPass, Pass == 1) |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 36 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 37 | assign depth = 1'b0; //output is meaningless |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 38 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 39 | // devie facing |
| 40 | assign rvalid = wvalid; |
| 41 | assign rdata = wdata; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 42 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 43 | // host facing |
| 44 | assign wready = rready; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 45 | |
Michael Schaffner | 1ba89b8 | 2019-11-03 14:25:54 -0800 | [diff] [blame] | 46 | // this avoids lint warnings |
| 47 | logic unused_clr; |
| 48 | assign unused_clr = clr_i; |
| 49 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 50 | // Normal FIFO construction |
| 51 | end else begin : gen_normal_fifo |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 52 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 53 | // consider Depth == 1 case when $clog2(1) == 0 |
| 54 | localparam int unsigned PTRV_W = $clog2(Depth) + ~|$clog2(Depth); |
| 55 | localparam int unsigned PTR_WIDTH = PTRV_W+1; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 56 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 57 | logic [PTR_WIDTH-1:0] fifo_wptr, fifo_rptr; |
| 58 | logic fifo_incr_wptr, fifo_incr_rptr, fifo_empty; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 59 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 60 | // create the write and read pointers |
| 61 | logic full, empty; |
| 62 | logic wptr_msb; |
| 63 | logic rptr_msb; |
| 64 | logic [PTRV_W-1:0] wptr_value; |
| 65 | logic [PTRV_W-1:0] rptr_value; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 66 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 67 | assign wptr_msb = fifo_wptr[PTR_WIDTH-1]; |
| 68 | assign rptr_msb = fifo_rptr[PTR_WIDTH-1]; |
| 69 | assign wptr_value = fifo_wptr[0+:PTRV_W]; |
| 70 | assign rptr_value = fifo_rptr[0+:PTRV_W]; |
| 71 | assign depth = (full) ? DepthW'(Depth) : |
| 72 | (wptr_msb == rptr_msb) ? DepthW'(wptr_value) - DepthW'(rptr_value) : |
| 73 | (DepthW'(Depth) - DepthW'(rptr_value) + DepthW'(wptr_value)) ; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 74 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 75 | assign fifo_incr_wptr = wvalid & wready; |
| 76 | assign fifo_incr_rptr = rvalid & rready; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 77 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 78 | assign wready = ~full; |
| 79 | assign rvalid = ~empty; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 80 | |
Michael Schaffner | 44242c4 | 2019-10-29 09:14:22 -0700 | [diff] [blame] | 81 | always_ff @(posedge clk_i or negedge rst_ni) begin |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 82 | if (!rst_ni) begin |
| 83 | fifo_wptr <= {(PTR_WIDTH){1'b0}}; |
Michael Schaffner | 44242c4 | 2019-10-29 09:14:22 -0700 | [diff] [blame] | 84 | end else if (clr_i) begin |
| 85 | fifo_wptr <= {(PTR_WIDTH){1'b0}}; |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 86 | end else if (fifo_incr_wptr) begin |
| 87 | if (fifo_wptr[PTR_WIDTH-2:0] == (Depth-1)) begin |
| 88 | fifo_wptr <= {~fifo_wptr[PTR_WIDTH-1],{(PTR_WIDTH-1){1'b0}}}; |
| 89 | end else begin |
| 90 | fifo_wptr <= fifo_wptr + {{(PTR_WIDTH-1){1'b0}},1'b1}; |
Michael Schaffner | 44242c4 | 2019-10-29 09:14:22 -0700 | [diff] [blame] | 91 | end |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 92 | end |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 93 | end |
| 94 | |
Michael Schaffner | 44242c4 | 2019-10-29 09:14:22 -0700 | [diff] [blame] | 95 | always_ff @(posedge clk_i or negedge rst_ni) begin |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 96 | if (!rst_ni) begin |
| 97 | fifo_rptr <= {(PTR_WIDTH){1'b0}}; |
Michael Schaffner | 44242c4 | 2019-10-29 09:14:22 -0700 | [diff] [blame] | 98 | end else if (clr_i) begin |
| 99 | fifo_rptr <= {(PTR_WIDTH){1'b0}}; |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 100 | end else if (fifo_incr_rptr) begin |
| 101 | if (fifo_rptr[PTR_WIDTH-2:0] == (Depth-1)) begin |
| 102 | fifo_rptr <= {~fifo_rptr[PTR_WIDTH-1],{(PTR_WIDTH-1){1'b0}}}; |
| 103 | end else begin |
| 104 | fifo_rptr <= fifo_rptr + {{(PTR_WIDTH-1){1'b0}},1'b1}; |
Michael Schaffner | 44242c4 | 2019-10-29 09:14:22 -0700 | [diff] [blame] | 105 | end |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 106 | end |
| 107 | end |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 108 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 109 | assign full = (fifo_wptr == (fifo_rptr ^ {1'b1,{(PTR_WIDTH-1){1'b0}}})); |
| 110 | assign fifo_empty = (fifo_wptr == fifo_rptr); |
| 111 | |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 112 | |
Michael Schaffner | 9e2f893 | 2019-10-16 20:24:46 -0700 | [diff] [blame] | 113 | // the generate blocks below are needed to avoid lint errors due to array indexing |
| 114 | // in the where the fifo only has one storage element |
Michael Schaffner | fd7d5d4 | 2020-01-22 11:46:53 -0800 | [diff] [blame] | 115 | logic [Depth-1:0][Width-1:0] storage; |
Michael Schaffner | 9e2f893 | 2019-10-16 20:24:46 -0700 | [diff] [blame] | 116 | logic [Width-1:0] storage_rdata; |
| 117 | if (Depth == 1) begin : gen_depth_eq1 |
| 118 | assign storage_rdata = storage[0]; |
| 119 | |
| 120 | always_ff @(posedge clk_i) |
| 121 | if (fifo_incr_wptr) begin |
| 122 | storage[0] <= wdata; |
| 123 | end |
| 124 | // fifo with more than one storage element |
| 125 | end else begin : gen_depth_gt1 |
| 126 | assign storage_rdata = storage[fifo_rptr[PTR_WIDTH-2:0]]; |
| 127 | |
| 128 | always_ff @(posedge clk_i) |
| 129 | if (fifo_incr_wptr) begin |
| 130 | storage[fifo_wptr[PTR_WIDTH-2:0]] <= wdata; |
| 131 | end |
| 132 | end |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 133 | |
| 134 | if (Pass == 1'b1) begin : gen_pass |
Michael Schaffner | 9e2f893 | 2019-10-16 20:24:46 -0700 | [diff] [blame] | 135 | assign rdata = (fifo_empty && wvalid) ? wdata : storage_rdata; |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 136 | assign empty = fifo_empty & ~wvalid; |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 137 | end else begin : gen_nopass |
Michael Schaffner | 9e2f893 | 2019-10-16 20:24:46 -0700 | [diff] [blame] | 138 | assign rdata = storage_rdata; |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 139 | assign empty = fifo_empty; |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 140 | end |
| 141 | |
Greg Chadwick | 46ede4b | 2020-01-14 12:46:39 +0000 | [diff] [blame] | 142 | `ASSERT(depthShallNotExceedParamDepth, !empty |-> depth <= DepthW'(Depth)) |
Timothy Chen | 61e25e8 | 2019-09-13 14:04:10 -0700 | [diff] [blame] | 143 | end // block: gen_normal_fifo |
| 144 | |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 145 | |
Michael Schaffner | 498b1a9 | 2019-12-06 12:31:46 -0800 | [diff] [blame] | 146 | ////////////////////// |
| 147 | // Known Assertions // |
| 148 | ////////////////////// |
| 149 | |
Greg Chadwick | 46ede4b | 2020-01-14 12:46:39 +0000 | [diff] [blame] | 150 | `ASSERT(DataKnown_A, rvalid |-> !$isunknown(rdata)) |
| 151 | `ASSERT_KNOWN(DepthKnown_A, depth) |
| 152 | `ASSERT_KNOWN(RvalidKnown_A, rvalid) |
| 153 | `ASSERT_KNOWN(WreadyKnown_A, wready) |
Michael Schaffner | 498b1a9 | 2019-12-06 12:31:46 -0800 | [diff] [blame] | 154 | |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 155 | endmodule |