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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_3/] [rtl/] [verilog/] [wbw_fifo_control.v] - Blame information for rev 58

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 58 mihad
// Revision 1.3  2002/02/01 15:25:14  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:30  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:47  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 21 mihad
`include "pci_constants.v"
59
// synopsys translate_off
60 6 mihad
`include "timescale.v"
61 21 mihad
// synopsys translate_on
62
 
63 2 mihad
module WBW_FIFO_CONTROL
64
(
65 21 mihad
    rclock_in,
66
    wclock_in,
67
    renable_in,
68
    wenable_in,
69
    reset_in,
70 58 mihad
//    flush_in, // not used
71 21 mihad
    almost_full_out,
72
    full_out,
73
    empty_out,
74
    waddr_out,
75
    raddr_out,
76
    rallow_out,
77 2 mihad
    wallow_out
78
);
79
 
80
parameter ADDR_LENGTH = 7 ;
81
 
82
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
83
input  rclock_in, wclock_in;
84
 
85
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
86
//                 write address changes on rising edge of wclock_in when writes are allowed
87
input  renable_in, wenable_in ;
88
 
89
// reset input
90
input  reset_in;
91
 
92
// flush input
93 58 mihad
// input flush_in ; // not used
94 2 mihad
 
95
// almost full and empy status outputs
96
output almost_full_out ;
97
 
98
// full and empty status outputs
99
output full_out, empty_out;
100
 
101
// read and write addresses outputs
102
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
103
 
104
// read and write allow outputs
105
output rallow_out, wallow_out ;
106
 
107
// read address register
108
reg [(ADDR_LENGTH - 1):0] raddr ;
109
 
110
// write address register
111
reg [(ADDR_LENGTH - 1):0] waddr;
112
assign waddr_out = waddr ;
113
 
114
// grey code registers
115
// grey code pipeline for write address
116
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current
117
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next
118
 
119
// next write gray address calculation - bitwise xor between address and shifted address
120
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
121
 
122
// grey code pipeline for read address
123
reg [(ADDR_LENGTH - 1):0] rgrey_minus2 ; // two before current
124
reg [(ADDR_LENGTH - 1):0] rgrey_minus1 ; // one before current
125
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
126
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
127
 
128
// next read gray address calculation - bitwise xor between address and shifted address
129
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
130
 
131
// FFs for registered empty and full flags
132
reg empty ;
133
reg full ;
134
 
135
// almost_full tag
136
reg almost_full ;
137
 
138
// write allow wire - writes are allowed when fifo is not full
139
wire wallow = wenable_in && ~full ;
140
 
141
// write allow output assignment
142
assign wallow_out = wallow && ~full ;
143
 
144
// read allow wire
145
wire rallow ;
146
 
147
// full output assignment
148
assign full_out  = full ;
149
 
150
// almost full output assignment
151
assign almost_full_out  = almost_full && ~full ;
152
 
153
// clear generation for FFs and registers
154 58 mihad
wire clear = reset_in /*|| flush_in*/ ;     // flush not used
155 2 mihad
 
156 21 mihad
reg wclock_nempty_detect ;
157 58 mihad
always@(posedge clear or posedge wclock_in)
158 21 mihad
begin
159 58 mihad
    if (clear)
160 21 mihad
        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
// 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 2 mihad
 
175 21 mihad
// empty output is actual empty + 1 read clock cycle ( stretched empty )
176
assign empty_out = empty || stretched_empty ;
177 2 mihad
 
178 21 mihad
//rallow generation
179
assign rallow = renable_in && ~empty && ~stretched_empty ; // reads allowed if read enable is high and FIFO is not empty
180 2 mihad
 
181 21 mihad
// rallow output assignment
182
assign rallow_out = rallow ;
183 2 mihad
 
184 21 mihad
// 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 2 mihad
 
188 21 mihad
// 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 2 mihad
 
192 21 mihad
always@(posedge rclock_in or posedge clear)
193
begin
194
    if (clear)
195 2 mihad
    begin
196 21 mihad
        // initial value is important - raddr initial value is 4, so this one is 5
197
        raddr_plus_one <= #`FF_DELAY 5 ;
198 2 mihad
    end
199 21 mihad
    else if (rallow)
200
        raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
201
end
202 2 mihad
 
203 21 mihad
// 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 4
208
    raddr <= #`FF_DELAY 4 ;
209
    else if (rallow)
210
        raddr <= #`FF_DELAY raddr_plus_one ;
211
end
212 2 mihad
 
213
/*-----------------------------------------------------------------------------------------------
214
Read address control consists of Read address counter and Grey Address pipeline
215 21 mihad
There are 4 Grey addresses:
216 2 mihad
    - rgrey_minus2 is Grey Code of address two before current address
217
    - rgrey_minus1 is Grey Code of address one before current address
218
    - rgrey_addr is Grey Code of current read address
219
    - rgrey_next is Grey Code of next read address
220
--------------------------------------------------------------------------------------------------*/
221
 
222
// grey code register for two before read address
223
always@(posedge rclock_in or posedge clear)
224
begin
225
        if (clear)
226
    begin
227 21 mihad
        // initial value is 0
228
        rgrey_minus2 <= #`FF_DELAY 0 ;
229 2 mihad
    end
230 21 mihad
    else
231
    if (rallow)
232
        rgrey_minus2 <= #`FF_DELAY rgrey_minus1 ;
233 2 mihad
end
234
 
