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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_00/] [rtl/] [verilog/] [wbw_fifo_control.v] - Blame information for rev 6

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

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