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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_3/] [rtl/] [verilog/] [fifo_control.v] - Blame information for rev 33

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

powered by: WebSVN 2.1.0

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