| 1 | ///////////////////////////////////////////////////////////////////// |
| 2 | //// //// |
| 3 | //// Universal FIFO Single Clock //// |
| 4 | //// //// |
| 5 | //// //// |
| 6 | //// Author: Rudolf Usselmann //// |
| 7 | //// rudi@asics.ws //// |
| 8 | //// //// |
| 9 | //// //// |
| 10 | //// D/L from: http://www.opencores.org/cores/generic_fifos/ //// |
| 11 | //// //// |
| 12 | ///////////////////////////////////////////////////////////////////// |
| 13 | //// //// |
| 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// |
| 15 | //// www.asics.ws //// |
| 16 | //// rudi@asics.ws //// |
| 17 | //// //// |
| 18 | //// This source file may be used and distributed without //// |
| 19 | //// restriction provided that this copyright statement is not //// |
| 20 | //// removed from the file and that any derivative work contains //// |
| 21 | //// the original copyright notice and the associated disclaimer.//// |
| 22 | //// //// |
| 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
| 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
| 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
| 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
| 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
| 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
| 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
| 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
| 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
| 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
| 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
| 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
| 35 | //// POSSIBILITY OF SUCH DAMAGE. //// |
| 36 | //// //// |
| 37 | ///////////////////////////////////////////////////////////////////// |
| 38 | |
| 39 | // CVS Log |
| 40 | // |
| 41 | // $Id: generic_fifo_sc_a.v,v 1.1.1.1 2002-09-25 05:42:06 rudi Exp $ |
| 42 | // |
| 43 | // $Date: 2002-09-25 05:42:06 $ |
| 44 | // $Revision: 1.1.1.1 $ |
| 45 | // $Author: rudi $ |
| 46 | // $Locker: $ |
| 47 | // $State: Exp $ |
| 48 | // |
| 49 | // Change History: |
| 50 | // $Log: not supported by cvs2svn $ |
| 51 | // |
| 52 | // |
| 53 | // |
| 54 | // |
| 55 | // |
| 56 | // |
| 57 | // |
| 58 | // |
| 59 | // |
| 60 | // |
| 61 | |
| 62 | `timescale 1ns / 100ps |
| 63 | `include "generic_dpram.v" |
| 64 | |
| 65 | /* |
| 66 | |
| 67 | Description |
| 68 | =========== |
| 69 | |
| 70 | I/Os |
| 71 | ---- |
| 72 | rst low active, either sync. or async. master reset (see below how to select) |
| 73 | clr synchronous clear (just like reset but always synchronous), high active |
| 74 | re read enable, synchronous, high active |
| 75 | we read enable, synchronous, high active |
| 76 | din Data Input |
| 77 | dout Data Output |
| 78 | |
| 79 | full Indicates the FIFO is full (combinatorial output) |
| 80 | full_r same as above, but registered output (see note below) |
| 81 | empty Indicates the FIFO is empty |
| 82 | empty_r same as above, but registered output (see note below) |
| 83 | |
| 84 | full_n Indicates if the FIFO has space for N entries (combinatorial output) |
| 85 | full_n_r same as above, but registered output (see note below) |
| 86 | empty_n Indicates the FIFO has at least N entries (combinatorial output) |
| 87 | empty_n_r same as above, but registered output (see note below) |
| 88 | |
| 89 | level indicates the FIFO level: |
| 90 | 2'b00 0-25% full |
| 91 | 2'b01 25-50% full |
| 92 | 2'b10 50-75% full |
| 93 | 2'b11 %75-100% full |
| 94 | |
| 95 | combinatorial vs. registered status outputs |
| 96 | ------------------------------------------- |
| 97 | Both the combinatorial and registered status outputs have exactly the same |
| 98 | synchronous timing. Meaning they are being asserted immediately at the clock |
| 99 | edge after the last read or write. The combinatorial outputs however, pass |
| 100 | through several levels of logic before they are output. The registered status |
| 101 | outputs are direct outputs of a flip-flop. The reason both are provided, is |
| 102 | that the registered outputs require quite a bit of additional logic inside |
| 103 | the FIFO. If you can meet timing of your device with the combinatorial |
| 104 | outputs, use them ! The FIFO will be smaller. If the status signals are |
| 105 | in the critical pass, use the registered outputs, they have a much smaller |
| 106 | output delay (actually only Tcq). |
| 107 | |
| 108 | Parameters |
| 109 | ---------- |
| 110 | The FIFO takes 3 parameters: |
| 111 | dw Data bus width |
| 112 | aw Address bus width (Determines the FIFO size by evaluating 2^aw) |
| 113 | n N is a second status threshold constant for full_n and empty_n |
| 114 | If you have no need for the second status threshold, do not |
| 115 | connect the outputs and the logic should be removed by your |
| 116 | synthesis tool. |
| 117 | |
| 118 | Synthesis Results |
| 119 | ----------------- |
| 120 | In a Spartan 2e a 8 bit wide, 8 entries deep FIFO, takes 85 LUTs and runs |
| 121 | at about 116 MHz (IO insertion disabled). The registered status outputs |
| 122 | are valid after 2.1NS, the combinatorial once take out to 6.5 NS to be |
| 123 | available. |
| 124 | |
| 125 | |
| 126 | Misc |
| 127 | ---- |
| 128 | This design assumes you will do appropriate status checking externally. |
| 129 | |
| 130 | IMPORTANT ! writing while the FIFO is full or reading while the FIFO is |
| 131 | empty will place the FIFO in an undefined state. |
| 132 | |
| 133 | */ |
| 134 | |
| 135 | |
| 136 | // Selecting Sync. or Async Reset |
| 137 | // ------------------------------ |
| 138 | // Uncomment one of the two lines below. The first line for |
| 139 | // synchronous reset, the second for asynchronous reset |
| 140 | |
| 141 | `define SC_FIFO_ASYNC_RESET // Uncomment for Syncr. reset |
| 142 | //`define SC_FIFO_ASYNC_RESET or negedge rst // Uncomment for Async. reset |
| 143 | |
| 144 | |
| 145 | module generic_fifo_sc_a(clk, rst, clr, din, we, dout, re, |
| 146 | full, empty, full_r, empty_r, |
| 147 | full_n, empty_n, full_n_r, empty_n_r, |
| 148 | level); |
| 149 | |
| 150 | parameter dw=8; |
| 151 | parameter aw=8; |
| 152 | parameter n=32; |
| 153 | parameter max_size = 1<<aw; |
| 154 | |
| 155 | input clk, rst, clr; |
| 156 | input [dw-1:0] din; |
| 157 | input we; |
| 158 | output [dw-1:0] dout; |
| 159 | input re; |
| 160 | output full, full_r; |
| 161 | output empty, empty_r; |
| 162 | output full_n, full_n_r; |
| 163 | output empty_n, empty_n_r; |
| 164 | output [1:0] level; |
| 165 | |
| 166 | //////////////////////////////////////////////////////////////////// |
| 167 | // |
| 168 | // Local Wires |
| 169 | // |
| 170 | |
| 171 | reg [aw-1:0] wp; |
| 172 | wire [aw-1:0] wp_pl1; |
| 173 | wire [aw-1:0] wp_pl2; |
| 174 | reg [aw-1:0] rp; |
| 175 | wire [aw-1:0] rp_pl1; |
| 176 | reg full_r; |
| 177 | reg empty_r; |
| 178 | reg gb; |
| 179 | reg gb2; |
| 180 | reg [aw:0] cnt; |
| 181 | wire full_n, empty_n; |
| 182 | reg full_n_r, empty_n_r; |
| 183 | |
| 184 | //////////////////////////////////////////////////////////////////// |
| 185 | // |
| 186 | // Memory Block |
| 187 | // |
| 188 | |
| 189 | generic_dpram #(aw,dw) u0( |
| 190 | .rclk( clk ), |
| 191 | .rrst( !rst ), |
| 192 | .rce( 1'b1 ), |
| 193 | .oe( 1'b1 ), |
| 194 | .raddr( rp ), |
| 195 | .do( dout ), |
| 196 | .wclk( clk ), |
| 197 | .wrst( !rst ), |
| 198 | .wce( 1'b1 ), |
| 199 | .we( we ), |
| 200 | .waddr( wp ), |
| 201 | .di( din ) |
| 202 | ); |
| 203 | |
| 204 | //////////////////////////////////////////////////////////////////// |
| 205 | // |
| 206 | // Misc Logic |
| 207 | // |
| 208 | |
| 209 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 210 | if(!rst) wp <= #1 {aw{1'b0}}; |
| 211 | else |
| 212 | if(clr) wp <= #1 {aw{1'b0}}; |
| 213 | else |
| 214 | if(we) wp <= #1 wp_pl1; |
| 215 | |
| 216 | assign wp_pl1 = wp + { {aw-1{1'b0}}, 1'b1}; |
| 217 | assign wp_pl2 = wp + { {aw-2{1'b0}}, 2'b10}; |
| 218 | |
| 219 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 220 | if(!rst) rp <= #1 {aw{1'b0}}; |
| 221 | else |
| 222 | if(clr) rp <= #1 {aw{1'b0}}; |
| 223 | else |
| 224 | if(re) rp <= #1 rp_pl1; |
| 225 | |
| 226 | assign rp_pl1 = rp + { {aw-1{1'b0}}, 1'b1}; |
| 227 | |
| 228 | //////////////////////////////////////////////////////////////////// |
| 229 | // |
| 230 | // Combinatorial Full & Empty Flags |
| 231 | // |
| 232 | |
| 233 | assign empty = ((wp == rp) & !gb); |
| 234 | assign full = ((wp == rp) & gb); |
| 235 | |
| 236 | // Guard Bit ... |
| 237 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 238 | if(!rst) gb <= #1 1'b0; |
| 239 | else |
| 240 | if(clr) gb <= #1 1'b0; |
| 241 | else |
| 242 | if((wp_pl1 == rp) & we) gb <= #1 1'b1; |
| 243 | else |
| 244 | if(re) gb <= #1 1'b0; |
| 245 | |
| 246 | //////////////////////////////////////////////////////////////////// |
| 247 | // |
| 248 | // Registered Full & Empty Flags |
| 249 | // |
| 250 | |
| 251 | // Guard Bit ... |
| 252 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 253 | if(!rst) gb2 <= #1 1'b0; |
| 254 | else |
| 255 | if(clr) gb2 <= #1 1'b0; |
| 256 | else |
| 257 | if((wp_pl2 == rp) & we) gb2 <= #1 1'b1; |
| 258 | else |
| 259 | if((wp != rp) & re) gb2 <= #1 1'b0; |
| 260 | |
| 261 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 262 | if(!rst) full_r <= #1 1'b0; |
| 263 | else |
| 264 | if(clr) full_r <= #1 1'b0; |
| 265 | else |
| 266 | if(we & ((wp_pl1 == rp) & gb2) & !re) full_r <= #1 1'b1; |
| 267 | else |
| 268 | if(re & ((wp_pl1 != rp) | !gb2) & !we) full_r <= #1 1'b0; |
| 269 | |
| 270 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 271 | if(!rst) empty_r <= #1 1'b1; |
| 272 | else |
| 273 | if(clr) empty_r <= #1 1'b1; |
| 274 | else |
| 275 | if(we & ((wp != rp_pl1) | gb2) & !re) empty_r <= #1 1'b0; |
| 276 | else |
| 277 | if(re & ((wp == rp_pl1) & !gb2) & !we) empty_r <= #1 1'b1; |
| 278 | |
| 279 | //////////////////////////////////////////////////////////////////// |
| 280 | // |
| 281 | // Combinatorial Full_n & Empty_n Flags |
| 282 | // |
| 283 | |
| 284 | assign empty_n = cnt < n; |
| 285 | assign full_n = !(cnt < (max_size-n+1)); |
| 286 | assign level = {2{cnt[aw]}} | cnt[aw-1:aw-2]; |
| 287 | |
| 288 | // N entries status |
| 289 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 290 | if(!rst) cnt <= #1 {aw+1{1'b0}}; |
| 291 | else |
| 292 | if(clr) cnt <= #1 {aw+1{1'b0}}; |
| 293 | else |
| 294 | if( re & !we) cnt <= #1 cnt + { {aw{1'b1}}, 1'b1}; |
| 295 | else |
| 296 | if(!re & we) cnt <= #1 cnt + { {aw{1'b0}}, 1'b1}; |
| 297 | |
| 298 | //////////////////////////////////////////////////////////////////// |
| 299 | // |
| 300 | // Registered Full_n & Empty_n Flags |
| 301 | // |
| 302 | |
| 303 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 304 | if(!rst) empty_n_r <= #1 1'b1; |
| 305 | else |
| 306 | if(clr) empty_n_r <= #1 1'b1; |
| 307 | else |
| 308 | if(we & (cnt >= (n-1) ) & !re) empty_n_r <= #1 1'b0; |
| 309 | else |
| 310 | if(re & (cnt <= n ) & !we) empty_n_r <= #1 1'b1; |
| 311 | |
| 312 | always @(posedge clk `SC_FIFO_ASYNC_RESET) |
| 313 | if(!rst) full_n_r <= #1 1'b0; |
| 314 | else |
| 315 | if(clr) full_n_r <= #1 1'b0; |
| 316 | else |
| 317 | if(we & (cnt >= (max_size-n) ) & !re) full_n_r <= #1 1'b1; |
| 318 | else |
| 319 | if(re & (cnt <= (max_size-n+1)) & !we) full_n_r <= #1 1'b0; |
| 320 | |
| 321 | //////////////////////////////////////////////////////////////////// |
| 322 | // |
| 323 | // Sanity Check |
| 324 | // |
| 325 | |
| 326 | // synopsys translate_off |
| 327 | always @(posedge clk) |
| 328 | if(we & full) |
| 329 | $display("%m WARNING: Writing while fifo is FULL (%t)",$time); |
| 330 | |
| 331 | always @(posedge clk) |
| 332 | if(re & empty) |
| 333 | $display("%m WARNING: Reading while fifo is EMPTY (%t)",$time); |
| 334 | // synopsys translate_on |
| 335 | endmodule |