235
// grey code register for one before read address
236
always@(posedge rclock_in or posedge clear)
237
begin
238 21 mihad
    if (clear)
239 2 mihad
    begin
240 21 mihad
        // initial value is 1
241
        rgrey_minus1 <= #`FF_DELAY 1 ;
242 2 mihad
    end
243 21 mihad
    else
244
    if (rallow)
245
        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
246 2 mihad
end
247
 
248
// grey code register for read address - represents current Read Address
249
always@(posedge rclock_in or posedge clear)
250
begin
251 21 mihad
    if (clear)
252 2 mihad
    begin
253 21 mihad
        // initial value is 3 = ...00011
254
        rgrey_addr <= #`FF_DELAY 3 ;
255 2 mihad
    end
256 21 mihad
    else
257
    if (rallow)
258
        rgrey_addr <= #`FF_DELAY rgrey_next ;
259 2 mihad
end
260
 
261 21 mihad
// grey code register for next read address - represents Grey Code of next read address
262 2 mihad
always@(posedge rclock_in or posedge clear)
263
begin
264 21 mihad
    if (clear)
265 2 mihad
    begin
266 21 mihad
        // initial value is 2 = ...00010
267
        rgrey_next <= #`FF_DELAY 2 ;
268 2 mihad
    end
269 21 mihad
    else
270
    if (rallow)
271
        rgrey_next <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
272 2 mihad
end
273
 
274
/*--------------------------------------------------------------------------------------------
275
Write address control consists of write address counter and two Grey Code Registers:
276
    - wgrey_addr represents current Grey Coded write address
277
    - wgrey_next represents Grey Coded next write address
278
----------------------------------------------------------------------------------------------*/
279
// grey code register for write address
280
always@(posedge wclock_in or posedge clear)
281
begin
282 21 mihad
    if (clear)
283 2 mihad
    begin
284 21 mihad
        // initial value is 3 = ....011
285
        wgrey_addr <= #`FF_DELAY 3 ;
286 2 mihad
    end
287 21 mihad
    else
288
    if (wallow)
289
        wgrey_addr <= #`FF_DELAY wgrey_next ;
290 2 mihad
end
291
 
292
// grey code register for next write address
293
always@(posedge wclock_in or posedge clear)
294
begin
295 21 mihad
    if (clear)
296 2 mihad
    begin
297 21 mihad
        // initial value is 2 = ...010
298
        wgrey_next <= #`FF_DELAY 2 ;
299 2 mihad
    end
300 21 mihad
    else
301
    if (wallow)
302
        wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
303 2 mihad
end
304
 
305 21 mihad
// write address counter - nothing special - initial value is important though
306 2 mihad
always@(posedge wclock_in or posedge clear)
307
begin
308 21 mihad
    if (clear)
309
        // initial value 4
310
        waddr <= #`FF_DELAY 4 ;
311
    else
312
    if (wallow)
313
        waddr <= #`FF_DELAY waddr + 1'b1 ;
314 2 mihad
end
315
 
316
/*------------------------------------------------------------------------------------------------------------------------------
317
Registered full control:
318
registered full is set on rising edge of wclock_in when there is one free location in and another written to fifo
319
It's kept high until something is read from FIFO, which is registered on
320
next rising write clock edge.
321
 
322
Registered almost full control:
323
Almost full flag is set on rising wclock_in edge when there are two unused locations left in and another written to fifo.
324
It is set until something is read/written from/to fifo
325
--------------------------------------------------------------------------------------------------------------------------------*/
326
//combinatorial input to Registered full FlipFlop
327
wire reg_full = wallow && (wgrey_next == rgrey_minus1) || (wgrey_next == rgrey_addr) ;
328
 
329
always@(posedge wclock_in or posedge clear)
330
begin
331
        if (clear)
332
                full <= #`FF_DELAY 1'b0 ;
333
        else
334
                full <= #`FF_DELAY reg_full ;
335
end
336
 
337
// input for almost full latch
338
wire reg_almost_full_in = wallow && (wgrey_next == rgrey_minus2) || (wgrey_next == rgrey_minus1) ;
339
 
340
always@(posedge clear or posedge wclock_in)
341
begin
342
    if (clear)
343
        almost_full <= #`FF_DELAY 1'b0 ;
344
    else
345
        almost_full <= #`FF_DELAY reg_almost_full_in ;
346
end
347
 
348
/*------------------------------------------------------------------------------------------------------------------------------
349
Registered empty control:
350
registered empty is set on rising edge of rclock_in when one location is used and read from fifo. It's kept high
351
until something is written to the fifo, which is registered on the next clock edge.
352
 
353
Registered almost empty control:
354
Almost empty is set on rising edge of rclock_in when two locations are used and one read. It's kept set until something
355
is read/written from/to fifo.
356
--------------------------------------------------------------------------------------------------------------------------------*/
357
// combinatorial input for registered emty FlipFlop
358
wire comb_almost_empty = (rgrey_next == wgrey_addr) ;
359
wire comb_empty        = (rgrey_addr == wgrey_addr) ;
360
wire reg_empty         = renable_in && comb_almost_empty  || comb_empty ;
361
 
362
always@(posedge rclock_in or posedge clear)
363
begin
364
    if (clear)
365
        empty <= #`FF_DELAY 1'b1 ;
366
        else
367
        empty <= #`FF_DELAY reg_empty ;
368
end
369
 
370
endmodule

powered by: WebSVN 2.1.0

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