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

Subversion Repositories pci

[/] [pci/] [tags/] [working_demo/] [old_stuff/] [wb_slave/] [test_bench/] [fifo_control.v] - Blame information for rev 8

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
////      - mihad@opencores.org                                   ////
10
////      - Miha Dolenc                                           ////
11
////                                                              ////
12
////  All additional information is avaliable in the README.pdf   ////
13
////  file.                                                       ////
14
////                                                              ////
15
////                                                              ////
16
//////////////////////////////////////////////////////////////////////
17
////                                                              ////
18
//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org          ////
19
////                                                              ////
20
//// This source file may be used and distributed without         ////
21
//// restriction provided that this copyright statement is not    ////
22
//// removed from the file and that any derivative work contains  ////
23
//// the original copyright notice and the associated disclaimer. ////
24
////                                                              ////
25
//// This source file is free software; you can redistribute it   ////
26
//// and/or modify it under the terms of the GNU Lesser General   ////
27
//// Public License as published by the Free Software Foundation; ////
28
//// either version 2.1 of the License, or (at your option) any   ////
29
//// later version.                                               ////
30
////                                                              ////
31
//// This source is distributed in the hope that it will be       ////
32
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
33
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
34
//// PURPOSE.  See the GNU Lesser General Public License for more ////
35
//// details.                                                     ////
36
////                                                              ////
37
//// You should have received a copy of the GNU Lesser General    ////
38
//// Public License along with this source; if not, download it   ////
39
//// from http://www.opencores.org/lgpl.shtml                     ////
40
////                                                              ////
41
//////////////////////////////////////////////////////////////////////
42
//
43
// CVS Revision History
44
//
45
// $Log: not supported by cvs2svn $
46
// Revision 1.3  2001/07/30 11:09:37  mihad
47
// no message
48
//
49
//
50
 
