OpenCores
URL https://opencores.org/ocsvn/pci/pci/trunk

Subversion Repositories pci

[/] [pci/] [tags/] [rel_00/] [rtl/] [verilog/] [fifo_control.v] - Blame information for rev 21

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 mihad
//////////////////////////////////////////////////////////////////////
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: not supported by cvs2svn $
45 21 mihad
// Revision 1.2  2001/10/05 08:14:28  mihad
46
// Updated all files with inclusion of timescale file for simulation purposes.
47
//
48 6 mihad
// Revision 1.1.1.1  2001/10/02 15:33:46  mihad
49
// New project directory structure
50 2 mihad
//
51 6 mihad
//
52 2 mihad
 
53
/* FIFO_CONTROL module provides read/write address and status generation for
54
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
55
 
56 21 mihad
`include "pci_constants.v"
57 6 mihad
 
58 21 mihad
// synopsys translate_off
59 6 mihad
`include "timescale.v"
60 21 mihad
// synopsys translate_on
61 6 mihad
 
62 2 mihad
module FIFO_CONTROL
63
(
64 21 mihad
    rclock_in,
65
    wclock_in,
66
    renable_in,
67
    wenable_in,
68
    reset_in,
69
    flush_in,
70
    almost_full_out,
71
    full_out,
72
    almost_empty_out,
73
    empty_out,
74
    waddr_out,
75
    raddr_out,
76
    rallow_out,
77 2 mihad
    wallow_out
78
);
79
 
80
// address length parameter - depends on fifo depth
81
parameter ADDR_LENGTH = 7 ;
82
 
83
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
84
input  rclock_in, wclock_in;
85
 
86
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
87
//                 write address changes on rising edge of wclock_in when writes are allowed
88
input  renable_in, wenable_in;
89
 
90
// reset input
91
input  reset_in;
92
 
93
// flush input
94
input flush_in ;
95
 
96
// almost full and empy status outputs
97
output almost_full_out, almost_empty_out;
98
 
99
// full and empty status outputs
100
output full_out, empty_out;
101
 
102
// read and write addresses outputs
103
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
104
 
105
// read and write allow outputs
106
output rallow_out, wallow_out ;
107
 
108
// read address register
109
reg [(ADDR_LENGTH - 1):0] raddr ;
110
 
111
// write address register
112
reg [(ADDR_LENGTH - 1):0] waddr;
113
assign waddr_out = waddr ;
114
 
115
// grey code registers
116
// grey code pipeline for write address
117
reg [(ADDR_LENGTH - 1):0] wgrey_minus1 ; // one before current grey coded write address
118
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current grey coded write address
119
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next grey coded write address
120
 
121
// next write gray address calculation - bitwise xor between address and shifted address
122
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
123
 
124
// grey code pipeline for read address
125
reg [(ADDR_LENGTH - 1):0] rgrey_minus2 ; // two before current
126
reg [(ADDR_LENGTH - 1):0] rgrey_minus1 ; // one before current
127
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
128
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
129
 
130
// next read gray address calculation - bitwise xor between address and shifted address
131
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
132
 
133
// FFs for registered empty and full flags
134
reg empty ;
135
reg full ;
136
 
137
// almost_empty and almost_full tag - implemented as latches
138
reg almost_empty ;
139
reg almost_full ;
140
 
141
// write allow wire - writes are allowed when fifo is not full
142
wire wallow = wenable_in && ~full ;
143
 
144
// write allow output assignment
145
assign wallow_out = wallow ;
146
 
147
// read allow wire
148
wire rallow ;
149
 
150
// full output assignment
151
assign full_out  = full ;
152
 
153
// almost full output assignment
154
assign almost_full_out  = almost_full && ~full ;
155
 
156
// clear generation for FFs and registers
157
wire clear = reset_in || flush_in ;
158
 
159 21 mihad
reg wclock_nempty_detect ;
160
always@(posedge reset_in or posedge wclock_in)
161
begin
162
    if (reset_in)
163
        wclock_nempty_detect <= #`FF_DELAY 1'b0 ;
164
    else
165
        wclock_nempty_detect <= #`FF_DELAY (rgrey_addr != wgrey_addr) ;
166
end
167 2 mihad
 
168 21 mihad
reg stretched_empty ;
169
always@(posedge rclock_in or posedge clear)
170
begin
171
    if(clear)
172
        stretched_empty <= #`FF_DELAY 1'b1 ;
173
    else
174
        stretched_empty <= #`FF_DELAY empty && ~wclock_nempty_detect ;
175
end
176 2 mihad
 
177 21 mihad
// empty output is actual empty + 1 read clock cycle ( stretched empty )
178
assign empty_out = empty || stretched_empty ;
179 2 mihad
 
180 21 mihad
//rallow generation
181
assign rallow = renable_in && ~empty && ~stretched_empty ; // reads allowed if read enable is high and FIFO is not empty
182 2 mihad
 
183 21 mihad
// rallow output assignment
184
assign rallow_out = rallow ;
185 2 mihad
 
186 21 mihad
// almost empty output assignment
187
assign almost_empty_out = almost_empty && ~empty && ~stretched_empty ;
188 2 mihad
 
189 21 mihad
// at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
190
// when FIFO is empty, this register provides actual read address, so first location can be read
191
reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
192 2 mihad
 
193 21 mihad
// 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
194
// next data immediately
195
// done for zero wait state burst operation
196
assign raddr_out = rallow ? raddr_plus_one : raddr ;
197 2 mihad
 
198 21 mihad
always@(posedge rclock_in or posedge clear)
199
begin
200
    if (clear)
201 2 mihad
    begin
202 21 mihad
        // initial value is 5 - one more than initial value of read address
203
        raddr_plus_one <= #`FF_DELAY 5 ;
204 2 mihad
    end
205 21 mihad
    else if (rallow)
206
        raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
207
end
208 2 mihad
 
209 21 mihad
// raddr is filled with raddr_plus_one on rising read clock edge when rallow is high
210
always@(posedge rclock_in or posedge clear)
211
begin
212
    if (clear)
213
        // initial value is 4
214
        raddr <= #`FF_DELAY 4 ;
215
    else if (rallow)
216
        raddr <= #`FF_DELAY raddr_plus_one ;
217
end
218 2 mihad
 
219
/*-----------------------------------------------------------------------------------------------
220
Read address control consists of Read address counter and Grey Address pipeline
221 21 mihad
There are 4 Grey addresses:
222 2 mihad
    - rgrey_minus2 is Grey Code of address two before current address
223
    - rgrey_minus1 is Grey Code of address one before current address
224
    - rgrey_addr is Grey Code of current read address
225
    - rgrey_next is Grey Code of next read address
226
--------------------------------------------------------------------------------------------------*/
227
// grey code register for two before read address
228
always@(posedge rclock_in or posedge clear)
229
begin
230 21 mihad
    if (clear)
