]> git.zerfleddert.de Git - raggedstone/blob - ethernet/source/pci/pci_pcir_fifo_control.v
progress
[raggedstone] / ethernet / source / pci / pci_pcir_fifo_control.v
1 //////////////////////////////////////////////////////////////////////
2 //// ////
3 //// File name "fifo_control.v" ////
4 //// ////
5 //// This file is part of the "PCI bridge" project ////
6 //// http://www.opencores.org/cores/pci/ ////
7 //// ////
8 //// Author(s): ////
9 //// - Miha Dolenc (mihad@opencores.org) ////
10 //// ////
11 //// All additional information is avaliable in the README ////
12 //// file. ////
13 //// ////
14 //// ////
15 //////////////////////////////////////////////////////////////////////
16 //// ////
17 //// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org ////
18 //// ////
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. ////
23 //// ////
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. ////
29 //// ////
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 ////
34 //// details. ////
35 //// ////
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 ////
39 //// ////
40 //////////////////////////////////////////////////////////////////////
41 //
42 // CVS Revision History
43 //
44 // $Log: pci_pcir_fifo_control.v,v $
45 // Revision 1.1 2007-03-20 17:50:56 sithglan
46 // add shit
47 //
48 // Revision 1.4 2003/08/14 13:06:03 simons
49 // synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated.
50 //
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.
54 //
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.
59 //
60 // Revision 1.1 2003/01/27 16:49:31 mihad
61 // Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed.
62 //
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.
67 //
68 // Revision 1.6 2002/09/30 16:03:04 mihad
69 // Added meta flop module for easier meta stable FF identification during synthesis
70 //
71 // Revision 1.5 2002/09/25 15:53:52 mihad
72 // Removed all logic from asynchronous reset network
73 //
74 // Revision 1.4 2002/03/05 11:53:47 mihad
75 // Added some testcases, removed un-needed fifo signals
76 //
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
79 //
80 // Revision 1.2 2001/10/05 08:14:28 mihad
81 // Updated all files with inclusion of timescale file for simulation purposes.
82 //
83 // Revision 1.1.1.1 2001/10/02 15:33:46 mihad
84 // New project directory structure
85 //
86 //
87
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 */
90
91 `include "pci_constants.v"
92
93 // synopsys translate_off
94 `include "timescale.v"
95 // synopsys translate_on
96
97 module pci_pcir_fifo_control
98 (
99 rclock_in,
100 wclock_in,
101 renable_in,
102 wenable_in,
103 reset_in,
104 flush_in,
105 full_out,
106 almost_empty_out,
107 empty_out,
108 waddr_out,
109 raddr_out,
110 rallow_out,
111 wallow_out
112 );
113
114 // address length parameter - depends on fifo depth
115 parameter ADDR_LENGTH = 7 ;
116
117 // independent clock inputs - rclock_in = read clock, wclock_in = write clock
118 input rclock_in, wclock_in;
119
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;
123
124 // reset input
125 input reset_in;
126
127 // flush input
128 input flush_in ;
129
130 // almost empy status output
131 output almost_empty_out;
132
133 // full and empty status outputs
134 output full_out, empty_out;
135
136 // read and write addresses outputs
137 output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
138
139 // read and write allow outputs
140 output rallow_out, wallow_out ;
141
142 // read address register
143 reg [(ADDR_LENGTH - 1):0] raddr ;
144
145 // write address register
146 reg [(ADDR_LENGTH - 1):0] waddr;
147 assign waddr_out = waddr ;
148
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
153
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] ;
156
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
160
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] ;
163
164 // FFs for registered empty and full flags
165 wire empty ;
166 wire full ;
167
168 // almost_empty tag
169 wire almost_empty ;
170
171 // write allow wire - writes are allowed when fifo is not full
172 wire wallow = wenable_in && !full ;
173
174 // write allow output assignment
175 assign wallow_out = wallow ;
176
177 // read allow wire
178 wire rallow ;
179
180 // full output assignment
181 assign full_out = full ;
182
183 // clear generation for FFs and registers
184 wire clear = reset_in /*|| flush_in*/ ; // flush changed to synchronous operation
185
186 assign empty_out = empty ;
187
188 //rallow generation
189 assign rallow = renable_in && !empty ; // reads allowed if read enable is high and FIFO is not empty
190
191 // rallow output assignment
192 assign rallow_out = rallow ;
193
194 // almost empty output assignment
195 assign almost_empty_out = almost_empty ;
196
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 ;
200
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 ;
205
206 always@(posedge rclock_in or posedge clear)
207 begin
208 if (clear)
209 begin
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 ;
213 end
214 else if (flush_in)
215 begin
216 raddr_plus_one <= #`FF_DELAY waddr + 1'b1 ;
217 raddr <= #`FF_DELAY waddr ;
218 end
219 else if (rallow)
220 begin
221 raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
222 raddr <= #`FF_DELAY raddr_plus_one ;
223 end
224 end
225
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)
234 begin
235 if (clear)
236 begin
237 rgrey_addr <= #1 0 ;
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
239 end
240 else if (flush_in)
241 begin
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 ;
246 end
247 else if (rallow)
248 begin
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} ;
252 end
253 end
254
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)
262 begin
263 if (clear)
264 begin
265 wgrey_addr <= #1 0 ;
266 wgrey_next <= #`FF_DELAY 1 ;
267 end
268 else
269 if (wallow)
270 begin
271 wgrey_addr <= #1 wgrey_next ;
272 wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
273 end
274 end
275
276 // write address binary counter - nothing special except initial value
277 always@(posedge wclock_in or posedge clear)
278 begin
279 if (clear)
280 // initial value 2
281 waddr <= #`FF_DELAY 2 ;
282 else
283 if (wallow)
284 waddr <= #`FF_DELAY waddr + 1'b1 ;
285 end
286
287 /*------------------------------------------------------------------------------------------------------------------------------
288 Full control:
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
295 (
296 .data_in (rgrey_addr),
297 .clk_out (wclock_in),
298 .sync_data_out (wclk_sync_rgrey_addr),
299 .async_reset (clear)
300 ) ;
301
302 always@(posedge wclock_in or posedge clear)
303 begin
304 if (clear)
305 wclk_rgrey_addr <= #`FF_DELAY 0 ;
306 else
307 wclk_rgrey_addr <= #`FF_DELAY wclk_sync_rgrey_addr ;
308 end
309
310 assign full = (wgrey_next == wclk_rgrey_addr) ;
311
312 /*------------------------------------------------------------------------------------------------------------------------------
313 Empty control:
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
321 (
322 .data_in (wgrey_addr),
323 .clk_out (rclock_in),
324 .sync_data_out (rclk_sync_wgrey_addr),
325 .async_reset (clear)
326 ) ;
327
328 always@(posedge rclock_in or posedge clear)
329 begin
330 if (clear)
331 rclk_wgrey_addr <= #`FF_DELAY 0 ;
332 else
333 rclk_wgrey_addr <= #`FF_DELAY rclk_sync_wgrey_addr ;
334 end
335
336 assign almost_empty = (rgrey_next == rclk_wgrey_addr) ;
337 assign empty = (rgrey_addr == rclk_wgrey_addr) ;
338
339 endmodule
Impressum, Datenschutz