51
/* FIFO_CONTROL module provides read/write address and status generation for
52
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
53
`include "constants.v"
54
`ifdef FPGA
55
    // fifo design in FPGA will be synchronous
56
    `ifdef SYNCHRONOUS
57
    `else
58
        `define SYNCHRONOUS
59
    `endif
60
`endif
61
module FIFO_CONTROL(rclock_in, wclock_in, renable_in,
62
                    wenable_in, reset_in, flush_in,
63
                    almost_full_out, full_out,
64
                    almost_empty_out, empty_out,
65
                    waddr_out, raddr_out, rallow_out, wallow_out);
66
 
67
parameter ADDR_LENGTH = 7 ;
68
 
69
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
70
input  rclock_in, wclock_in;
71
 
72
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
73
//                 write address changes on rising edge of wclock_in when writes are allowed
74
input  renable_in, wenable_in;
75
 
76
// reset input
77
input  reset_in;
78
 
79
// flush input
80
input flush_in ;
81
 
82
// almost full and empy status outputs
83
output almost_full_out, almost_empty_out;
84
 
85
// full and empty status outputs
86
output full_out, empty_out;
87
 
88
// read and write addresses outputs
89
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
90
 
91
// read and write allow outputs
92
output rallow_out, wallow_out ;
93
 
94
// read address register
95
reg [(ADDR_LENGTH - 1):0] raddr ;
96
 
97
// write address register
98
reg [(ADDR_LENGTH - 1):0] waddr;
99
assign waddr_out = waddr ;
100
 
101
// grey code registers
102
// grey code pipeline for write address
103
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current
104
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next
105
 
106
// next write gray address calculation - bitwise xor between address and shifted address
107
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
108
 
109
// grey code pipeline for read address
110
reg [(ADDR_LENGTH - 1):0] rgrey_minus1 ; // one before current
111
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
112
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
113
 
114
// next read gray address calculation - bitwise xor between address and shifted address
115
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
116
 
117
// FFs for registered empty and full flags
118
reg empty ;
119
reg full ;
120
 
121
// almost_empty and almost_full tag - implemented as latches
122
reg almost_empty ;
123
reg almost_full ;
124
 
125
// write allow wire - writes are allowed when fifo is not full
126
wire wallow = wenable_in && ~full ;
127
 
128
// write allow output assignment
129
assign wallow_out = wallow ;
130
 
131
// read allow wire
132
wire rallow ;
133
 
134
// full output assignment
135
assign full_out  = full ;
136
 
137
// almost full output assignment
138
assign almost_full_out  = almost_full && ~full ;
139
 
140
// clear generation for FFs and registers
141
wire clear = reset_in || flush_in ;
142
 
143
`ifdef SYNCHRONOUS
144
 
145
    reg wclock_nempty_detect ;
146
    always@(posedge reset_in or posedge wclock_in)
147
    begin
148
        if (reset_in)
149
            wclock_nempty_detect <= #`FF_DELAY 1'b0 ;
150
        else
151
            wclock_nempty_detect <= #`FF_DELAY (rgrey_addr != wgrey_addr) ;
152
    end
153
 
154
    // special synchronizing mechanism for different implementations - in synchronous imp., empty is prolonged for 1 clock edge if no write clock comes after initial write
155
    reg stretched_empty ;
156
    always@(posedge rclock_in or posedge clear)
157
    begin
158
        if(clear)
159
            stretched_empty <= #`FF_DELAY 1'b1 ;
160
        else
161
            stretched_empty <= #`FF_DELAY empty && ~wclock_nempty_detect ;
162
    end
163
 
164
    // empty output is actual empty + 1 read clock cycle ( stretched empty )
165
    assign empty_out = empty  || stretched_empty ;
166
 
167
    //rallow generation    
168
    assign rallow = renable_in && ~empty && ~stretched_empty ; // reads allowed if read enable is high and FIFO is not empty
169
 
170
    // rallow output assignment
171
    assign rallow_out = rallow ;
172
 
173
    // almost empty output assignment
174
    assign almost_empty_out = almost_empty && ~empty && ~stretched_empty ;
175
 
176
    // at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
177
    // when FIFO is empty, this register provides actual read address, so first location can be read
178
    reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
179
 
180
    // address output mux - when FIFO is empty, current actual address is driven out, when it is non - empty next address is driven out
181
    // done for zero wait state burst
182
    assign raddr_out = empty_out ? raddr : raddr_plus_one ;
183
 
184
    // enable for this register
185
    wire raddr_plus_one_en = rallow ;
186
    always@(posedge rclock_in or posedge clear)
187
    begin
188
        if (clear)
189
        begin
190
            raddr_plus_one[(ADDR_LENGTH - 1):1] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0}} ;
191
            raddr_plus_one[0] <= #`FF_DELAY 1'b1 ;
192
        end
193
        else if (raddr_plus_one_en)
194
            raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
195
    end
196
 
197
    // raddr is filled with raddr_plus_one on rising read clock edge when rallow is high
198
    always@(posedge rclock_in or posedge clear)
199
    begin
200
            if (clear)
201
            // initial value is 000......00
202
                    raddr <= #`FF_DELAY { ADDR_LENGTH{1'b0}} ;
203
            else if (rallow)
204
                raddr <= #`FF_DELAY raddr_plus_one ;
205
    end
206
 
207
`else
208
    // asynchronous RAM storage for FIFOs - somewhat simpler control logic
209
    //rallow generation    
210
    assign rallow = renable_in && ~empty ;
211
 
212
    assign rallow_out = rallow;
213
 
214
    assign almost_empty_out = almost_empty && ~empty ;
215
 
216
    // read address counter - normal counter, nothing to it
217
    // for asynchronous implementation, there is no need for pointing to next address.
218
    // On clock edge that read is performed, read address will change and on the next clock edge
219
    // asynchronous memory will provide next data
220
    always@(posedge rclock_in or posedge clear)
221
    begin
222
            if (clear)
223
            // initial value is 000......00
224
                    raddr <= #`FF_DELAY { ADDR_LENGTH{1'b0}} ;
225
            else if (rallow)
226
                    raddr <= #`FF_DELAY raddr + 1'b1 ;
227
    end
228
 
229
    assign empty_out = empty ;
230
    assign raddr_out = raddr ;
231
`endif
232
 
233
/*-----------------------------------------------------------------------------------------------
234
Read address control consists of Read address counter and Grey Address pipeline
235
There are 3 Grey addresses:
236
    - rgrey_minus1 is Grey Code of address one before current address
237
    - rgrey_addr is Grey Code of current read address
238
    - rgrey_next is Grey Code of next read address
239
--------------------------------------------------------------------------------------------------*/
240
 
241
// grey code register for one before read address
242
always@(posedge rclock_in or posedge clear)
243
begin
244
        if (clear)
245
    begin
246
        // initial value is 100......011