231 2 mihad
    begin
232 21 mihad
        // initial value is 0
233
        rgrey_minus2 <= #`FF_DELAY 0 ;
234 2 mihad
    end
235 21 mihad
    else
236
    if (rallow)
237
        rgrey_minus2 <= #`FF_DELAY rgrey_minus1 ;
238 2 mihad
end
239
 
240
// grey code register for one before read address
241
always@(posedge rclock_in or posedge clear)
242
begin
243 21 mihad
    if (clear)
244 2 mihad
    begin
245 21 mihad
        // initial value is 1
246
        rgrey_minus1 <= #`FF_DELAY 1 ;
247 2 mihad
    end
248 21 mihad
    else
249
    if (rallow)
250
        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
251 2 mihad
end
252
 
253
// grey code register for read address - represents current Read Address
254
always@(posedge rclock_in or posedge clear)
255
begin
256 21 mihad
    if (clear)
257 2 mihad
    begin
258 21 mihad
        // initial value is 3
259
        rgrey_addr <= #`FF_DELAY 3 ;
260 2 mihad
    end
261 21 mihad
    else
262
    if (rallow)
263
        rgrey_addr <= #`FF_DELAY rgrey_next ;
264 2 mihad
end
265
 
266 21 mihad
// grey code register for next read address - represents Grey Code of next read address
267 2 mihad
always@(posedge rclock_in or posedge clear)
268
begin
269 21 mihad
    if (clear)
270 2 mihad
    begin
271 21 mihad
        // initial value is 2
272
        rgrey_next <= #`FF_DELAY 2 ;
273 2 mihad
    end
274 21 mihad
    else
275
    if (rallow)
276
        rgrey_next <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
277 2 mihad
end
278
 
279
/*--------------------------------------------------------------------------------------------
280
Write address control consists of write address counter and three Grey Code Registers:
281
    - wgrey_minus1 represents Grey Coded address of location one before current write address
282
    - wgrey_addr represents current Grey Coded write address
283
    - wgrey_next represents Grey Coded next write address
284
----------------------------------------------------------------------------------------------*/
285
// grey code register for one before write address
286
always@(posedge wclock_in or posedge clear)
287
begin
288 21 mihad
    if (clear)
289 2 mihad
    begin
290 21 mihad
        // initial value is 1
291
        wgrey_minus1 <= #`FF_DELAY 1 ;
292 2 mihad
    end
293 21 mihad
    else
294 2 mihad
    if (wallow)
