1 //////////////////////////////////////////////////////////////////////
3 //// File name "fifo_control.v" ////
5 //// This file is part of the "PCI bridge" project ////
6 //// http://www.opencores.org/cores/pci/ ////
9 //// - Miha Dolenc (mihad@opencores.org) ////
11 //// All additional information is avaliable in the README ////
15 //////////////////////////////////////////////////////////////////////
17 //// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org ////
19 //// This source file may be used and distributed without ////
20 //// restriction provided that this copyright statement is not ////
21 //// removed from the file and that any derivative work contains ////
22 //// the original copyright notice and the associated disclaimer. ////
24 //// This source file is free software; you can redistribute it ////
25 //// and/or modify it under the terms of the GNU Lesser General ////
26 //// Public License as published by the Free Software Foundation; ////
27 //// either version 2.1 of the License, or (at your option) any ////
28 //// later version. ////
30 //// This source is distributed in the hope that it will be ////
31 //// useful, but WITHOUT ANY WARRANTY; without even the implied ////
32 //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
33 //// PURPOSE. See the GNU Lesser General Public License for more ////
36 //// You should have received a copy of the GNU Lesser General ////
37 //// Public License along with this source; if not, download it ////
38 //// from http://www.opencores.org/lgpl.shtml ////
40 //////////////////////////////////////////////////////////////////////
42 // CVS Revision History
44 // $Log: pci_pcir_fifo_control.v,v $
45 // Revision 1.1 2007-03-20 17:50:56 sithglan
48 // Revision 1.4 2003/08/14 13:06:03 simons
49 // synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated.
51 // Revision 1.3 2003/07/29 08:20:11 mihad
52 // Found and simulated the problem in the synchronization logic.
53 // Repaired the synchronization logic in the FIFOs.
55 // Revision 1.2 2003/03/26 13:16:18 mihad
56 // Added the reset value parameter to the synchronizer flop module.
57 // Added resets to all synchronizer flop instances.
58 // Repaired initial sync value in fifos.
60 // Revision 1.1 2003/01/27 16:49:31 mihad
61 // Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed.
63 // Revision 1.7 2002/11/27 20:36:10 mihad
64 // Changed the code a bit to make it more readable.
65 // Functionality not changed in any way.
66 // More robust synchronization in fifos is still pending.
68 // Revision 1.6 2002/09/30 16:03:04 mihad
69 // Added meta flop module for easier meta stable FF identification during synthesis
71 // Revision 1.5 2002/09/25 15:53:52 mihad
72 // Removed all logic from asynchronous reset network
74 // Revision 1.4 2002/03/05 11:53:47 mihad
75 // Added some testcases, removed un-needed fifo signals
77 // Revision 1.3 2002/02/01 15:25:12 mihad
78 // Repaired a few bugs, updated specification, added test bench files and design document
80 // Revision 1.2 2001/10/05 08:14:28 mihad
81 // Updated all files with inclusion of timescale file for simulation purposes.
83 // Revision 1.1.1.1 2001/10/02 15:33:46 mihad
84 // New project directory structure
88 /* FIFO_CONTROL module provides read/write address and status generation for
89 FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
91 `include "pci_constants.v"
93 // synopsys translate_off
94 `include "timescale.v"
95 // synopsys translate_on
97 module pci_pcir_fifo_control
114 // address length parameter - depends on fifo depth
115 parameter ADDR_LENGTH = 7 ;
117 // independent clock inputs - rclock_in = read clock, wclock_in = write clock
118 input rclock_in, wclock_in;
120 // enable inputs - read address changes on rising edge of rclock_in when reads are allowed
121 // write address changes on rising edge of wclock_in when writes are allowed
122 input renable_in, wenable_in;
130 // almost empy status output
131 output almost_empty_out;
133 // full and empty status outputs
134 output full_out, empty_out;
136 // read and write addresses outputs
137 output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
139 // read and write allow outputs
140 output rallow_out, wallow_out ;
142 // read address register
143 reg [(ADDR_LENGTH - 1):0] raddr ;
145 // write address register
146 reg [(ADDR_LENGTH - 1):0] waddr;
147 assign waddr_out = waddr ;
149 // grey code registers
150 // grey code pipeline for write address
151 reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current grey coded write address
152 reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next grey coded write address
154 // next write gray address calculation - bitwise xor between address and shifted address
155 wire [(ADDR_LENGTH - 2):0] calc_wgrey_next = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
157 // grey code pipeline for read address
158 reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
159 reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
161 // next read gray address calculation - bitwise xor between address and shifted address
162 wire [(ADDR_LENGTH - 2):0] calc_rgrey_next = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
164 // FFs for registered empty and full flags
171 // write allow wire - writes are allowed when fifo is not full
172 wire wallow = wenable_in && !full ;
174 // write allow output assignment
175 assign wallow_out = wallow ;
180 // full output assignment
181 assign full_out = full ;
183 // clear generation for FFs and registers
184 wire clear = reset_in /*|| flush_in*/ ; // flush changed to synchronous operation
186 assign empty_out = empty ;
189 assign rallow = renable_in && !empty ; // reads allowed if read enable is high and FIFO is not empty
191 // rallow output assignment
192 assign rallow_out = rallow ;
194 // almost empty output assignment
195 assign almost_empty_out = almost_empty ;
197 // at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
198 // when FIFO is empty, this register provides actual read address, so first location can be read
199 reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
201 // address output mux - when FIFO is not read, current actual address is driven out, when it is read, next address is driven out to provide
202 // next data immediately
203 // done for zero wait state burst operation
204 assign raddr_out = rallow ? raddr_plus_one : raddr ;
206 always@(posedge rclock_in or posedge clear)
210 // initial values seem a bit odd - they are this way to allow easier grey pipeline implementation and to allow min fifo size of 8
211 raddr_plus_one <= #`FF_DELAY 3 ;
212 raddr <= #`FF_DELAY 2 ;
216 raddr_plus_one <= #`FF_DELAY waddr + 1'b1 ;
217 raddr <= #`FF_DELAY waddr ;
221 raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
222 raddr <= #`FF_DELAY raddr_plus_one ;
226 /*-----------------------------------------------------------------------------------------------
227 Read address control consists of Read address counter and Grey Address pipeline
228 There are 2 Grey addresses:
229 - rgrey_addr is Grey Code of current read address
230 - rgrey_next is Grey Code of next read address
231 --------------------------------------------------------------------------------------------------*/
232 // grey coded address pipeline for status generation in read clock domain
233 always@(posedge rclock_in or posedge clear)
238 rgrey_next <= #`FF_DELAY 1 ; // this grey code is calculated from the current binary address and loaded any time data is read from fifo
242 // when fifo is flushed, load the register values from the write clock domain.
243 // must be no problem, because write pointers are stable for at least 3 clock cycles before flush can occur.
244 rgrey_addr <= #1 wgrey_addr ;
245 rgrey_next <= #`FF_DELAY wgrey_next ;
249 // move the pipeline when data is read from fifo and calculate new value for first stage of pipeline from current binary fifo address
250 rgrey_addr <= #1 rgrey_next ;
251 rgrey_next <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
255 /*--------------------------------------------------------------------------------------------
256 Write address control consists of write address counter and 2 Grey Code Registers:
257 - wgrey_addr represents current Grey Coded write address
258 - wgrey_next represents Grey Coded next write address
259 ----------------------------------------------------------------------------------------------*/
260 // grey coded address pipeline for status generation in write clock domain
261 always@(posedge wclock_in or posedge clear)
266 wgrey_next <= #`FF_DELAY 1 ;
271 wgrey_addr <= #1 wgrey_next ;
272 wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
276 // write address binary counter - nothing special except initial value
277 always@(posedge wclock_in or posedge clear)
281 waddr <= #`FF_DELAY 2 ;
284 waddr <= #`FF_DELAY waddr + 1'b1 ;
287 /*------------------------------------------------------------------------------------------------------------------------------
289 Gray coded read address pointer is synchronized to write clock domain and compared to Gray coded next write address.
290 If they are equal, fifo is full.
291 --------------------------------------------------------------------------------------------------------------------------------*/
292 wire [(ADDR_LENGTH - 1):0] wclk_sync_rgrey_addr ;
293 reg [(ADDR_LENGTH - 1):0] wclk_rgrey_addr ;
294 pci_synchronizer_flop #(ADDR_LENGTH, 0) i_synchronizer_reg_rgrey_addr
296 .data_in (rgrey_addr),
297 .clk_out (wclock_in),
298 .sync_data_out (wclk_sync_rgrey_addr),
302 always@(posedge wclock_in or posedge clear)
305 wclk_rgrey_addr <= #`FF_DELAY 0 ;
307 wclk_rgrey_addr <= #`FF_DELAY wclk_sync_rgrey_addr ;
310 assign full = (wgrey_next == wclk_rgrey_addr) ;
312 /*------------------------------------------------------------------------------------------------------------------------------
314 Gray coded write address pointer is synchronized to read clock domain and compared to Gray coded read address pointer.
315 If they are equal, fifo is empty. Synchronized write pointer is also compared to Gray coded next read address. If these two are
316 equal, fifo is almost empty.
317 --------------------------------------------------------------------------------------------------------------------------------*/
318 wire [(ADDR_LENGTH - 1):0] rclk_sync_wgrey_addr ;
319 reg [(ADDR_LENGTH - 1):0] rclk_wgrey_addr ;
320 pci_synchronizer_flop #(ADDR_LENGTH, 0) i_synchronizer_reg_wgrey_addr
322 .data_in (wgrey_addr),
323 .clk_out (rclock_in),
324 .sync_data_out (rclk_sync_wgrey_addr),
328 always@(posedge rclock_in or posedge clear)
331 rclk_wgrey_addr <= #`FF_DELAY 0 ;
333 rclk_wgrey_addr <= #`FF_DELAY rclk_sync_wgrey_addr ;
336 assign almost_empty = (rgrey_next == rclk_wgrey_addr) ;
337 assign empty = (rgrey_addr == rclk_wgrey_addr) ;