247
                rgrey_minus1[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
248
        rgrey_minus1[(ADDR_LENGTH  - 2):2] <= #`FF_DELAY { (ADDR_LENGTH  - 3){1'b0} } ;
249
        rgrey_minus1[1:0] <= #`FF_DELAY 2'b11 ;
250
    end
251
        else
252
                if (rallow)
253
                        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
254
end
255
 
256
// grey code register for read address - represents current Read Address
257
always@(posedge rclock_in or posedge clear)
258
begin
259
        if (clear)
260
    begin
261
        // initial value is 100.......01
262
                rgrey_addr[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
263
        rgrey_addr[(ADDR_LENGTH - 2):1] <= #`FF_DELAY { (ADDR_LENGTH - 2){1'b0} } ;
264
        rgrey_addr[0] <= #`FF_DELAY 1'b1 ;
265
    end
266
        else
267
                if (rallow)
268
                        rgrey_addr <= #`FF_DELAY rgrey_next ;
269
end
270
 
271
// grey code register for next read address - represents Grey Code of next read address    
272
always@(posedge rclock_in or posedge clear)
273
begin
274
        if (clear)
275
    begin
276
        // initial value is 100......00
277
                rgrey_next[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
278
        rgrey_next[(ADDR_LENGTH - 2):0] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0} } ;
279
    end
280
        else
281
                if (rallow)
282
            rgrey_next <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
283
end
284
 
285
/*--------------------------------------------------------------------------------------------
286
Write address control consists of write address counter and two Grey Code Registers:
287
    - wgrey_addr represents current Grey Coded write address
288
    - wgrey_next represents Grey Coded next write address
289
----------------------------------------------------------------------------------------------*/
290
// grey code register for write address
291
always@(posedge wclock_in or posedge clear)
292
begin
293
        if (clear)
294
    begin
295
        // initial value is 100.....001
296
        wgrey_addr[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
297
        wgrey_addr[(ADDR_LENGTH - 2):1] <= #`FF_DELAY { (ADDR_LENGTH - 2){1'b0} } ;
298
        wgrey_addr[0] <= #`FF_DELAY 1'b1 ;
299
    end
300
        else
301
                if (wallow)
302
                        wgrey_addr <= #`FF_DELAY wgrey_next ;
303
end
304
 
305
// grey code register for next write address
306
always@(posedge wclock_in or posedge clear)
307
begin
308
        if (clear)
309
    begin
310
        // initial value is 100......00
311
                wgrey_next[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
312
        wgrey_next[(ADDR_LENGTH - 2):0] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0} } ;
313
    end
314
        else
315
        if (wallow)
316
            wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
317
end
318
 
319
// write address counter - nothing special
320
always@(posedge wclock_in or posedge clear)
321
begin
322
        if (clear)
323
        // initial value 00.........00
324
                waddr <= #`FF_DELAY { (ADDR_LENGTH){1'b0} } ;
325
        else
326
                if (wallow)
327
                        waddr <= #`FF_DELAY waddr + 1'b1 ;
328
end
329
 
330
/*------------------------------------------------------------------------------------------------------------------------------
331
Registered full control:
332
registered full is set on rising edge of wclock_in, when almost full and wallow are high.
333
It's kept high until something is read from FIFO, which is registered on
334
next rising write clock edge.
335
 
336
Latched almost full control:
337
Almost full flag is latched whenever writes are not allowed ( nothing is beeing written to the FIFO ) or when
338
write clock is high - that way almost full can still go low if there is half a cycle left between a read and write operation
339
--------------------------------------------------------------------------------------------------------------------------------*/
340
//combinatorial input to Registered full FlipFlop
341
wire reg_full = (wallow && almost_full) || (wgrey_next == rgrey_addr) ;
342
 
343
always@(posedge wclock_in or posedge clear)
344
begin
345
        if (clear)
346
                full <= #`FF_DELAY 1'b0 ;
347
        else
348
                full <= #`FF_DELAY reg_full ;
349
end
350
 
351
// input for almost full latch
352
wire latch_almost_full_in = (wgrey_next == rgrey_minus1) ;
353
 
354
always@(clear or latch_almost_full_in or wallow or wclock_in)
355
begin
356
    if (clear)
357
        almost_full <= #`FF_DELAY 1'b0 ;
358
    else
359
    if ( wclock_in || ~wallow )
360
        almost_full <= #`FF_DELAY latch_almost_full_in ;
361
end
362
 
363
/*------------------------------------------------------------------------------------------------------------------------------
364
Registered empty control:
365
registered empty is set on rising edge of rclock_in,
366
when almost empty is high, and rallow is high. It's kept high until something is written to FIFO, which is registered on
367
the next read clock.
368
 
369
Latched almost empty control:
370
Almost empty is latched whenever reads are not allowed or read clock is high.
371
This way almost empty can still go down if there is at least half of read clock cycle left between write and next read
372
--------------------------------------------------------------------------------------------------------------------------------*/
373
// combinatorial input for registered emty FlipFlop
374
wire reg_empty = (rallow && almost_empty) || (rgrey_addr == wgrey_addr) ;
375
 
376
always@(posedge rclock_in or posedge clear)
377
begin
378
    if (clear)
379
        empty <= #`FF_DELAY 1'b1 ;
380
        else
381
        empty <= #`FF_DELAY reg_empty ;
382
end
383
 
384
// input for almost empty latch
385
wire latch_almost_empty = (rgrey_next == wgrey_addr) ;
386
always@(clear or latch_almost_empty or rclock_in or rallow)
387
begin
388
    if (clear)
389
        almost_empty <= #`FF_DELAY 1'b0 ;
390
    else
391
        if (rclock_in || ~rallow)
392
            almost_empty <= #`FF_DELAY latch_almost_empty ;
393
end
394
 
395
endmodule

powered by: WebSVN 2.1.0

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