295 21 mihad
        wgrey_minus1 <= #`FF_DELAY wgrey_addr ;
296 2 mihad
end
297
 
298
// grey code register for write address
299
always@(posedge wclock_in or posedge clear)
300
begin
301 21 mihad
    if (clear)
302 2 mihad
    begin
303 21 mihad
        // initial value is 3
304
        wgrey_addr <= #`FF_DELAY 3 ;
305 2 mihad
    end
306 21 mihad
    else
307 2 mihad
    if (wallow)
308 21 mihad
        wgrey_addr <= #`FF_DELAY wgrey_next ;
309 2 mihad
end
310
 
311
// grey code register for next write address
312
always@(posedge wclock_in or posedge clear)
313
begin
314 21 mihad
    if (clear)
315 2 mihad
    begin
316 21 mihad
        // initial value is 2
317
        wgrey_next <= #`FF_DELAY 2 ;
318 2 mihad
    end
319 21 mihad
    else
320 2 mihad
    if (wallow)
321
        wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
322
end
323
 
324 21 mihad
// write address counter - nothing special except initial value
325 2 mihad
always@(posedge wclock_in or posedge clear)
326
begin
327 21 mihad
    if (clear)
328
        // initial value 4
329
        waddr <= #`FF_DELAY 4 ;
330
    else
331
    if (wallow)
332
        waddr <= #`FF_DELAY waddr + 1'b1 ;
333 2 mihad
end
334
 
335
/*------------------------------------------------------------------------------------------------------------------------------
336
Registered full control:
337 21 mihad
registered full is set on rising edge of wclock_in, when fifo is almost full and something gets written to it.
338 2 mihad
It's kept high until something is read from FIFO, which is registered on next rising write clock edge.
339
 
340
Registered almost full control:
341
Almost full flag is set on rising write clock edge whenever two free locations are left in fifo and another entry is written to it.
342
It remains set if nothing is read/written from/to fifo. All operations are synchronized on write clock.
343
--------------------------------------------------------------------------------------------------------------------------------*/
344
wire comb_full          = wgrey_next == rgrey_addr ;
345
wire comb_almost_full   = wgrey_addr == rgrey_minus2 ;
346
wire comb_two_left      = wgrey_next == rgrey_minus2 ;
347
 
348
//combinatorial input to Registered full FlipFlop
349
wire reg_full = (wallow && comb_almost_full) || (comb_full) ;
350
 
351
always@(posedge wclock_in or posedge clear)
352
begin
353 21 mihad
    if (clear)
354
        full <= #`FF_DELAY 1'b0 ;
355
    else
356
        full <= #`FF_DELAY reg_full ;
357 2 mihad
end
358
 
359
// input for almost full flip flop
360
wire reg_almost_full_in = wallow && comb_two_left || comb_almost_full ;
361
 
362
always@(posedge clear or posedge wclock_in)
363
begin
364
    if (clear)
365
        almost_full <= #`FF_DELAY 1'b0 ;
366
    else
367
        almost_full <= #`FF_DELAY reg_almost_full_in ;
368
end
369
 
370
/*------------------------------------------------------------------------------------------------------------------------------
371
Registered empty control:
372
registered empty is set on rising edge of rclock_in when one location is occupied and read from it. It remains set until
373
something is written to fifo which is detected on next read clock edge.
374
 
375
Registered almost empty control:
376
Almost empty is set on rising clock edge of read clock when two locations are used in fifo and one of them is read from it.
377
It remains set until something is read/written from/to fifo. All operations are detected on rising edge of read clock.
378
--------------------------------------------------------------------------------------------------------------------------------*/
379
wire comb_almost_empty  = rgrey_next == wgrey_addr ;
380
wire comb_empty         = rgrey_addr == wgrey_addr ;
381
wire comb_two_used      = rgrey_next == wgrey_minus1 ;
382
 
383
// combinatorial input for registered emty FlipFlop
384
wire reg_empty = (rallow && comb_almost_empty) || comb_empty ;
385
 
386
always@(posedge rclock_in or posedge clear)
387
begin
388
    if (clear)
389
        empty <= #`FF_DELAY 1'b1 ;
390 21 mihad
    else
391 2 mihad
        empty <= #`FF_DELAY reg_empty ;
392
end
393
 
394
// input for almost empty flip flop
395
wire reg_almost_empty = rallow && comb_two_used || comb_almost_empty ;
396
always@(posedge clear or posedge rclock_in)
397
begin
398
    if (clear)
399
        almost_empty <= #`FF_DELAY 1'b0 ;
400
    else
401
        almost_empty <= #`FF_DELAY reg_almost_empty ;
402
end
403
 
404
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.